summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp')
-rw-r--r--contrib/gcc/cp/ChangeLog3913
-rw-r--r--contrib/gcc/cp/ChangeLog.14
-rw-r--r--contrib/gcc/cp/ChangeLog.24
-rw-r--r--contrib/gcc/cp/Make-lang.in82
-rw-r--r--contrib/gcc/cp/NEWS4
-rw-r--r--contrib/gcc/cp/call.c1810
-rw-r--r--contrib/gcc/cp/cfns.gperf108
-rw-r--r--contrib/gcc/cp/class.c2197
-rw-r--r--contrib/gcc/cp/config-lang.in2
-rw-r--r--contrib/gcc/cp/cp-lang.c207
-rw-r--r--contrib/gcc/cp/cp-tree.def66
-rw-r--r--contrib/gcc/cp/cp-tree.h1318
-rw-r--r--contrib/gcc/cp/cvt.c159
-rw-r--r--contrib/gcc/cp/decl.c3706
-rw-r--r--contrib/gcc/cp/decl.h8
-rw-r--r--contrib/gcc/cp/decl2.c1862
-rw-r--r--contrib/gcc/cp/dump.c30
-rw-r--r--contrib/gcc/cp/error.c290
-rw-r--r--contrib/gcc/cp/except.c173
-rw-r--r--contrib/gcc/cp/expr.c27
-rw-r--r--contrib/gcc/cp/friend.c50
-rw-r--r--contrib/gcc/cp/g++spec.c29
-rw-r--r--contrib/gcc/cp/init.c1259
-rw-r--r--contrib/gcc/cp/lang-options.h4
-rw-r--r--contrib/gcc/cp/lang-specs.h25
-rw-r--r--contrib/gcc/cp/lex.c294
-rw-r--r--contrib/gcc/cp/lex.h6
-rw-r--r--contrib/gcc/cp/mangle.c424
-rw-r--r--contrib/gcc/cp/method.c245
-rw-r--r--contrib/gcc/cp/operators.def4
-rw-r--r--contrib/gcc/cp/optimize.c34
-rw-r--r--contrib/gcc/cp/parse.y953
-rw-r--r--contrib/gcc/cp/pt.c1222
-rw-r--r--contrib/gcc/cp/ptree.c18
-rw-r--r--contrib/gcc/cp/repo.c25
-rw-r--r--contrib/gcc/cp/rtti.c87
-rw-r--r--contrib/gcc/cp/search.c635
-rw-r--r--contrib/gcc/cp/semantics.c512
-rw-r--r--contrib/gcc/cp/spew.c530
-rw-r--r--contrib/gcc/cp/tree.c341
-rw-r--r--contrib/gcc/cp/typeck.c1838
-rw-r--r--contrib/gcc/cp/typeck2.c280
42 files changed, 15061 insertions, 9724 deletions
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 2fd119a..58bd155 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,20 +1,1173 @@
-2003-02-05 Release Manager
+2003-07-09 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.2 Released.
+ PR c++/10032
+ * decl.c (cxx_init_decl_processing): With -pedantic, pedwarns are
+ still errors.
-2003-02-03 Mark Mitchell <mark@codesourcery.com>
+ PR c++/10527
+ * error.c (decl_to_string): Do not print default argument
+ expressions.
+
+2003-07-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10849
+ * decl2.c (handle_class_head_apparent_template): New function.
+ * cp-tree.h (handle_class_head_apparent_template): Add declaration.
+ * parse.y (class_head_defn): Use it.
+ * search.c (type_access_control): Revert my 2003-05-25 change.
+
+2003-07-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11236
+ * cvt.c (convert_to_void): Treat an overloaded function like
+ "((void) 0)" after issuing a diagnostic.
+
+ PR c++/11345
+ * search.c (lookup_base_r): Remove is_non_public and
+ within_current_scope parameters. Remove other dead code.
+ (lookup_base): Adjust call to lookup_base_r.
+ (adjust_result_of_qualified_name_lookup): Improve comment.
+ * semantics.c (finish_call_expr): Use maybe_dummy_object.
+
+2003-07-05 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11431
+ * typeck.c (build_static_cast): Check for reference conversions
+ earlier.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6949
+ * decl2.c (grokfield): Create TEMPLATE_DECLs for methods in local
+ classes.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (resolve_scoped_fn_name): Return error_mark_node for
+ erroneous cases.
+
+ PR c++/11137
+ * decl2.c (generate_ctor_or_dtor_function): Tolerate a
+ non-existant ssdf_decls array.
+ (finish_file): Call generator_ctor_or_dtor_function when there are
+ static constructors or destructors and no other static
+ initializations.
+
+ PR c++/11149
+ * call.c (resolve_scoped_fn_name): Check that the qualifying scope
+ is a class type.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9559
+ * decl2.c (grokfield): Do not build NOP_EXPRs around the
+ error_mark_node.
+
+2003-06-30 Giovanni Bajo <giovannibajo@libero.it>
+
+ * mangle.c (write_expression): Exit gracefully when trying to
+ mangle a CALL_EXPR.
+
+2003-06-30 Giovanni Bajo <giovannibajo@libero.it>
+
+ PR c++/11106
+ * error.c (dump_decl): Call dump_decl to dump the DECL_NAME for a
+ USING_DECL, instead of print_tree_identifier.
+
+2003-06-27 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10468
+ * pt.c (tsubst): Handle qualified TYPEOF_TYPEs correctly.
+
+ PR c++/10796
+ * decl.c (finish_enum): Implement DR377.
+
+ * decl.c (cp_finish_decl): Don't make variables with reference
+ type readonly while they are being initialized.
+
+2003-06-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11332
+ * typeck.c (build_static_cast): Avoid returning expressions with
+ reference type.
+
+2003-06-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10990
+ * search.c (lookup_base_r): Rely on accessible_p, rather than
+ trying to emulate that logic here.
+
+ PR c++/10931
+ * call.c (convert_like): Pass issue_conversion_warnings.
+ (convert_like_with_context): Likewise.
+ (convert_like_real): Add issue_conversion_warnings parameter.
+ (perform_direct_initialization_if_possible): New function.
+ * cp-tree.h (perform_direct_initialization_if_possible): Declare it.
+ * typeck.c (check_for_casting_away_constness): New function.
+ (build_static_cast): Rewrite.
- PR C++/7129
- * operators.def: Add <?= and >?=.
+2003-06-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/5754
+ * parse.y (structsp): Improve error handling of invalid nested
+ template classes.
+
+2003-06-23 Jakub Jelinek <jakub@redhat.com>
+
+ * mangle.c: Include ggc.h, gt-cp-mangle.h.
+ (mangle_conv_op_name_for_type): Use htab_create_ggc instead of
+ htab_create.
+ * config-lang.in (gtfiles): Add cp/mangle.c.
+ * Make-lang.in (gt-cp-mangle.h): Depend on s-gtype.
+ (cp/mangle.o): Depend on gt-cp-mangle.h.
+
+2003-06-23 Jakub Jelinek <jakub@redhat.com>
+
+ * mangle.c (hash_type): val is the TREE_LIST itself, not a pointer
+ to it.
+
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10784
+ * call.c (joust): Warn about choosing conversion sequence only if
+ -Wconversion.
-2003-01-28 Christian Cornelssen <ccorn@cs.tu-berlin.de>
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10864
+ * call.c (op_error): Tidy.
+ * error.c (dump_expr): Properly format 'T()' when T is an
+ aggregate type.
+
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10915
+ * decl.c (grok_op_properties): Warn possible confusing conversion
+ only if -Wconversion.
+
+2003-06-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10845
+ * pt.c (try_class_unification): Correct handling of member class
+ templates.
+
+2003-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10939
+ * Make-lang.in (decl.o): Depend on input.h.
+ * decl.c (input.h): Include it.
+ (cp_finish_decl): Revert previous change:
+ 2003-06-19 Mark Mitchell <mark@codesourcery.com>
+ * decl.c (cp_finish_decl): Remove support for RESULT_DECLs.
+ Don't check building_stmt_tree.
+ * pt.c (tsubst_decl): Do not try to substitute into non-dependent
+ functions.
+
+ PR c++/9649
+ * cp-tree.h (pushdecl_class_level): Change prototype.
+ (push_class_level_binding): Likewise.
+ * decl.c (add_binding): Reject duplicate static data members.
+ (pushdecl_class_level): Return a value indicating whether or not
+ the binding was valid.
+ (push_class_level_binding): Likewise.
+ * semantics.c (finish_member_declaration): Don't keep invalid
+ declarations.
+
+2003-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11041
+ * call.c (initialize_reference): Do not use cp_finish_decl to emit
+ temporary variables.
+ * cp-tree.h (static_aggregates): Declare.
+ (pushdecl_top_level_and_finish): Likewise.
+ * decl.c (pushdecl_top_level_1): New function.
+ (pushdecl_top_level): Use it.
+ (pushdecl_top_level_and_finish): New function.
+ (initialize_local_var): Remove redundant code.
+ (cp_finish_decl): Remove support for RESULT_DECLs. Don't check
+ building_stmt_tree.
+ * decl.h (static_aggregates): Remove.
+ * decl2.c (get_guard): Use pushdecl_top_level_and_finish.
+ * rtti.c (get_tinfo_decl): Use pushdecl_top_level_and_finish.
+ (tinfo_base_init): Likewise.
+
+2003-06-19 Matt Austern <austern@apple.com>
+
+ PR c++/11228
+ * init.c (build_zero_init): Assert that number of array elements
+ is an integer constant.
+ (build_default_init) Don't use build_zero_init for arrays with
+ variable number of elements.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ * mangle.c (mangle_conv_op_name_for_type): Correct sprintf format
+ string again.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ * mangle.c (mangle_conv_op_name_for_type): Correct sprintf format
+ string.
+
+2003-06-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/10929
+ * decl.c (grokfndecl): Don't mark a function inline for
+ -finline-functions if it isn't defined.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10712
+ * class.c (handle_using_decl): Robustify.
+
+ PR c++/11105
+ * cp-tree.h (DECL_CONV_FN_TYPE): New method.
+ * decl.c (lookup_name_real): Backport conversion operator code
+ from mainline.
+ * mangle.c (struct globals): Remove internal_mangling_p.
+ (write_unqualified_name): Use DECL_CONV_FN_TYPE.
+ (write_template_parm): Don't write out the level number.
+ (conv_type_names): New variable.
+ (hash_type): New function.
+ (compare_type): Likewise.
+ (mangle_conv_op_name_for_type): Don't try to mangle conversion
+ operator names.
+ * search.c (lookup_conversion_operator): New function.
+ (lookup_fnfields_1): Use it.
+
+2003-06-12 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10635
+ * typeck.c (build_c_cast): Check that the destination type is
+ complete.
+
+2003-06-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/10968
+ * pt.c (mark_decl_instantiated): Clear DECL_COMDAT.
+
+2003-06-09 Zack Weinberg <zack@codesourcery.com>
+
+ PR 8861
+ * mangle.c (write_real_cst): New function. Implement
+ ABI-compliant mangling of floating-point literals when
+ -fabi-version>=2; provide backward compatibility with 3.3 when
+ -fabi-version=1 (with warning). Clarify commentary.
+ (write_template_arg_literal): Use write_real_cst.
+
+2003-06-08 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/11039
+ * decl2.c (handle_class_head): Remove implicitness in typename
+ appeared as elaborated type specifier in declaration.
+
+2003-06-03 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10940
+ * pt.c (check_explicit_specialization): Check for 'static'
+ earlier.
+
+2003-05-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10956
+ * pt.c (instantiate_decl): Don't use full template arguments if
+ we are dealing with specializations.
+
+2003-05-29 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (ENABLE_CHECKING_SCOPES): New macro.
+ (binding_depth): Unconditionally define.
+ (is_class_level): Likewise.
+ (indent): Likewise. Take an indenting parameter.
+ (push_binding_level): Remove conditional definittion.
+ (pop_binding_level): Likewise.
+ (suspend_binding_level): Likewise.
+ (resume_binding_level): Likewise.
+ (pushlevel): Likewise.
+ (pushlevel_class): Likewise.
+ (poplevel_class): Likewise.
+ (pop_everything): Likewise.
+
+2003-05-27 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (global_scope_p): New macro.
+ (pop_binding_level): Use it.
+ (suspend_binding_level): Likewise.
+ (global_bindings_p): Likewise.
+ (print_other_binding_stack): Likewise.
+ (print_binding_stack): Likewise.
+ (maybe_push_to_top_level): Likewise.
+ (pushdecl_namespace_level): Likewise.
+ (start_decl): Likewise.
+ (cp_finish_decl): Likewise.
+ (start_function): Likewise.
+ (cxx_init_decl_processing): Don't refer to global_binding_level.
+ (global_binding_level): Remove.
+
+2003-05-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10849
+ * search.c (type_access_control): Don't check access when
+ processing_specialization.
+
+2003-05-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10682
+ * pt.c (instantiate_class_template): Use DECL_ARTIFICIAL to
+ check for implicitly created typedef to an enum.
+
+2003-05-20 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (free_binding_entry): Fix thinko.
+
+2003-05-19 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * cp-tree.h (struct binding_entry_s): New datatype.
+ (binding_table): Declare.
+ (binding_entry): Likewise.
+ (bt_foreach_proc): Likewise.
+ (binding_table_foreach): Likewise.
+ (binding_table_find): Likewise.
+ (cxx_remember_type_decls): Likewise.
+ (CLASSTYPE_TAGS): Remove.
+ (CLASSTYPE_NESTED_UDTS): New macro.
+ (struct lang_type_class): Remove tags field. Add nested_types.
+ * decl.c (ENTRY_INDEX): New macro.
+ (free_binding_entry): New free list.
+ (binding_entry_make): New function.
+ (binding_entry_free): Likewise.
+ (struct binding_table_s): New datatype.
+ (SCOPE_DEFAULT_HT_SIZE): New macro.
+ (CLASS_SCOPE_HT_SIZE): Likewise.
+ (NAMESPACE_ORDINARY_HT_SIZE): Likewise.
+ (NAMESPACE_STD_HT_SIZE): Likewise.
+ (GLOBAL_SCOPE_HT_SIZE): Likewise.
+ (binding_table_construct): New function.
+ (binding_table_free): Likewise.
+ (binding_table_new): Likewise.
+ (binding_table_expand): Likewise.
+ (binding_table_insert): Likewise.
+ (binding_table_find): Likewise.
+ (binding_table_find_anon_type): Likewise.
+ (binding_table_reverse_maybe_remap): Likewise.
+ (binding_table_remove_anonymous_types): Likewise.
+ (binding_table_foreach): Likewise.
+ (struct cp_binding_level): Remove tags field. Add type_decls.
+ (pop_binding_level): Free binding_entries if possible.
+ (kept_level_p): Tidy.
+ (poplevel): Remove unused variable tags.
+ (bt_print_entry): New function.
+ (print_binding_level): Use it.
+ (push_namespace): Construct binding table.
+ (maybe_process_template_type_declaration): Tidy.
+ (pushtag): Likewise.
+ (clear_anon_tags): Likewise.
+ (cxx_remember_type_decls): New function.
+ (lookup_tag): Tidy.
+ (lookup_tag_reverse): Likewise.
+ (cxx_init_decl_processing): Construct binding_table for the global
+ scope.
+ (store_parm_decls): Remove pointless code.
+ (gettags): Remove.
+ (storetags): Likewise.
+ * class.c (unreverse_member_declarations): Don't touch
+ CLASSTYPE_TAGS.
+ (pushclass): Remember CLASSTYPE_NESTED_UTDS.
+ * pt.c (instantiate_class_template): Remove reference to
+ CLASSTYPE_TAGS. Remeber CLASSTYPE_NESTED_UTDS.
+ (bt_instantiate_type_proc): New function.
+ (do_type_instantiation): Use it.
+ * search.c (lookup_field_r): Use binding_table_find.
+ * semantics.c (begin_class_definition): Remove reference to
+ CLASSTYPE_TAGS. Nullify CLASSTYPE_NESTED_UTDS.
+
+2003-05-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/5388
+ * call.c (conditional_conversion): Don't consider implicit
+ conversions if T2 is a base of T1.
+ * cp-tree.h (DERIVED_FROM_P, UNIQUELY_DERIVED_FROM_P): Make boolean.
+ (ACCESSIBLY_UNIQUELY_DERIVED_P, PUBLICLY_UNIQUELY_DERIVED_P): Likewise.
+
+ PR c++/10661
+ * pt.c (instantiate_class_template): Also instantiate our
+ enclosing class.
+
+2003-05-13 Release Manager
+
+ * GCC 3.3 Released.
+
+2003-05-02 Richard Henderson <rth@redhat.com>
+
+ PR c++/10570
+ * cfns.gperf: Comment out POSIX thread cancellation points,
+ plus abort and raise.
+ * cfns.h: Regenerate.
+
+2003-05-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (comdat_linkage): Don't externalize explicit
+ instantiations.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10551
+ * pt.c (mark_decl_instantiated): Defer all explicit instantiations
+ that have not yet been written out.
+
+ PR c++/10549
+ * class.c (layout_class_type): Mark overlong bitfields as having
+ the maximum size permitted by their type, after layout.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10527
+ * error.c (dump_expr): Correctly handling of NEW_EXPR.4
+
+2003-04-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * lang-options.h: Fix typo.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10515
+ * cp-tree.h (lookup_field_1): Declare it.
+ * search.c (lookup_field_1): Make it public.
+ * decl.c (reshape_init): Handle designated initializers.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Further tweak support for systems
+ without weak symbols.
+
+2003-04-27 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Fix thinko in last patch.
+
+ PR c++/10506
+ * method.c (use_thunk): Decrement immediate_size_expand.
+
+ PR c++/10503
+ * cp-tree.h (DECL_VAR_MARKED_P): New macro.
+ (DECL_MAYBE_TEMPLATE): Remove.
+ * class.c (fixed_type_or_null): Avoid infinite recursion.
+
+2003-04-27 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Make the code match the comments.
+ * pt.c (instantiate_decl): Move call to import_export_decl.
+
+2003-04-25 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (finish_file): Don't call import_export_decl for
+ functions that are not defined.
+ (handle_class_head): Robustify.
+ * pt.c (instantiate_decl): Do not call cp_finish_decl for
+ variables that are not defined.
+
+2003-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10471
+ * call.c (build_cxx_call): Robustify.
+
+2003-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10451
+ * decl.c (grokdeclarator): Correct logic for "mutable" errors.
+
+2003-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10446
+ * search.c (lookup_fnfields_1): Handle empty slots in the method
+ vector.
+
+2003-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10428
+ * decl.c (check_elaborated_type_specifier): New function, split
+ out from ...
+ (xref_tag): ... here. Use the new function in more places.
+
+2003-04-21 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_over_call): Use build_cxx_call.
+ (build_cxx_call): New method, split out of build_over_call.
+ * cp-tree.h (language_function): Add can_throw.
+ (build_cxx_call): Declare it.
+ * decl.c (finish_function): If a function does not contain any
+ calls to functions that can throw an exception, indicate that
+ fact.
+ * decl2.c (mark_used): Do not defer the instantiation of
+ functions, if the current function does not throw.
+ * optimize.c (maybe_clone_body): Copy TREE_NOTHROW to the clones.
+ * pt.c (instantiate_decl): Make sure import_export_decl is called
+ before emitting things.
+ * rtti.c (throw_bad_cast): Use build_cxx_call.
+ (build_dynamic_cast_1): Likewise.
+ * typeck.c (build_function_call): Likewise.
+
+2003-04-21 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9881
+ * typeck.c (build_unary_op): Fold all COMPONENT_REF addr
+ expressions. Reverts my 2002-08-08 patch.
+
+2003-04-20 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10405
+ * search.c (lookup_field_1): Final scan goes backwards for
+ types, forwards for non-types.
+
+2003-04-15 Jason Merrill <jason@redhat.com>
+
+ * decl2.c (mark_used): Don't instantiate anything if
+ skip_evaluation.
+
+2003-04-15 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_new_1): Use nullexp instead of null_node to avoid
+ unwanted macro expansion.
+
+2003-04-14 Ziemowit Laski <zlaski@apple.com>
+
+ * tree.c (build_cplus_array_type_1): Do not call
+ uses_template_parms() on a NULL index_type.
+
+2003-04-14 Andreas Schwab <schwab@suse.de>
+
+ * init.c (build_new_1): Test use_cookie instead of cookie_size to
+ avoid code-gen bug on ia64.
+
+2003-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10300
+ * init.c (build_new_1): Correct logic for checking whether the
+ return value from the allocation function was zero.
+
+2003-03-31 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10278
+ * spew.c (yyerror): Avoid crashing at all costs.
+
+2003-03-31 Jason Merrill <jason@redhat.com>
+
+ PR java/10145
+ * class.c (check_field_decl): Don't set DECL_ALIGN.
+
+2003-03-30 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7647
+ * search.c (lookup_field_1): Add want_type parameter.
+ (lookup_field_r): Adjust call to lookup_field_1.
+
+2003-03-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/10245
+ * cvt.c (force_rvalue): New fn.
+ * call.c (build_conditional_expr): Use it.
+ * cp-tree.h: Declare it.
+
+2003-03-28 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10047
+ * decl2.c (finish_file): Don't warn about explicitly instantiated
+ inline decls.
+
+2003-03-27 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10158
+ * spew.c (snarf_method):Set DECL_INITIALIZED_IN_CLASS for
+ members.
+ * pt.c (instantiate_decl): Only reduce the template args for
+ friends that are not defined in class.
+
+2003-03-24 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9898, PR c++/383, DR 322
+ * pt.c (maybe_adjust_types_for_deduction) [DEDUCE_CONV]: Look
+ through reference types on both PARM and ARG.
+
+ PR c++/10199
+ * call.c (build_method_call): Deal with LOOKUP_EXPR.
+ * semantics.c (finish_object_call_expr): Use build_method_call
+ when in a template decl.
+
+2003-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7086
+ * semantics.c (genrtl_named_return_value): Adjust calls to
+ put_var_into_stack.
+ * typeck.c (cxx_mark_addressable): Likewise.
+
+2003-03-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6412
+ * cp/decl2.c (arg_assoc_class): Correct check for namespace-scope
+ friends.
+ * cp/pt.c (instantiate_class_template): Fix formatting.
+
+2003-03-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/8316, c++/9315, c++/10136
+ * call.c (joust): Improve wording.
+
+2003-03-18 Roger Sayle <roger@eyesopen.com>
+
+ PR c++/10031
+ * decl.c (duplicate_decls): Use the new type when prototyping
+ anticipated decls, even when the types match. This defines the
+ exception list for the built-in function.
+
+2003-03-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/10091
+ * typeck.c (build_class_member_access_expr): Compare
+ TYPE_MAIN_VARIANTs.
+
+ * decl.c (finish_function): Don't skip a block.
+
+ PR c++/9993
+ * decl.c (finish_function): Only allow the NRVO to use variables
+ declared at function scope.
+
+2003-03-17 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9629
+ * cp-tree.h (struct language_function): Add in_base_initializer.
+ (in_base_initializer): define it.
+ (expand_member_init): Remove INIT param.
+ * init.c (expand_member_init): Remove INIT param, return the member.
+ (emit_mem_initializers): Set in_base_initializer.
+ * class.c (build_base_path): Check in_base_initializer.
+ * parse.y (begin_member_init): New reduction.
+ (member_init): Use it.
+ * pt.c (tsubst_initializer_list): Set in_base_initializer.
+
+2003-03-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/6440
+ * pt.c (maybe_process_partial_specialization): Handle
+ member class template when enclosing class template is
+ explicit specialized.
+ (most_general_template): Stop looking when DECL is already
+ specialized.
+
+2003-03-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/9420
+ * search.c (lookup_conversions): Call complete_type here.
+ * call.c (implicit_conversion): Not here.
+
+2003-03-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/9336
+ * decl2.c (lookup_arg_dependent): Handle error_mark_node.
+
+2003-03-13 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (do_nonmember_using_decl): Correct handling of
+ simultaneous type/non-type bindings.
+
+2003-03-13 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (initialize_reference): Remove bogus assertion.
+ * decl.c (build_ptrmemfunc_type): Revert change of 2003-03-09.
+
+2003-03-12 Andrew Lewycky <andrew@mxc.ca>
+
+ PR c++/7050
+ * expr.c (cxx_expand_expr): Return const0_rtx for throw
+ expressions.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9474
+ * decl2.c (do_nonmember_using_decl): Do not call duplicate decls
+ to merge old and new declarations.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9924
+ * decl2.c (do_nonmember_using_decl): Ignore anticipated builtins.
+
+2003-03-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/9820
+ * search.c (lookup_member): Fix handling of functions in a class
+ being defined.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8700
+ * call.c (print_z_candidates): Avoid printing duplicates.
+
+2003-03-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/8660
+ * decl2.c (check_classfn): A member template only matches a
+ member template.
+
+2003-03-10 Devang Patel <dpatel@apple.com>
+
+ PR c++/9394
+ * g++spec.c (lang_specific_driver): Use DEFAULT_WORD_SWITCH_TAKES_ARG.
+
+2003-03-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/9798
+ * decl.c (push_using_directive): Push before recursing.
+
+ PR c++/9868
+ * call.c (resolve_scoped_fn_name): Handle the case of a function
+ pointer member.
+ * init.c (build_offset_ref): Handle getting a FIELD_DECL for NAME.
+
+ * decl2.c (build_offset_ref_call_from_tree): Only mess with 'this'
+ argument in the pointer-to-member case.
+
+2003-03-09 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9373
+ * cp-lang.c (cxx_get_alias_set): Use alias set zero for
+ pointers to member functions.
+
+ PR c++/8534
+ * decl.c (build_ptrmemfunc_type): Do not allow default arugments
+ in pointer-to-member-function types.
+
+2003-03-09 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9912
+ * cp-tree.h (is_ancestor): New function.
+ * decl2.c (is_namespace_ancestor): Rename to ...
+ (is_ancestor): ... this.
+ (namespace_ancestor): Use it.
+ (set_decl_namespace): Likewise.
+ (handle_class_head): Check for invalid class definitions.
+
+2003-03-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ Compile-time improvement: 2/n.
+ * cp-tree.h (struct cxx_binding): New datatype;
+ (struct lang_identifier): Use it.
+ (LOCAL_BINDING_P): Adjust definition.
+ (INHERITED_VALUE_BINDING_P): Likewise.
+ (BINDING_SCOPE): Likewise.
+ (BINDING_HAS_LEVEL_P): Likewise.
+ (BINDING_VALUE): Likewise.
+ (BINDING_TYPE): Likewise.
+ (IDENTIFIER_VALUE): Likewise.
+ (struct tree_binding): Remove.
+ (TS_CP_BINDING): Likewise.
+ ((union lang_tree_node): Remove field "binding".
+ (cxx_binding_clear): New macro.
+ (binding_for_name): Adjust return type.
+ (qualified_lookup_using_namespace): Adjust prototype.
+ (lookup_using_namespace): Adjust prototype.
+ (cxx_scope_find_binding_for_name): Declare.
+ * cp-tree.def: Remove CPLUS_BINDING definition.
+ * parse.y (parse_scoped_id): Don't type-abuse of 'id'. Allocate
+ temporary cxx_binding on stack. Simplify.
+ * decl.c (push_binding): Adjust local variable type.
+ (add_binding): Likewise.
+ (push_class_binding): Likewise.
+ (pop_binding): Likewise.
+ (poplevel): Likewise.
+ (poplevel_class): Likewise.
+ (free_bindings): Adjust type.
+ (find_binding): Adjust return type, add a third parameter. Remove
+ non-useful assertion now that we use static typing.
+ (cxx_scope_find_binding_for_name): New function.
+ (binding_for_name): Use it. Adjust local variable type. Simplify.
+ (namespace_binding): Simplify.
+ (set_namespace_binding): Likewise.
+ (set_identifier_type_value_with_scope): Adjust local variable type.
+ (lookup_tag): Don't type-abuse of local variable 'old'.
+ (lookup_namespace_name): Likewise. Allocate binding on stack.
+ (select_decl): Adjust prototype.
+ (unqualified_namespace_lookup): Allocate binding on stack.
+ Don't type-abuse of local variable 'val'.
+ (lookup_name_real): Likewise.
+ (maybe_inject_for_scope_var): Adjust local variable type.
+ (cp_tree_node_structure): Remove CPLUS_BINDING case label.
+ (namespace_binding): Adjust logic, simplify.
+ (BINDING_LEVEL): Adjust definition.
+ (push_class_level_binding): Adjust local variable type.
+ (struct cxx_saved_binding): Adjust field 'binding' type.
+ * decl2.c (ambiguous_decl): Adjust prototype.
+ (lookup_using_namespace): Adjust local variable type.
+ (qualified_lookup_using_namespace): Catch type error and correct
+ ensueing logic error.
+ (do_nonmember_using_decl): Adjust local variable type. Allocate
+ temporary cxx_binding on stack.
+ (do_toplevel_using_decl): Adjust local variable type.
+ * ptree.c (cxx_print_cxx_binding): New function.
+ (cxx_print_identifier): Use it.
+ (cxx_print_xnode): Delete CPLUS_BINDING case label.
+
+2003-03-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9970
+ * decl.c (duplicate_decls): Only copy DECL_THUNKS for virtual
+ functions.
+
+2003-03-07 Matt Austern <austern@apple.com>
+
+ * cp-tree.h (struct lang_type_class): add field for key method
+ (cp_global_trees): rename dynamic_classes to keyed_classes
+ (key_method): add definition
+ * class.c (finish_struct_1): compute class's key method, and add
+ the class to keyed_classes list if there is no key method.
+ * decl.c (finish_function): add class to keyed_classes list if we
+ see a definition of the class's key method.
+ * pt.c (instantiate_class_template): add template specialization
+ of a dynamic class to keyed_classes list.
+ * decl2.c (key_method): remove
+ (finish_file): iterate only through keyed_classes list when
+ deciding whether to emit vtables, remove class from its list after
+ we do the emission.
+
+2003-03-08 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9809
+ * call.c (add_function_candidate): Skip builtin fuctions that have
+ not yet been declared.
+
+2003-03-07 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (reference_binding): Remove REF_IS_VAR parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (make_temporary_var_for_ref_to_type): Add TYPE parameter.
+ (initialize_reference): Adjust handling for references bound to
+ rvalues.
+ * cp-tree.h (make_temporary_var_for_ref_to_temp): Change
+ prototype.
+ (real_non_cast_lvalue_p): New method.
+ * cvt.c (build_up_reference): Adjust use of
+ make_temporary_var_for_ref_to_temp.
+ * tree.c (real_non_cast_lvalue_p): New method.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (merge_conversion_sequences): New function.
+ (build_conv): Set ICS_USER_FLAG for USER_CONVs.
+ (convert_class_to_reference): Correct handling of second
+ standard conversion sequence in a user-defined conversion
+ sequence.
+ (build_user_type_conversion_1): Use merge_conversion_sequences.
+ * cp-tree.def: Add comments for CONV nodes.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9965
+ * call.c (reference_binding): Add ref_is_var parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (initialize_reference): Likewise.
+
+ PR c++/9400
+ * decl.c (pushdecl): Don't check for shadowing of DECL_ARTIFICIAL
+ PARM_DECLs.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9791
+ * class.c (get_basefndecls): Use lookup_fnfields_1.
+
+2003-03-02 Matt Austern <austern@apple.com>
+
+ * decl.c (cp_binding_level): Add static_decls varray member.
+ (add_decl_to_level): Add static/inline namespace scope
+ declarations to static_decls array.
+ (wrapup_global_for_namespace): Pass static_decls only, instead of
+ all decls, to wrapup_global_declarations/check_global_declarations.
+ (push_namespace): Initialize static_decls for ordinary namespaces.
+ (cxx_init_decl_processing): Initialize static_decls for global
+ namespace.
+
+2003-03-05 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (end_of_class): Correct thinko.
+
+2003-03-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * cp-tree.h (cxx_saved_binding): Declare.
+ (struct saved_scope): Adjust type of field 'old_binding'.
+ * decl.c (cxx_saved_binding_make): New macro.
+ (struct cxx_saved_binding): Define.
+ (store_bindings): Adjust prototype. Use cxx_saved_binding to save
+ C++ bindings.
+ (maybe_push_to_top_level): Adjust local variable type.
+ (pop_from_top_level): Likewise.
+
+2003-03-03 Jason Merrill <jason@redhat.com>
+
+ * decl.c (finish_enum): Do set the type in a template. Simplify.
+ * pt.c (tsubst_enum, tsubst_copy): Revert last patch.
+
+2003-03-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9878
+ * call.c (convert_class_to_reference): Correct conversion
+ sequences.
+ (reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (add_candidate): Change type of candidates parameter.
+ (add_function_candidate): Likewise.
+ (add_conv_candidate): Likewise.
+ (build_builtin_candidate): Likewise.
+ (add_builtin_candidate): Likewise.
+ (add_builtin_candidates): Likewise.
+ (add_template_candidate_real): Likewise.
+ (add_template_candidate): Likewise.
+ (add_template_conv_candidate): Likewise.
+ (build_user_type_conversion_1): Adjust accordingly.
+ (build_object_call): Likewise.
+ (build_conditional_expr): Likewise.
+ (add_candidates): Likewise.
+ (build_new_op): Likewise.
+ (convert_like_real): Use USER_CONV_CAND. Use build_nop.
+ (build_new_method_call): Adjust calls to add_function_candidate.
+ (make_temporary_var_for_ref_to_temp): New function.
+ (initialize_reference): Add decl parameter.
+ * class.c (build_rtti_vtbl_entries): Use build_address and
+ build_nop.
+ * cp-tree.h (initialize_reference): Change prototype.
+ (make_temporary_var_for_ref_to_temp): New function.
+ (build_type_conversion): Change prototype.
+ (build_address): New function.
+ (build_nop): Likewise.
+ * cvt.c (cp_convert_to_pointer): Adjust call to
+ build_type_conversion. Avoid indicating redundant NOP_EXPRs.
+ Use build_nop.
+ (convert_to_pointer_force): Use build_nop.
+ (build_up_reference): Use make_temporary_var_for_ref_to_temp.
+ (convert_to_reference): Adjust call to build_type_conversion.
+ (ocp_convert): Likewise.
+ (build_type_conversion): Remove for_sure parameter.
+ * decl.c (grok_reference_init): Use initialize_reference.
+ * typeck.c (build_address): New function.
+ (build_nop): Likewise.
+ (build_unary_op): Use them.
+ (build_ptrmemfunc): Tidy slightly.
+ (convert_for_initialization): Adjust call to
+ initialize_reference.
+ * typeck2.c (store_init_value): Remove #if 0'd code.
+
+2003-03-02 Ashif Harji <asharji@uwaterloo.ca>
+
+ * lang-specs.h (default_compilers): Add -no-integrated-cpp flag to
+ invoke an external cpp during compilation.
+
+2003-02-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9892
+ * pt.c (instantiate_decl): Clear DECL_RTL for a VAR_DECL when
+ instantiating it.
+
+2003-02-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9879
+ * cp-tree.h (build_zero_init): Add parameter.
+ * decl.c (cp_finish_decl): Adjust call.
+ * init.c (build_zero_init): Add nelts parameter. Adjust recursive
+ calls.
+ (build_default_init): Add nelts parameter. Adjust calls to
+ build_zero_init.
+ (build_new_1): Adjust call to build_default_init.
+ * typeck2.c (process_init_constructor): Adjust call to build_zero_init.
+
+2003-02-27 Devang Patel <dpatel@apple.com>
+
+ * decl.c (finish_enum): Merge two 'for' loops. Copy value node if required.
+ Postpone enum setting for template decls.
+ (build_enumerator): Delay copying value node until finish_enum (). Remove
+ #if 0'ed code.
+ * pt.c (tsubst_enum): Set TREE_TYPE and copy value node.
+ (tsubst_copy): Add check for enum type.
+
+
+2003-02-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9829
+ * decl.c (grokdeclarator): Handle SCOPE_REFs whose second argument
+ is a NAMESPACE_DECL.
+
+2003-02-24 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (add_binding): Time TV_NAME_LOOKUP.
+ (push_class_binding): Likewise.
+ (set_namespace_binding): Likewise.
+
+2003-02-24 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9602
+ * typeck2.c (abstract_virtuals_error): Don't check when we
+ are processing a template.
+
+2003-02-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/7982
+ * decl.c (warn_about_implicit_typename_lookup): Handle TYPEOF_TYPE.
+
+2003-02-21 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9749
+ * decl.c (grokdeclarator): Do not allow parameters with variably
+ modified types.
+
+ PR c++/9727
+ * decl2.c (push_scope): Don't pushclass for non-class types.
+ (pop_scope): Don't popclass either.
+
+ PR c++/8906
+ * decl.c (lookup_name_real): Use IMPLICIT_TYPENAME_P.
+ * decl2.c (handle_class_head): Check it.
+
+ PR c++/8724
+ * call.c (build_method_call): Make sure that the type destroyed in
+ an explicit destructor call is complete.
+
+2003-02-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9729
+ * mangle.c (mangle_conv_op_name_for_type): Issue an error message
+ when the G++ 3.2 ABI prevents correct compilation.
+
+2003-02-18 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9704
+ * class.c (layout_class_type): In the 3.2 ABI, take into account
+ trailing bit fields when computing CLASSTYPE_SIZE_UNIT.
+
+2003-02-18 Matt Austern <austern@apple.com>
+
+ * cp/cp-lang.c: Change lang hooks so that final_write_globals does
+ nothing for C++.
+ * cp/decl.c (wrapup_globals_for_namespace): Remove special
+ handling of global namespace.
+
+2003-02-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/9623
+ * decl.c (reshape_init): Don't mess with initializer labels.
+
+2003-02-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9459
+ * error.c (dump_type_prefix): Handle TYPEOF_TYPE.
+ (dump_type_suffix): Likewise.
+
+2003-02-17 Michael Elizabeth Chastain <mec@shout.net>
+
+ PR debug/9717
+ * class.c (build_base_field): Mark fields for base classes with
+ DECL_IGNORED_P.
+
+2003-02-13 Andrew Pinski <pinskia@physics.uc.edu>
+
+ * decl.c: (define_label): Fix warning for return 0 instead of NULL.
+
+2003-02-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * Make-lang.in (cp/decl2.o): Add dependency on timevar.h
+ * decl2.c: Include "timevar.h".
+ (namespace_ancestor): Time name lookup.
+ (add_using_namespace): Likewise.
+ (lookup_using_namespace): Likewise.
+ (qualified_lookup_using_namespace): Likewise.
+ (decl_namespace): Likewise.
+ (lookup_arg_dependent): Likewise.
+ * lex.c (do_identifier): Likewise.
+ (do_scoped_id): Likewise.
+ * pt.c (lookup_template_class): Likewise.
+
+2003-02-12 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (define_label): Don't forget to pop TV_NAME_LOOKUP.
+
+2003-02-11 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c: Include "timevar.h".
+ (poplevel): Time name lookup.
+ (find_binding): Likewise.
+ (push_namespace): Likewise.
+ (pop_nested_namespace): Likewise.
+ (store_bindings): Likewise.
+ (maybe_push_to_top_level): Likewise.
+ (pop_from_top_level): Likewise.
+ (push_local_name): Likewise.
+ (pushtag): Likewise.
+ (pushdecl): Likewise.
+ (pushdecl_with_scope): Likewise.
+ (pushdecl_namespace_level): Likewise.
+ (pushdecl_top_level): Likewise.
+ (pushdecl_class_level): Likewise.
+ (push_class_level_binding): Likewise.
+ (push_using_decl): Likewise.
+ (push_using_directive): Likewise.
+ (push_overloaded_decl): Likewise.
+ (lookup_label): Likewise.
+ (define_label): Likewise.
+ (lookup_tag): Likewise.
+ (lookup_tag_reverse): Likewise.
+ (lookup_namespace_name): Likewise.
+ (select_decl): Likewise.
+ (unqualified_namespace_lookup): Likewise.
+ (lookup_name_real): Likewise.
+ (lookup_name_current_level): Likewise.
+ (lookup_type_current_level): Likewise.
+ (maybe_inject_for_scope_var): Likewise.
+ (xref_tag): Likewise.
+
+ * Make-lang.in (cp/decl.o): Add dependency on timevar.h
+
+2003-02-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7129
+ * operators.def: Add <?= and >?=.
+
+2003-01-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8849
+ * error.c (dump_expr): Handle BASELINK.
+ * pt.c (resolve_overloaded_unification): Handle FUNCTION_DECL.
+
+2003-01-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9453
+ * friend.c (is_friend): Always accept when SUPPLICANT is still
+ a TEMPLATE_DECL.
+ * pt.c (push_access_scope_real): Call push_to_top_level for
+ function in namespace scope.
+ (push_access_scope): Remove ARGS argument, all caller adjusted.
+ (pop_access_scope): Call pop_from_top_level for function in
+ namespace scope.
+ (regenerate_decl_from_template): Use push_access_scope_real.
+
+2003-01-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9437
+ * pt.c (unify): Don't unify '*T' with 'U C::*'.
+
+2003-01-27 Jeffrey D. Oldham <oldham@codesourcery.com>
+
+ PR c++/47
+ * cp-tree.h (lookup_nested_field): Add declaration.
+ * decl.c (lookup_name_real): Call lookup_nested_field.
+ * search.c (lookup_nested_field): Add function.
+
+2003-01-26 Christian Cornelssen <ccorn@cs.tu-berlin.de>
* Make-lang.in (c++.install-common, c++.install-man)
- (c++.uninstall): Prepend $(DESTDIR) to destination paths
- in all (un)installation commands.
+ (c++.uninstall): Prepend $(DESTDIR) to destination paths in
+ all (un)installation commands.
(c++.install-common): Rewrite $(LN) commands to support
DESTDIR with "ln" as well as with "ln -s".
+2003-01-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (check_classfn): Fix uninitialized warning.
+
2003-01-22 Mark Mitchell <mark@codesourcery.com>
PR c++/9328
@@ -22,20 +1175,145 @@
function; it doesn't make sense to try to print its type.
* semantics.c (finish_typeof): Issue errors about invalid uses.
-2003-01-21 Jeffrey D. Oldham <oldham@codesourcery.com>
+2003-01-22 Josef Zlomek <zlomekj@suse.cz>
- PR c++/47
- * cp-tree.h (lookup_nested_field): Add declaration.
- * decl.c (lookup_name_real): Call lookup_nested_field.
- * search.c (lookup_nested_field): Add function.
+ PR/9386, PR/8801
+ 2002-12-27 Mark Mitchell <mark@codesourcery.com>
+ * typeck.c (build_class_member_access_expr): Fix anonymous union
+ handling.
+
+2003-01-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/9167, c++/9358
+ * decl.c (require_complete_types_for_parms): Also update DECL_ARG_TYPE.
+
+2003-01-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/9342
+ * call.c (build_conditional_expr): Always do lvalue-rvalue
+ conversion.
+
+2003-01-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/8564
+ * init.c (build_vec_init): Re-add maxindex parm.
+ (perform_member_init, build_aggr_init): Pass it.
+ (build_new_1): Pass it. Use an incomplete array type for full_type.
+ * typeck.c (build_modify_expr): Pass it.
+ * cp-tree.h: Adjust.
+
+2003-01-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/8748
+ * class.c (build_base_path): Take the address before calling save_expr.
+
+ * call.c (build_user_type_conversion_1): Do set ICS_BAD_FLAG if
+ all the ambiguous conversions are bad.
+
+ * class.c (maybe_warn_about_overly_private_class): Don't stop
+ searching when we find a nonprivate method.
+
+2003-01-09 Jakub Jelinek <jakub@redhat.com>
+
+ * decl.c (start_decl): Only check DECL_THREAD_LOCAL for VAR_DECLs.
+
+2003-01-09 Jakub Jelinek <jakub@redhat.com>
+
+ * decl.c (start_decl): Don't set DECL_COMMON for __thread variables.
+
+2003-01-07 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9030
+ * decl.c (make_typename_type): Check access only when tf_error.
+ (make_unbound_class_template): Likewise.
+ * pt.c (saved_access_scope): New variable.
+ (push_access_scope_real): New function.
+ (push_access_scope): Likewise.
+ (pop_access_scope): Likewise.
+ (tsubst_default_argument): Use them.
+ (instantiate_template): Likewise.
+ (regenerate_decl_from_template): Likewise.
+ (instantiate_decl): Likewise.
+ (get_mostly_instantiated_function_type): Likewise.
+
+2003-01-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9165
+ * decl2.c (build_cleanup): Mark the object as used.
+
+2003-01-03 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/45, c++/3784
+ * tree.c (cp_tree_equal, TEMPLATE_PARM_INDEX): The types must be
+ the same too.
+
+2002-12-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9054
+ * class.c (layout_class_type): Set DECL_CONTEXT of type for base.
+ * dump.c (cp_dump_tree, RECORD_TYPE): Deal with type for base types.
2002-12-26 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/8503
- Remove DR 295 implementation.
- * pt.c (check_cv_quals_for_unify): Disable function & method cases.
- * tree.c (cp_build_qualified_type_real): Likewise. Don't warn
- about ignoring volatile qualifiers.
+ PR c++/4803
+ * decl2.c (mark_used): Defer inline functions.
+ (finish_file): Merge deferred_fns loops. Check all used
+ inline functions have a definition.
+ * method.c (make_thunk): Thunks are not inline.
+
+ PR c++/5116, c++/764
+ * call.c (build_new_op): Make sure template class operands are
+ instantiated.
+
+2002-12-24 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR C++/7964
+ * cp-tree.h (resolve_scoped_fn_name): Prototype.
+ * call.c (resolve_scoped_fn_name): New function. Deal with
+ more template expansion. Broken out of ...
+ * parse.y (parse_finish_call_expr): ... here. Call it.
+ * decl2.c (build_expr_from_tree, CALL_EXPR): Use
+ resolve_scoped_fn_name and build_call_from_tree.
+
+ PR c++/9053
+ * decl.c (duplicate_decls): Templates may be disambiguated by
+ return type.
+
+ PR c++/8702
+ * decl2.c (check_classfn): Use lookup_fnfield_1. List all
+ conversion operators on failure.
+
+2002-12-22 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/8572
+ * cp-tree.h (grokoptypename): Add SCOPE parameter.
+ * decl2.c (grokoptypename): Add SCOPE parameter. tsubst the type
+ if in a template scope.
+ * parse.y (unoperator): Return the scope.
+ (operator_name): Adjust grokoptypename call.
+
+2002-12-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * cp-tree.h (make_unbound_class_template): Use tsubst_flags_t.
+ * decl.c (make_unbound_class_template): Adjust. Check for tf_error.
+ * pt.c (tsubst) [OFFSET_TYPE]: Check for tf_error.
+
+2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8099
+ * friend.c (make_friend_class): Allow partial specialization
+ when declaration is not a template friend.
+
+2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/3663
+ * pt.c (lookup_template_class): Copy TREE_PRIVATE and
+ TREE_PROTECTED to created decl nodes.
+
+2002-12-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (build_base_field): Do not set DECL_PACKED on the
+ FIELD_DECL.
2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
@@ -49,46 +1327,94 @@
* pt.c (convert_template_argument): Fix type or template template
parameter decision logic.
-2002-12-13 Joe Buck <jbuck@synopsys.com>
-
- * parse.y (class_head_defn): Set CLASSTYPE_DECLARED_CLASS for
- anonymous structs.
-
2002-12-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
-
- PR C++/8031
+
+ PR C++/8031
* cvt.c (convert_to_pointer_force): Don't try comparing against
erronous type.
+2002-12-13 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h: Have the multiple-include guards around
+ the entire file.
+
2002-12-10 Mark Mitchell <mark@codesourcery.com>
PR c++/8372
* pt.c (tsubst_copy): Handle destructor names more correctly.
+2002-12-10 Matt Austern <austern@apple.com>
+
+ * cp-tree.h: get rid of needs_virtual_reinit bit.
+
+2002-12-09 Mark Mitchell <mark@codesourcery.com>
+
+ * NEWS: Document removal of in-class initialization extension for
+ static data members of non-arithmetic, non-enumeration type.
+ * decl.c (check_static_variable_definition): Do not allow that
+ extension.
+ * decl2.c (grokfield): Do not call digest_init when processing
+ templates.
+
2002-12-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* error.c (dump_expr): Fix format specifier warning.
+2002-12-04 Geoffrey Keating <geoffk@apple.com>
+
+ * class.c (finish_struct_1): Correct comment.
+ * cp-tree.c (DECL_SORTED_FIELDS): Likewise.
+
2002-12-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
PR C++/8799
* error.c (dump_expr): Don't ever try to dump a non-existent
- expression.
+ expression.
+
+2002-12-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/8674
+ * call.c (build_over_call): Check specifically for TARGET_EXPR
+ when eliding.
+
+ PR c++/8461, c++/8625
+ * call.c (convert_for_arg_passing): Don't mess with error_mark_node.
+ (cp_convert_parm_for_inlining): Remove.
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Remove.
+ * cp-tree.h (ADDR_IS_INVISIREF): Remove.
+ * except.c (stabilize_throw_expr): Remove ADDR_IS_INVISIREF code.
+
+ * call.c (build_user_type_conversion_1): Don't set ICS_BAD_FLAG on
+ an ambiguous conversion.
+
+2002-12-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8688
+ * decl.c (reshape_init): Handle erroneous initializers.
2002-12-02 Mark Mitchell <mark@codesourcery.com>
+ PR c++/8720
+ * spew.c (remove_last_token): Make sure that last_chunk is set
+ correctly.
+
PR c++/8615
* error.c (dump_expr): Handle character constants with
TREE_OVERFLOW set.
+2002-12-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ DR 180
+ * decl.c (grokdeclarator): Require class-key for all friend class.
+ Output the correct type and context in the error message.
+
2002-12-01 Mark Mitchell <mark@codesourcery.com>
PR c++/5919
* pt.c (unify): Use variably_modified_type_p to test validity of
template argument types.
-2002-12-01 Mark Mitchell <mark@codesourcery.com>
-
PR c++/8727
* cp-tree.h (lang_type_class): Add typeinfo_var.
(CLASSTYPE_TYPEINFO_VAR): New macro.
@@ -106,41 +1432,204 @@
c_size_type_node.
* decl2.c (coerce_new_type): Likewise.
* except.c (do_allocate_exception): Likewise.
- * typeck.c (c_sizeof): Likewise.
- (c_sizeof_nowarn): Likewise.
2002-11-30 Mark Mitchell <mark@codesourcery.com>
+ PR c++/8227
+ * decl.c (layout_var_decl): Deal gracefully with erroneous types.
+ (check_initializer): Validate the type of the initialized
+ variable, even if the initializer is absent.
+ * typeck.c (cp_type_quals): Deal gracefully with erroneous types.
+
PR c++/8214
* typeck.c (convert_for_assignment): Do not use
decl_constant_value on the operand.
-2002-11-19 Release Manager
+ PR c++/8511
+ * pt.c (instantiate_decl): Handle template friends defined outside
+ of the class correctly.
+
+2002-11-29 Joe Buck <jbuck@synopsys.com>
- * GCC 3.2.1 Released.
+ * parse.y (class_head_defn): Set CLASSTYPE_DECLARED_CLASS for
+ anonymous structs.
-2002-11-19 Release Manager
+2002-11-29 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.1 Released.
+ * class.c (walk_subobject_offsets): Recur on binfos as well as on
+ types.
+ (layout_nonempty_base_or_field): Pass it a binfo when processing a
+ base class.
+ (layout_empty_base): Likewise.
+ (build_base_field): Likewise.
-2002-11-18 Release Manager
+2002-11-27 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.1 Released.
+ * class.c (build_base_field): Make sure we get the canonical base
+ when descending through primary bases.
-2002-11-11 Nathan Sidwell <nathan@codesourcery.com>
+2002-11-26 Geoffrey Keating <geoffk@apple.com>
- PR c++/7788
- * rtti.c (unemitted_tinfo_decl_p): Check it has a field.
+ * decl.c (check_initializer): Don't error on initialisation of
+ a scalar with a brace-enclosed expression.
+
+2002-11-26 Nathan Sidwell <nathan@codesourcery.com>
-2002-11-02 Zack Weinberg <zack@codesourcery.com>
+ * cp-tree.h (DECL_LANG_FLAG_4): Document more uses.
+ (template_parms_equal): Remove prototype.
+ * typeck.c (buuld_indirect_ref): Reformat.
+
+2002-11-25 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.c (cp_build_qualified_type_real): Correct handling of
+ array types.
+ * class.c (walk_subobject_offsets): Fix thinko.
+ (build_base_field): Record offsets of empty bases in primary
+ virtual bases.
+ (layout_class_type): Record offsets of empty bases in fields.
+
+ * search.c (is_subobject_of_p_1): Fix thinko.
+ (lookup_field_queue_p): Likewise.
+
+2002-11-24 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (layout_class_type): Reuse tail padding when laying out
+ virtual bases.
+
+2002-11-22 Mark Mitchell <mark@codesourcery.com>
+
+ * rtti.c (qualifier_flags): Fix thinko.
+
+2002-11-21 Glen Nakamura <glen@imodulo.com>
+
+ PR c++/8342
+ * typeck.c (get_member_function_from_ptrfunc): Make sure that a
+ SAVE_EXPR for instance_ptr doesn't get evaluated first inside one
+ of the branches of a COND_EXPR.
+
+2002-11-19 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (for_each_template_parm): Free allocated memory.
+ * search.c (is_subobject_of_p_1): New function.
+ (is_subobject_of_p): Avoid walking virtual bases multiple times.
+
+2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * g++spec.c (lang_specific_spec_functions): New.
+
+2002-11-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * class.c: Likewise.
+ * decl2.c: Likewise.
+
+2002-11-14 Zack Weinberg <zack@codesourcery.com>
+
+ * search.c (dfs_push_decls): Do not try to reorder elements
+ 3..n of method_vec if method_vec has only two elements.
+ Reverse order of two tests to avoid accessing unallocated
+ memory.
+
+2002-11-14 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (dfs_find_final_overrider): Adjust so that the most
+ derived object is a binfo, rather than a class type.
+ (find_final_overrider): Likewise.
+ (add_vcall_offset_vtbl_entries_1): Simplify accordingly.
+ (add_vcall_offset): Likewise.
+
+2002-11-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8389
+ * pt.c (instantiate_template): Push class scope for member
+ functions.
+ (get_mostly_instantiated_function_type): Likewise. Don't call
+ tsubst on context. Remove CONTEXTP and TPARMSP parameters.
+ * cp-tree.h (get_mostly_instantiated_function_type): Adjust.
+ * mangle.c (write_encoding, write_unqualified_name): Adjust.
+
+2002-11-07 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (add_vcall_offset_vtbl_entries_1): Correct ordering of
+ vcall offfsets. Split out ...
+ (add_vcall_offset): ... new function.
+
+ PR c++/8338
+ * pt.c (for_each_template_parm): Add htab parameter.
+ (process_partial_specialization): Adjust call.
+ (push_template_decl_real): Likewise.
+ (pair_fn_data): Add visited.
+ (for_each_template_parm_r): Avoid walking duplicates more than
+ once.
+ (uses_template_parms): Adjust call to for_each_template_parm.
+
+2002-11-07 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (add_implicitly_declared_members): Put implicitly
+ declared functions at the end of TYPE_METHODs when -fabi-version
+ is at least 2.
+
+2002-11-05 Geoffrey Keating <geoffk@apple.com>
+
+ * decl2.c (finish_file): Correct spelling.
+
+2002-11-03 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_special_member_call): Do not try to lookup VTTs by
+ name.
+ * class.c (vtbl_init_data): Add generate_vcall_entries.
+ (get_vtable_decl): Do not look up virtual tables by name.
+ (copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
+ (set_primary_base): Do not set CLASSTYPE_RTTI.
+ (determine_primary_base): Likewise.
+ (get_matching_virtual): Remove.
+ (get_vcall_index): New function.
+ (update_vtable_entry_for_fn): Do not try to use virtual thunks
+ when they are not required. Assign vcall indices at this point.
+ (finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
+ Do update dynamic_classes.
+ (build_vtt): Do not add VTTs to the symbol table.
+ (build_ctor_vtbl_group): Likewise.
+ (build_vtbl_initializer): Simplify handling of vcall indices.
+ (build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
+ for the most derived class.
+ (add_vcall_offset_vtbl_entries_1): But do not actually add them to
+ the vtable.
+ * cp-tree.h (dynamic_classes): New macro.
+ (lang_type_class): Remove rtti. Add vtables. Add vcall_indices.
+ (CLASSTYPE_RTTI): Remove.
+ (CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
+ (CLASSTYPE_VCALL_INDICES): New macro.
+ (CLASSTYPE_VTABLES): Likewise.
+ (BV_USE_VCALL_INDEX_P): Remove.
+ (build_vtable_path): Remove.
+ * decl2.c (finish_vtable_vardecl): Remove.
+ (key_method): Remove #if 0'd code.
+ (finish_vtable_vardecl): Rename to ...
+ (maybe_emit_vtables): ... this.
+ (finish_file): Use it.
+ * search.c (look_for_overrides_here): Update comment.
+
+2002-11-01 Zack Weinberg <zack@codesourcery.com>
PR c/7353 redux
* decl2.c (grokfield): Reject TYPE_DECLs with initializers.
-2002-11-01 Gabriel Dos Reis <gdr@integrable-solutions.net>
+2002-10-30 Jason Merrill <jason@redhat.com>
- PR C++/2521
- * typeck.c (build_x_unary_op): Handle pointer-to-member.
+ PR c++/8186
+ * cp-tree.h (ADDR_IS_INVISIREF): New macro.
+ * call.c (convert_for_arg_passing): Set it.
+ * except.c (stabilize_throw_expr): Recurse for such an arg.
+
+2002-10-31 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove init_priority.
+ (lang_decl): Add delta.
+ (GLOBAL_INIT_PRIORITY): Remove.
+ (THUNK_DELTA): Revise definition.
+ * decl2.c (start_objects): Don't set GLOBAL_INIT_PRIORITY.
+ * dump.c (cp_dump_tree): Don't dump it.
2002-10-30 Mark Mitchell <mark@codesourcery.com>
@@ -150,6 +1639,25 @@
PR c++/8149
* decl.c (make_typename_type): Issue errors about invalid results.
+2002-10-30 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ Core issue 287, PR c++/7639
+ * cp-tree.h (lang_type_class): Add decl_list field.
+ (CLASSTYPE_DECL_LIST): New macro.
+ (maybe_add_class_template_decl_list): Add declaration.
+ * class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST.
+ (unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST.
+ (maybe_add_class_template_decl_list): New function.
+ (add_implicitly_declared_members): Use it.
+ * decl.c (maybe_process_template_type_declaration): Likewise.
+ (pushtag): Likewise.
+ * friend.c (add_friend): Likewise.
+ (make_friend_class): Likewise.
+ * semantics.c (finish_member_declaration): Likewise.
+ (begin_class_definition): Initialize CLASSTYPE_DECL_LIST.
+ * pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST
+ to process members and friends in the order of declaration.
+
2002-10-29 Mark Mitchell <mark@codesourcery.com>
PR c++/8287
@@ -157,28 +1665,45 @@
when returning from a destructor here.
(finish_function_body): Rather than here.
- * semantics.c (finish_alignof): Call complete_type before calling
- c_alignof.
- * decl2.c (build_expr_from_tree): Use
- finish_sizeof/finish_alignof.
-
-2002-10-10 Jim Wilson <wilson@redhat.com>
-
- * decl.c (duplicate_decls): Don't call decl_attributes.
-
2002-10-25 Zack Weinberg <zack@codesourcery.com>
- PR middle-end/6994
- * cp-lang.c (cp_var_mod_type_p): New: C++ hook for
- variably_modified_type_p.
- * cp-tree.h: Remove prototype of variably_modified_type_p.
- * tree.c (variably_modified_type_p): Remove; now implemented
- in language-independent code.
-
PR c++/7266
* decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a
SCOPE_REF is not null before dereferencing it.
+2002-10-25 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_over_call): Use DECL_CONTEXT, not
+ DECL_VIRTUAL_CONTEXT.
+ * class.c (modify_vtable_entry): Don't mess with
+ DECL_VIRTUAL_CONTEXT.
+ (set_vindex): Remove.
+ (set_primary_base): Remove vfuns_p parameter.
+ (determine_primary_base): Likewise.
+ (modify_all_vtables): Likewise.
+ (layout_class_type): Likewise. Adjust calls to other functions
+ accordingly.
+ (finish_struct_1): Adjust calls to modified functions. Set
+ DECL_VINDEX here.
+ * cp-tree.h (lang_type_class): Remove vsize.
+ (CLASSTYPE_VSIZE): Remove.
+ (lang_decl): Remove thunks.
+ (DECL_THUNKS): Adjust.
+ (DECL_VIRTUAL_CONTEXT): Remove.
+ (duplicate_decls): Don't copy it.
+ * pt.c (build_template_decl): Don't set it.
+ (tsubst_decl): Likewise.
+ * typeck.c (expand_ptrmemfunc_cst): Don't use it.
+
+ * class.c (build_vtbl_initializer): Don't use build_vtable_entry.
+ (build_vtable_entry): Remove.
+ * cp-tree.h (BINFO_VIRTUALS): Expand documentation.
+ (lang_decl): Add thunks.
+ (DECL_THUNKS): New macro.
+ * decl.c (duplicate_decls): Copy it.
+ * method.c (make_thunk): Simplify, and add thunks to DECL_THUNKS.
+ * semantics.c (emit_associated_thunks): Simplify.
+
2002-10-24 David Edelsohn <edelsohn@gnu.org>
PR c++/7228
@@ -191,14 +1716,19 @@
* typeck2.c (process_init_constructor): Remove redundant check for
existence of lang_type structure.
+2002-10-24 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (end_of_base): New method.
+ (end_of_class): Use it. Check indirect virtual bases.
+
+ * class.c (check_field_decls): Fix typo.
+
2002-10-23 Mark Mitchell <mark@codesourcery.com>
PR c++/8067
* decl.c (maybe_inject_for_scope_var): Ignore __FUNCTION__ and
related variables.
-2002-10-23 Mark Mitchell <mark@codesourcery.com>
-
PR c++/7679
* spew.c (next_token): Do not return an endless stream of
END_OF_SAVED_INPUT tokens.
@@ -206,24 +1736,39 @@
the cached token stream.
(snarf_defarg): Likewise.
+2002-10-23 Zack Weinberg <zack@codesourcery.com>
+
+ * cp-lang.c (cp_var_mod_type_p): New: C++ hook for
+ variably_modified_type_p.
+ * cp-tree.h: Remove prototype of variably_modified_type_p.
+ * tree.c (variably_modified_type_p): Remove; now implemented
+ in language-independent code.
+
2002-10-22 Mark Mitchell <mark@codesourcery.com>
PR c++/6579
* spew.c (snarf_parenthesized_expression): New function.
(snarf_block): Use it.
-2002-10-21 Matthias Klose <doko@debian.org>
+2002-10-22 Richard Henderson <rth@redhat.com>
- * Backport, without whitespace change:
- 2002-06-19 Akim Demaille <akim@epita.fr>
- * parse.y (TYPENAME): Rename as tTYPENAME to avoid the clash with
- decl.h's TYPENAME.
- * spew.c, lex.c: Adjust.
- * parse.y (explicit_instantiation): Add empty action to override
- the default $$ = $1 where it introduces a type clash.
+ * method.c (use_thunk): Always compute vcall_value; assert that
+ it is not zero. Use can_output_mi_thunk; use output_mi_thunk
+ for vcall thunks as well.
2002-10-21 Mark Mitchell <mark@codesourcery.com>
+ * class.c (empty_base_at_nonzero_offset_p): New function.
+ (layout_nonempty_base_or_field): Do not check for conflicts when
+ laying out a virtual base using the GCC 3.2 ABI.
+ (build_base_field): Correct checking for presence of empty classes
+ at nonzero offsets when clearing CLASSTYPE_NEARLY_EMPTY_P.
+
+ * class.c (include_empty_classes): Use normalize_rli.
+ (layout_class_type): Likewise.
+
+ * decl.c (reshape_init): Tweak handling of character arrays.
+
PR c++/8218
* cp-tree.h (lang_type_class): Add contains_empty_class_p.
(CLASSTYPE_CONTAINS_EMPTY_CLASS_P): New macro.
@@ -233,55 +1778,145 @@
(finish_struct_1): Initialize it.
(walk_subobject_offsets): Use it to prune searches.
+2002-10-20 Mark Mitchell <mark@codesourcery.com>
+
+ * method.c (use_thunk): Compute the vcall index as a HOST_WIDE_INT.
+ * optimize.c (optimize_function): Replace ASM_OUTPUT_MI_THUNK with
+ TARGET_ASM_OUTPUT_MI_THUNK in comments.
+
2002-10-18 Zack Weinberg <zack@codesourcery.com>
* decl.c (start_decl): Point users of the old initialized-
typedef extension at __typeof__.
-2002-10-18 Nathan Sidwell <nathan@codesourcery.com>
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * Make-lang.in (method.o): Depend on TARGET_H.
+ * method.c (target.h): Include it.
+ (use_thunk): Use target hooks. Use vcall thunks, if available.
+
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (base_derived_from): Make sure return value is a bool.
+
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (find_final_overrider_data_s): Remove overriding_fn and
+ overriding_base.
+ (dfs_base_derived_from): New function.
+ (base_derived_from): Likewise.
+ (dfs_find_final_overrider): Use base_derived_from.
+ (find_final_overrider): Adjust.
+
+2002-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/8080
+ * semantics.c (finish_for_cond, finish_while_cond): Don't mess
+ with condition decls in a template.
+
+2002-10-17 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/7676
* class.c (add_method): Compare template parms too.
2002-10-17 Mark Mitchell <mark@codesourcery.com>
- * mangle.c (globals): Add entity and need_abi_warning.
- (write_prefix): Likewise.
- (write_template_prefix): Likewise.
- (start_mangling): Add entity parameter.
- (finish_mangling): Warn about names whose mangling will change.
- (mangle_decl_string): Adjust.
- (mangle_type_string): Likewise.
- (mangle_special_for_type): Likewise.
- (mangle_ctor_vtbl_for_type): Likewise.
- (mangle_thunk): Likewise.
- (mangle_guard_variable): Likewise.
- (mangle_ref_init_variable): Likewise.
-
PR c++/7584
* class.c (handle_using_decl): Allow the declaration used to be
from an ambiguous base.
+ * pt.c (convert_template_argument): Revert this change:
+ 2002-10-16 Mark Mitchell <mark@codesourcery.com>
+ * pt.c (convert_template_argument): Do not fold non-type
+ template rguments when inside a template.
+
+ * init.c (expand_default_init): Handle brace-enclosed initializers
+ correctly.
+
2002-10-16 Mark Mitchell <mark@codesourcery.com>
+ * mangle.c (write_expression): Correct handling of enumeration
+ constants.
+ (write_template_arg): Likewise.
+ * pt.c (convert_template_argument): Do not fold non-type template
+ arguments when inside a template.
+
PR c++/7478
* cvt.c (convert_to_reference): Allow references as the incoming
type.
- PR c++/8134
- * tree.c (zero_init_p): Always return 1.
+2002-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/7524
* method.c (do_build_assign_ref): Use cp_build_qualified_type, not
build_qualified_type.
+2002-10-15 Richard Henderson <rth@redhat.com>
+
+ * error.c (dump_expr): Use real_to_decimal directly, and with
+ the new arguments.
+
+2002-10-15 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (reshape_init): Fix typo.
+
+ * cp-tree.h (operator_name_info_t): Add arity.
+ * lex.c (init_operators): Initialize it.
+ * mangle.c (write_conversion_operator_name): New function.
+ (write_unqualified_name): Use it.
+ (write_template_args): Accept template arguments as a TREE_LIST.
+ (write_expression): Adjust handling of qualified names to match
+ specification.
+
+2002-10-15 Jason Merrill <jason@redhat.com>
+
+ * call.c (call_builtin_trap): New fn.
+ (convert_arg_to_ellipsis): Use it. Downgrade error to warning.
+ (build_call): Don't set current_function_returns_abnormally outside
+ a function.
+
2002-10-14 Mark Mitchell <mark@codesourcery.com>
+ * class.c (check_field_decls): Remove empty_p parameter. Instead,
+ clear CLASSTYPE_EMPTY_P.
+ (build_base_field): Likewise.
+ (build_base_fields): Likewise.
+ (check_bases_and_members): Likewise.
+ (create_vtbl_ptr): Likewise.
+ (layout_class_type): Likewise. Ensure that empty classes have
+ size zero when used as base classes in the 3.2 ABI.
+ (finish_struct_1): Initialize CLASSTYPE_EMPTY_P and
+ CLASSTYPE_NEARLY_EMPTY_P. Adjust calls to avoid passing empty_p
+ parameter.
+ (is_empty_class): Correct definition when using post-3.2 ABI.
+ * cp-tree.h (lang_type_class): Add empty_p.
+ (CLASSTYPE_EMPTY_P): New macro.
+
+2002-10-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ * init.c (build_delete): Do not apply save_expr for arrays.
+ (build_vec_delete): Likewise.
+
+2002-10-14 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (layout_var_decl): Call layout_decl even for variables
+ whose type is an array with unspecified bounds.
+
PR c++/7176
* lex.c (do_identifier): Add another option for the parsing
parameter.
* parse.y (do_id): Use it.
+2002-10-11 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PRs C++/6803, C++/7721 and C++/7803
+ * decl.c (grokdeclarator): Gracefully handle template-name as
+ decl-specifier.
+
+2002-10-11 Jason Molenda <jmolenda@apple.com>
+
+ * init.c (build_field_list): Provide uses_unions_p with a default
+ value.
+
2002-10-11 Mark Mitchell <mark@codesourcery.com>
PR c++/5661
@@ -292,16 +1927,44 @@
types as template arguments.
* tree.c (variably_modified_type_p): New function.
-2002-10-11 Jason Molenda <jmolenda@apple.com>
+ * NEWS: Document removal of "new X = ..." extension.
+ * class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializers.
+ * cp-tree.h (CP_AGGREGATE_TYPE_P): New macro.
+ (initialize_local_var): Remove declaration.
+ (expand_static_init): Likewise.
+ * decl.c (next_initializable_field): New function.
+ (reshape_init): Likewise.
+ (check_initializer): Use them. Build dynamic initializer for
+ aggregates here too.
+ (initialize_local_var): Simplify, and incorporate cleanup
+ insertion code as well.
+ (destroy_local_var): Remove.
+ (cp_finish_decl): Tidy.
+ (expand_static_init): Fold checks for whether or not a variable
+ needs initialization into this function. Simplify.
+ * decl2.c (do_static_initialization): Simplify.
+ * init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will
+ be done for us automatically.
+ (expand_default_init): Handle brace-enclosed initializers
+ correctly.
+ (expand_aggr_init_1): Remove RTL-generation code.
+ (build_vec_init): Remove "new X = ..." support.
+ * parse.y (new_initializer): Likewise.
+ * rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializer.
+ (create_pseudo_type_info): Likewise.
+ * typeck2.c (store_init_value): Don't try to handle digest_init
+ being called more than once.
+ (digest_init): Tidy handling of brace-enclosed initializers.
- * init.c (build_field_list): Provide uses_unions_p with a default
- value.
+2002-10-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-10-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
+ * decl.c (typename_hash): Use htab_hash_pointer.
- PRs C++/6803, C++/7721 and C++/7803
- * decl.c (grokdeclarator): Gracefully handle template-name as
- decl-specifier.
+2002-10-10 Jim Wilson <wilson@redhat.com>
+
+ * decl.c (duplicate_decls): Don't call decl_attributes.
2002-10-09 Zack Weinberg <zack@codesourcery.com>
@@ -311,6 +1974,10 @@
(cp_finish_decl): Remove special case for TYPE_DECL with initializer.
(grokdeclarator): Remove redundant error for 'typedef foo = bar'.
+2002-10-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (prune_vtable_vardecl): Delete unused function.
+
2002-10-03 Mark Mitchell <mark@codesourcery.com>
PR c++/7754
@@ -322,23 +1989,17 @@
2002-10-07 Richard Henderson <rth@redhat.com>
- * decl2.c: Complete reversion of c++/7754.
+ * decl2.c, pt.c: Revert c++/7754 fix.
-2002-10-06 Roger Sayle <roger@eyesopen.com>
-
- PR optimization/6627
- * cp/cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition
- from here, and move it to tree.h.
- * cp/decl.c (cxx_init_decl_processing): If storing the vbit
- in function pointers, ensure that force_align_functions_log
- is atleast one.
+2002-10-05 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
-2002-10-04 H.J. Lu (hjl@gnu.org)
+ PR c++/7804
+ * error.c (dump_expr) [REAL_CST]: Output in decimal format.
- * pt.c (tsubst_decl, case VAR_DECL): Back out the last change.
- (tsubst_expr, case DECL_STMT): Likewise.
+2002-10-03 Mark Mitchell <mark@codesourcery.com>
-2002-10-02 Mark Mitchell <mark@codesourcery.com>
+ PR c++/7931
+ * pt.c (for_each_template_parm_r): Handle BASELINKs.
PR c++/7754
* decl2.c (finish_anon_union): Do not expand anonymous unions when
@@ -347,54 +2008,644 @@
type. Call layout_decl.
(tsubst_expr, case DECL_STMT): Handle anonymous unions.
+2002-10-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8006
+ * mangle.c (CLASSTYPE_TEMPLATE_ID_P): Handle instances of template
+ template parameters.
+ (globals): Add entity and need_abi_warning.
+ (decl_is_template_id): Use TYPE_TEMPLATE_INFO, not
+ CLASSTYPE_TEMPLATE_INFO.
+ (is_std_substitution): Use CLASSTYPE_TI_TEMPLATE, not
+ TYPE_TI_TEMPLATE.
+ (write_prefix): Handle typename types correctly.
+ (write_template_prefix): Handle template template parameters
+ correctly.
+ (start_mangling): Add entity parameter.
+ (finish_mangling): Warn about names whose mangling will change.
+ (mangle_decl_string): Adjust.
+ (mangle_type_string): Likewise.
+ (mangle_special_for_type): Likewise.
+ (mangle_ctor_vtbl_for_type): Likewise.
+ (mangle_thunk): Likewise.
+ (mangle_guard_variable): Likewise.
+ (mangle_ref_init_variable): Likewise.
+
2002-10-02 Mark Mitchell <mark@codesourcery.com>
PR c++/7188.
- * init.c (expand_member_init): Allow a FIELD_DECL to be passed in
- directly.
- * pt.c (tsubst_initializer_list): Use expand_member_init.
+ * cp-tree.def (CTOR_INITIALIZER): Use one slot, not two.
+ * cp-tree.h (emit_base_init): Rename to ....
+ (emit_mem_initializers): ... this.
+ (expand_member_init): Change prototype.
+ * init.c (perform_member_init): Compute explicit, rather than
+ requiring it as a parameter.
+ (sort_member_init): Rename to ...
+ (sort_mem_initializers): ... this. Process bases and data members
+ together.
+ (sort_base_init): Remove.
+ (emit_base_init): Rename to ...
+ (emit_mem_initializers): ... this.
+ (expand_aggr_vbase_init_1): Remove.
+ (construct_virtual_bases): Rename to ...
+ (construct_virtual_base): ... this.
+ (expand_member_init): Rework handling of base initializers.
+ * method.c (do_build_copy_constructor): Use
+ finish_mem_initializers.
+ * parse.y (member_init): Adjust calls to expand_member_init.
+ * pt.c (tsubst_expr): Simplify CTOR_INITIALIZER case.
+ (tsubst_initializer_list): Use expand_member_init.
+ * semantics.c (finish_mem_intiailizers): Simplify.
+
+2002-10-02 Matt Austern <austern@apple.com>
+ * decl.c (walk_vtables_r): Fixed typo that caused result to
+ never get a nonzero value.
+
+2002-10-02 Roger Sayle <roger@eyesopen.com>
+
+ PR optimization/6627
+ * cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition
+ from here, and move it to tree.h.
+ * decl.c (cxx_init_decl_processing): If storing the vbit
+ in function pointers, ensure that force_align_functions_log
+ is atleast one.
+
+2002-10-02 Matt Austern <austern@apple.com>
+
+ * class.c (check_field_decls): Changed warning about const member
+ variables so that it doesn't get issued for a class aggregate.
+
+2002-10-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (cp_finish_decl): Make sure array types are laid out,
+ even if the array bounds are unknown.
+
+2002-10-01 Steve Ellcey <sje@cup.hp.com>
+
+ * class.c (build_vtbl_initializer): Change build_c_cast
+ to build1.
+
+2002-10-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (cp_finish_decl): Make sure array types are laid out,
+ even if the array bounds are unknown.
+
+ * decl.c (cp_finish_decl): Correct check for dynamic
+ initialization of thread-local storage.
+
+2002-09-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (really_overloaded_fn): TEMPLATE_ID_EXPRs are also
+ overloaded.
+
+2002-09-30 Steve Ellcey <sje@cup.hp.com>
+
+ * class.c (build_vtbl_initializer): Add cast.
+ (add_vcall_offset_vtbl_entries_1):
+ Use TARGET_VTABLE_DATA_ENTRY_DISTANCE for offset.
+
+2002-09-30 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (walk_subobject_offsets): Correct the calculation of
+ offsets for virtual bases. Correct the counting of array
+ elements.
+ (layout_nonempty_base_or_field): Simplify. Correct the
+ calculation of offsets to be propagated through the binfo
+ hierarchy.
+ (build_base_field): Avoid creating a FIELD_DECL for empty bases.
+ Add the FIELD_DECL to TYPE_FIELDS.
+ (build_base_fields): Adjust accordingly.
+ (layout_virtual_bases): Use build_base_field.
+ (end_of_class): Return a tree, not an integer.
+ (warn_about_ambiguous_direct_bases): Rename to ...
+ (warn_about_ambiguous_bases): ... this.
+ (include_empty_classes): New function.
+ (layout_class_type): Create an alternative version of the type to
+ be used when as a base class type. Do not call
+ finish_record_layout until we are done laying out the class.
+ * cp-tree.h (lang_type_class): Remove size, size_unit. Add
+ as_base.
+ (CLASSTYPE_SIZE): Reimplement.
+ (CLASSTYPE_SIZE_UNIT): Likewise.
+ (CLASSTYPE_ALIGN): Likweise.
+ (CLASSTYPE_USER_ALIGN): Likewise.
+ (CLASSTYPE_AS_BASE): New macro.
+ (DECL_INITIALIZED_P): Likewise.
+ (extract_init): Remove prototype.
+ (build_forced_zero_init): Rename to ...
+ (build_zero_init): ... this.
+ (force_store_init_value): Remove.
+ * decl.c (obscure_complex_init): Remove.
+ (duplicate_decls): Copy DECL_INITIALIZED_P.
+ (check_initializer): Do not leave junk in DECL_INITIAL.
+ (cp_finish_decl): Handle zero-initialization of entities with
+ static storage duration.
+ * expr.c (extract_init): Remove.
+ * init.c (build_forced_zero_init): Remove.
+ (build_zero_init): New function.
+ (build_default_init): Use it.
+ (build_field_list): Skip FIELD_DECLs for base subobjects.
+ (push_base_cleanups): Likewise.
+ * method.c (do_build_assign_ref): Likewise.
+ (synthesize_exception_spec): Likewise.
+ * pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
+ (regenerate_decl_from_template): To not set DECL_INITIAL for a
+ static data member whose initialization took place in its class.
+ (instantiate_decl): Do not pass an initializer to cp_finish_decl
+ in that situation.
+ * search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
+ (dfs_unuse_fields): Likewise.
+ * tree.c (pod_type_p): Handle error_mark_node.
+ (zero_init_p): Likewise.
+ * typeck.c (lookup_anon_field): Skip FIELD_DECLs for base
+ subobjects.
+ * typeck2.c (store_init_value): Remove #if 0'd code.
+ (force_store_init_value): Remove.
+ (process_init_constructor): Use build_zero_init.
+
+2002-09-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7788
+ * rtti.c (unemitted_tinfo_decl_p): Check it has a field.
+
+2002-09-29 Kazu Hirata <kazu@cs.umass.edu>
+
+ * cp-tree.h: Fix comment typos.
+ * decl.c: Likewise.
+ * pt.c: Likewise.
+
+2002-09-25 Mark Mitchell <mark@codesourcery.com>
+
+ * cp/class.c (contains_empty_class_p): New method.
+ (walk_subobject_offsets): Correct computation of field offset.
+ (layout_empty_base): Correct placement of emtpy base classes.
+ (layout_class_type): Warn about ABI changes.
+
+2002-09-23 Mark Mitchell <mark@codesourcery.com>
+
+ * cp/class.c (layout_virtual_bases): Do not round the size of the
+ type to a multiple of the alignment before laying out virtual bases.
+ (layout_class_type): Correct handling of bit-fields that are wider
+ than their type inside unions. Round the size of the type to a
+ even number of bytes when computing the size without virtual
+ bases.
+ * cp/cp-tree.h (abi_version_at_least): New macro.
+
+2002-09-21 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.2: Likewise.
+ * call.c: Likewise.
+ * class.c: Likewise.
+ * cp-tree.h: Likewise.
+ * cvt.c: Likewise.
+ * decl.c: Likewise.
+ * decl2.c: Likewise.
+ * except.c: Likewise.
+ * friend.c: Likewise.
+ * g++spec.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * mangle.c: Likewise.
+ * method.c: Likewise.
+ * operators.def: Likewise.
+ * optimize.c: Likewise.
+ * pt.c: Likewise.
+ * rtti.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+ * typeck.c: Likewise.
+
+2002-09-18 Devang Patel <dpatel@apple.com>
+
+ * cp/cp-tree.h: New prototype for walk_vtabls().
+ * cp/decl.c (walk_vtables_r): New function.
+ (struct cp_binding_level): Add new members, namespaces,
+ names_size and vtables.
+ (add_decl_to_level): Add decl in namespaces or vtables
+ chain, if conditions match.
+ (walk_vtables): New function.
+ (walk_namespaces_r): Travers separate namespace chain
+ for namespace decls.
+ (wrapup_globals_for_namespace): Use names_size instead
+ of list_length().
+ * cp/decl2.c (finish_file): Use walk_vtables() instead of
+ walk_globals() to walk vtable decls.
+
+2002-09-18 Nathan Sidwell <nathan@codesourcery.com>
+
+ * decl.c (grokdeclarator): Use assert, not internal_error. Don't
+ ICE with invalid pointers & references.
+
+2002-09-17 Zack Weinberg <zack@codesourcery.com>
+
+ * Make-lang.in: Remove all references to the demangler.
+ * cxxfilt.c: Moved to binutils.
+
+2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7718
+ * pt.c (tsubst_decl): Remove assert.
+
+ Remove DR 295 implementation.
+ * pt.c (check_cv_quals_for_unify): Disable function & method cases.
+ * tree.c (cp_build_qualified_type_real): Likewise. Don't warn
+ about ignoring volatile qualifiers.
+
+ * search.c (lookup_member): Correct documentation.
+
+2002-09-16 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (union lang_tree_node): Add chain_next option.
+
+2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ * parse.y (parse_finish_call_expr): Check lookup_member result.
+
+ PR c++/7015
+ * semantic.c (finish_asm_stmt): Fix operand/output_operands
+ thinko.
+ * typeck.c (c_expand_asm_operands): Protect from error_mark_node.
+
+2002-09-15 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7919
+ * call.c (build_over_call): Convert this pointer for fns found by
+ using decls.
+
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.1: Likewise.
+
+2002-09-14 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7768
+ * pt.c (build_template_decl): Copy DECL_DESTRUCTOR_P.
+
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
+
+ * error.c: Fix comment formatting.
+ * except.c: Likewise.
+ * expr.c: Likewise.
+ * friend.c: Likewise.
+ * g++spec.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * mangle.c: Likewise.
+ * method.c: Likewise.
+ * optimize.c: Likewise.
+ * pt.c: Likewise.
+ * rtti.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+ * typeck.c: Likewise.
+ * typeck2.c: Likewise.
+
+2002-09-13 Matt Austern <austern@apple.com>
+
+ PR C++/7828
+ * cp/cp-tree.h, cp/tree.c: New function non_cast_lvalue_p.
+ * cp/call.c: Change call-by-const-reference mechanism to use
+ non_cast_lvalue_p when deciding whether the create a temporary.
+ We need a temporary when passing, e.g. (long) x by const ref.
+
+2002-09-13 Nathan Sidwell <nathan@codesourcery.com>
+
+ * pt.c (unify, ARRAY_TYPE): Element type can be more qualified.
+
+2002-09-13 Kazu Hirata <kazu@cs.umass.edu>
+
+ * decl.c: Fix comment formatting.
+ * decl2.c: Likewise.
+
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
+
+ * call.c: Fix comment formatting.
+ * class.c: Likewise.
+ * cp-lang.c: Likewise.
+ * cp-tree.h: Likewise.
+ * cvt.c: Likewise.
+
+2002-09-11 Zack Weinberg <zack@codesourcery.com>
+
+ * Make-lang.in: Build cp/cxxfilt.o from $(srcdir)/cp/cxxfilt.c,
+ and c++filt from cxxfilt.o + version.o + $(LIBDEPS).
+ * cxxfilt.c: New file: split from libiberty/cplus-dem.c, with
+ minor adjustments (use version_string, eliminate yet another
+ duplicate of xmalloc)
+
+2002-09-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (require_complete_eh_spec_types): Add prototype.
+
+2002-09-05 Jason Merrill <jason@redhat.com>
+
+ * typeck2.c (add_exception_specifier): Only pedwarn for an
+ incomplete type.
+ (require_complete_eh_spec_types): New fn.
+ (cxx_incomplete_type_diagnostic): Also support pedwarning.
+ * typeck.c (complete_type_or_diagnostic): Likewise.
+ * call.c (build_call): Call require_complete_eh_spec_types.
+ * rtti.c (get_pseudo_ti_desc): Give an error rather than aborting
+ on an incomplete type.
2002-09-04 Jakub Jelinek <jakub@redhat.com>
* decl.c (start_cleanup_fn): Clear interface_only before
start_function, restore it afterwards.
-2002-09-01 Alexandre Oliva <aoliva@redhat.com>
+2002-08-31 Jason Merrill <jason@redhat.com>
- * parse.y (sizeof, alignof, typeof): New non-terminals to
- increment skip_evaluation. Replace terminals with them and
- decrement skip_evaluation at the end of rules using them.
- * decl2.c (mark_used): Don't assemble_external if
- skipping evaluation.
+ * cp-lang.c (cp_expr_size): Allow initialization from a
+ CONSTRUCTOR.
-2002-08-31 Jason Merrill <jason@redhat.com>
+2002-08-30 Richard Henderson <rth@redhat.com>
- * cp-lang.c (cp_expr_size): Don't abort.
+ PR opt/7515
+ * tree.c: Include target.h.
+ (cp_cannot_inline_tree_fn): Don't auto-inline functions that
+ don't bind locally.
+ * Makefile.in (tree.o): Update.
2002-08-27 Mark Mitchell <mark@codesourcery.com>
- * cp-tree.h (warn_abi): Declare it.
- * decl.c (warn_abi): Define it.
- (cxx_decode_option): Set it.
* class.c (layout_virtual_bases): Warn about bugs in G++ that
result in incorrect object layouts.
(layout_class_type): Likewise.
+2002-08-24 Matt Austern <austern@apple.com>
+
+ * tree.c (lvalue_p_1): Add argument for whether casts of lvalues
+ are allowable.
+ (real_lvalue_p): Update caller.
+ (lvalue_p): Ditto.
+ (non_cast_lvalue_or_else): New.
+ * tree.h: Declare it.
+ * typeck.c (build_unary_op): Use non_cast_lvalue_or_else.
+
+2002-08-22 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR
+ and COND_EXPR specially; fix error message output.
+
2002-08-22 Jason Merrill <jason@redhat.com>
- PR c++/5607
- * search.c (check_final_overrider): No longer static.
- * class.c (update_vtable_entry_for_fn): Call it.
- * cp-tree.h: Adjust.
+ * pt.c (tsubst_expr): RETURN_EXPR is now RETURN_STMT_EXPR.
+ * semantics.c (nullify_returns_r): Likewise.
- * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
- (cp_expr_size): New fn.
- * call.c (convert_arg_to_ellipsis): Promote non-POD warning to error.
- * typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
+2002-08-17 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ Fix PR/7621
+ * typeck.c (finish_class_member_access_expr): Diagnose cases where
+ name lookup finds nothing.
+
+2002-08-15 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (finish_then_clause): Remove redundant assignment.
+ (finish_if_stmt, begin_switch_stmt, finish_switch_stmt): Move the
+ extra binding level outside the if/switch statement.
+ (finish_while_cond, finish_for_cond): Rewrite complex condition
+ into the loop body.
+
+2002-08-15 Alexandre Oliva <aoliva@redhat.com>
+
+ * parse.y (sizeof, alignof, typeof): New non-terminals to
+ increment skip_evaluation. Replace terminals with them and
+ decrement skip_evaluation at the end of rules using them.
+ * decl2.c (mark_used): Don't assemble_external if
+ skipping evaluation.
+
+2002-08-15 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/7504
+ * parse.y (parse_finish_call_expr): Handle incomplete
+ type used to name a scope.
+
+2002-08-15 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7598
+ * typeck.c (build_unary_op): Fold offsetof idiom. Fixes
+ regression caused by my 2002-08-08 patch.
+
+2002-08-13 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (pushdecl_class_level): Honor requests to bind names to
+ OVERLOADs.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (build_call_from_tree): Fix uninitialized variable.
+ * parse.y (parse_finish_call_expr): Likewise.
+ * repo.c (old_args, old_dir, old_main): Const-ify.
+
+2002-08-11 Gabriel Dos Reis <gdr@nerim.net>
+
+ * decl.c (duplicate_decls): Replace DECL_SOURCE_FILE +
+ DECL_SOURCE_LINE with DECL_SOURCE_LOCATION.
+ * optimize.c (maybe_clone_body): Likewise.
+ * pt.c (tsubst_enum): Likewise.
+ (lookup_template_class): Likewise.
+ * tree.c (cp_copy_res_decl_for_inlining): Likewise.
+
+2002-08-10 Neil Booth <neil@daikokuya.co.uk>
+
+ * lang-specs.h: Remove -ansi.
+
+2002-08-10 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (maybe_dummy_object): Replace // with /* */
+
+2002-08-09 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (standard_conversion): Use build_ptrmem_type.
+ * cp-tree.h (build_ptrmem_type): New function.
+ (adjust_result_of_qualified_name_lookup): Likewise.
+ * decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
+ static data members.
+ (build_ptrmem_type): New function.
+ (grokdeclarator): Do not use build_offset_type when encountering a
+ qualified name.
+ * parse.y (parse_finish_call_expr): Use
+ adjust_result_of_qualified_name_lookup.
+ * search.c (adjust_result_of_qualified_name_lookup): New function.
+ * typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
+ accessing OFFSET_TYPEs directly.
+
+2002-08-08 Mike Stump <mrs@apple.com>
+
+ * call.c (add_builtin_candidate): legal -> valid, illegal -> invalid.
+ (type_decays_to): Likewise.
+ * class.c (find_final_overrider): Likewise.
+ (maybe_note_name_used_in_class): Likewise.
+ * decl.c (current_tmpl_spec_kind): Likewise.
+ (add_binding): Likewise.
+ (push_class_binding): Likewise.
+ (duplicate_decls): Likewise.
+ (layout_var_decl): Likewise.
+ (grokfndecl): Likewise.
+ (grokdeclarator): Likewise.
+ (check_default_argument): Likewise.
+ * decl2.c (handle_class_head): Likewise.
+ * error.c (dump_template_decl): Likewise.
+ * init.c (build_offset_ref): Likewise.
+ * pt.c (check_specialization_scope): Likewise.
+ (determine_specialization): Likewise.
+ (check_explicit_specialization): Likewise.
+ (maybe_check_template_type): Likewise.
+ (process_partial_specialization): Likewise.
+ (check_default_tmpl_args): Likewise.
+ (push_template_decl_real): Likewise.
+ (convert_template_argument): Likewise.
+ (try_class_unification): Likewise.
+ (get_bindings_real): Likewise.
+ (do_decl_instantiation): Likewise.
+ * semantics.c (begin_function_definition): Likewise.
+ (finish_member_declaration): Likewise.
+ (check_multiple_declarators): Likewise.
+ * typeck.c (comp_array_types): Likewise.
+ (comptypes): Likewise.
+ (expr_sizeof): Likewise.
+ (build_binary_op): Likewise.
+ (dubious_conversion_warnings): Likewise.
+ (check_return_expr): Likewise.
+
+2002-08-08 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_class_member_access_expr): Do not return
+ error_mark_node when no error has occurred.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * typeck.c (build_component_addr): Remove.
+ (build_unary_op): Just check it's not a bitfield, and then build
+ an ADDR_EXPR.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * class.c (convert_to_base): Correct check for error_mark_node.
+ (create_vtable_ptr): Remove unused VFUNS_P parm.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp/Make-lang.in (c++.mostlyclean): Remove coverage files.
+
+2002-08-07 Mark Mitchell <mark@codesourcery.com>
+
+ Rework build_component_ref.
+ * call.c (build_vfield_ref): Do not go through build_component_ref.
+ (build_field_call): Use build_class_member_access_expr.
+ (build_user_type_conversion_1): Use BASELINK_FUNCTIONS.
+ (build_object_call): Likewise.
+ * class.c (convert_to_base): New function.
+ (type_requires_array_cookie): Use BASELINK_FUNCTIONS.
+ (instantiate_type): Handle BASELINKs.
+ * cp-tree.def (BASELINK): New tree code.
+ * cp-tree.h (BASELINK_P): Reimplement.
+ (SET_BASELINK_P): Remove.
+ (BASELINK_BINFO): Reimplement.
+ (BASELINK_FUNCTIONS): Likewise.
+ (BASELINK_ACCESS_BINFO): Likewise.
+ (BASELINK_OPTYPE): Likewise.
+ (convert_to_base): New function.
+ (name_p): Likewise.
+ (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_component_ref): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ * decl.c (grokdeclarator): Handle BASELINKs.
+ * decl2. (build_expr_from_tree): Handle COMPONENT_REFs by using
+ finish_class_member_access_expr.
+ (arg_assoc): Handle BASELINKs.
+ (do_class_using_decl): Likewise.
+ * error.c (dump_decl): Likewise.
+ (dump_expr): Use build_ptrmemfunc_access_expr.
+ * except.c (dtor_nothrow): Use CLASSTYPE_DESTRUCTORS to find
+ destructors.
+ (build_throw): Use BASELINK_FUNCTIONS.
+ * init.c (perform_member_init): Use
+ build_class_member_access_expr.
+ (build_offset_ref): Handle BASELINKs. Use
+ build_class_member_access_expr.
+ * method.c (hack_identifier): Likewise.
+ * parse.y (do_id): Use BASELINK, not TREE_LIST.
+ (primary): Remove uses of build_object_ref.
+ * pt.c (lookup_template_function): Handle BASELINKs.
+ (resolve_overloaded_unification): Likewise.
+ * search.c (build_baselink): Build a BASELINK, not a TREE_LIST.
+ (lookup_field): Use BASELINK, not TREE_LIST.
+ (lookup_fnfiels): Likewise.
+ (setup_class_bindings): Likewise.
+ * semantics.c (finish_object_call_expr): Do not use
+ build_method_call when we already know what function is being
+ called.
+ * spew.c (identifier_type): Use BASELINK, not TREE_LIST.
+ * tree.c (really_overloaded_fn): Use OVL_CHAIN for OVERLOADs, not
+ TREE_CHAIN.
+ (name_p): New function.
+ * typeck.c (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ (get_member_function_from_ptrfunc): Use
+ build_ptrmemfunc_access_expr.
+ (build_binary_op): Likewise.
+ (build_unary_op): Likewise.
+ (build_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+ * typeck2.c (build_m_component_ref): Adjust comment.
+
+2002-08-07 Neil Booth <neil@daikokuya.co.uk>
+
+ * Make-lang.in (CXX_C_OBJS): Update.
+ * cp-lang.c (LANG_HOOKS_DECODE_OPTION): Use c_common_decode_option.
+ * cp-tree.h (cxx_decode_option): Remove.
+ * decl2.c (compare_options, lang_f_options, unsupported_options,
+ cxx_decode_option): Remove.
+
+2002-08-06 Gabriel Dos Reis <gdr@nerim.net>
+
+ * typeck.c (build_x_unary_op): Handle pointer-to-member.
-2002-08-14 Release Manager
+2002-08-05 Geoffrey Keating <geoffk@redhat.com>
- * GCC 3.2 Released.
+ * class.c: Don't include obstack.h.
+ (popclass):
+ * decl2.c: Delete bogus comment.
+ * error.c: Don't include obstack.h.
+ * except.c: Likewise.
+ (dump_type): Correct comment.
+ * method.c: Don't include obstack.h.
+ * tree.c: Likewise.
+
+2002-08-04 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/2213
+ * cvt.c (cp_convert_to_pointer): Reject conversions from integral
+ expressions to pointer-to-data-member of pointer-to-member-functions.
+
+2002-08-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * cvt.c (ocp_convert): Delete obsolete code.
+ * parse.y (permanent_obstack): Delete declaration.
+ * pt.c (permanent_obstack): Delete declaration.
+ * repo.c (permanent_obstack): Delete declaration.
+ (open_repo_file): Use xmalloc instead of permanent_obstack.
+ (init_repo): Use xstrdup instead of permanent_obstack.
+
+2002-08-04 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (VF_DERIVED_VALUE): Remove.
+ * class.c (finish_struct_1): Use VF_BINFO_VALUE not VF_DERIVED_VALUE.
2002-08-03 Nathan Sidwell <nathan@codesourcery.com>
@@ -409,82 +2660,284 @@
(layout_class_type): Take single list of virtuals. Adjust.
(finish_struct_1): Keep virtuals on single list. Adjust.
+2002-08-02 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_member_call): Use build_new_method_call, not
+ build_method_call.
+
+2002-08-02 Krister Walfridsson <cato@df.lth.se>
+
+ * Make-lang.in (spew.o, lex.o, pt.o): Add path to parse.h dependencies.
+
+2002-08-02 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_method_call): Issue a more helpful error message
+ about ambiguous method names.
+
+2002-08-02 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (build_shared_int_cst): Make cache file scope, and
+ GTY it.
+
+2002-08-02 Jason Merrill <jason@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
+ (cp_expr_size): New fn.
+ * call.c (build_over_call): Lose empty class hackery.
+ (convert_arg_to_ellipsis): Promote non-POD warning to error.
+ * typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
+
+ * semantics.c (expand_body): Do tree optimization in the function
+ context, too.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h: Move all warning and flag declarations to c-common.h.
+ * decl.c: Move all warning and flag variables to c-common.c.
+ * decl2.c: Move all warning and flag variables to c-common.c.
+ * lex.c (flag_digraphs): Remove.
+ (warn_traditional): Now in c-common.c.
+
+2002-07-31 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_field_call): Do not look up the field by name.
+ (build_method_call): Simplify.
+ (struct z_candidate): Add access_path and conversion_path. Remove
+ basetype_path.
+ (convert_class_to_reference): Adjust use of
+ add_function_candidate.
+ (add_candidate): Add conversion_path argument.
+ (add_function_candidate): Use it.
+ (add_conv_dndidate): Likewise.
+ (build_builtin_candidate): Likewise.
+ (add_template_candidate_real): Add conversion_path argument.
+ (add_template_conv_candidate): Likewise.
+ (add_template_candidate): Likewise.
+ (build_user_type_conversion_1): Use it.
+ (build_new_function_call): Remove name lookup code. Adjust use of
+ add_template_candidate and add_function_candidate.
+ (build_new_op): Likewise.
+ (convert_like_real): Use build_special_member_call.
+ (build_over_call): Use cand->conversion_path.
+ (build_special_member_call): New method.
+ (build_new_method_call): Remove name lookup code.
+ * cp-tree.def (OFFSET_REF): Update documentation.
+ (TEMPLATE_ID_EXPR): Likewise.
+ * cp-tree.h (BASELINK_ACCESS_BINFO): New macro.
+ (BASELINK_OPTYPE): Likewise.
+ (build_new_method_call): Adjust prototype.
+ (build_special_member_call): New method.
+ (build_baselink): New method.
+ (build_offset_ref_call_from_tree): Likewise.
+ (build_call_from_tree): Likewise.
+ (finish_qualified_call_expr): Remove.
+ (finish_call_expr): Adjust prototype.
+ (build_x_function_call): Remove.
+ * cvt.c (ocp_convert): Use build_special_member_call.
+ * decl2.c (reparse_absdcl_as_expr): Use finish_call_expr.
+ (build_expr_from_tree): Adjust handling for TEMPLATE_ID_EXPR and
+ CALL_EXPR.
+ (build_offset_ref_call_from_tree): New function.
+ (build_call_from_tree): Likewise.
+ * init.c (expand_cleanup): Use build_special_member_call.
+ (expand_default_init): Likewise.
+ (build_member_call): Use finish_call_expr.
+ (build_new_1): Use build_special_member_call.
+ (push_base_cleanups): Likewise.
+ * method.c (do_build_assign_ref): Likewise.
+ * parse.y (template_id): Do not pass a COMPONENT_REF to
+ lookup_template_function.
+ (primary): Use parse_finish_call_epxr, not finish_call_expr.
+ (parse_finish_call_expr): New function.
+ * pt.c (lookup_template_function): Add assertions.
+ * search.c (lookup_base): Allow T to be a binfo.
+ (build_baselink): New function.
+ (lookup_member): Use it.
+ * semantics.c (finish_call_expr): Do not do name lookup.
+ (finish_object_call_expr): Remove #if 0'd code.
+ (finish_qualified_call_expr): Remove.
+ * typeck.c (build_x_function_call): Remove.
+ (build_static_case): Use build_special_member_call.
+ * typeck2.c (build_functional_cast): Likewise.
+
2002-07-30 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* lang-specs.h: Remove __GXX_ABI_VERSION, moved to gcc.c.
-2002-07-17 Scott Snyder <snyder@fnal.gov>
+2002-07-30 Gabriel Dos Reis <gdr@nerim.net>
- PR c++/7320
- * rtti.c (get_tinfo_decl): Set DECL_COMDAT.
+ * cp-tree.h (VF_DERIVED_VALUE): Restore from previous deletion.
-2002-07-05 Nathan Sidwell <nathan@codesourcery.com>
+2002-07-30 Nathan Sidwell <nathan@codesourcery.com>
- Repair damage on weak-impared targets caused by my previous patch.
- * cp-tree.h (import_export_tinfo): Add parameter.
- * decl2.c (import_export_tinfo): Add parameter, post adjust
- DECL_COMDAT.
- * rtti.c (emit_tinfo_decl): DECL_COMDAT is (nearly) always setup by
- import_export_tinfo.
+ * cp-tree.h (CLASSTYPE_VFIELDS, VF_*, BV_*): Add more
+ documentation.
-2002-06-30 Nathan Sidwell <nathan@codesourcery.com>
+2002-07-29 Alan Modra <amodra@bigpond.net.au>
- * cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
- (CPTI_TYPE_INFO_PTR_TYPE): ... this.
- (tinfo_decl_type): Replace with ...
- (type_info_ptr_type): ... this.
- (import_export_tinfo): Declare.
- (tinfo_decl_p): Rename to ...
- (unemitted_tinfo_decl_p): ... this.
- * decl2.c (import_export_decl): Break out tinfo handling into ...
- (import_export_tinfo): ... here. New function.
- (finish_file): Adjust.
- * rtti.c (TINFO_REAL_NAME): New macro.
- (init_rtti_processing): Create the tinfo types.
- (get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
- (get_tinfo_decl): Adjust.
- (get_tinfo_ptr): New function.
- (get_type_id): Use it.
- (tinfo_base_init): Create vtable decl here, if it doesn't exist.
- (ptr_initializer): Use get_tinfo_ptr.
- (ptm_initializer): Likewise.
- (synthesize_tinfo_var): Break into ...
- (get_pseudo_ti_init): ... this. Just create the initializer.
- (get_pseudo_ti_desc): .. and this.
- (create_real_tinfo_var): Remove.
- (create_pseudo_type_info): Don't create the vtable decl here.
- (get_vmi_pseudo_type_info): Remove.
- (create_tinfo_types): Adjust.
- (tinfo_decl_p): Rename to ...
- (unemitted_tinfo_decl_p): ... here. Adjust.
- (emit_tinfo_decl): Adjust. Create the initializer.
+ * cp-tree.h: Comment typo fix.
-2002-06-14 Jason Merrill <jason@redhat.com>
+2002-07-29 Richard Earnshaw <rearnsha@arm.com>
- C++ ABI changes.
- * class.c (build_base_field): Set DECL_PACKED.
- (layout_class_type): Don't use tail padding of PODs.
- * mangle.c (write_unqualified_name): Fix template conversion op
- mangling.
+ * spew.c (space_for_token): Allocate zeroed memory for a new token
+ chunk.
-2002-05-18 Jason Merrill <jason@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- PR c++/6611
- * decl2.c (import_export_decl): If we clear
- DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+ * decl.c (builtin_function_1): No need to explicitly mark
+ BUILT_IN_RETURN and BUILT_IN_EH_RETURN as noreturn.
-2002-05-14 Jason Merrill <jason@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- * rtti.c (get_tinfo_decl): Don't call comdat_linkage.
- Do set DECL_COMDAT.
- (synthesize_tinfo_var): Take the public decl.
- (create_real_tinfo_var): Likewise. Check DECL_COMDAT.
- (emit_tinfo_decl): Adjust. Call import_export_decl.
- * decl2.c (import_export_decl): Simplify tinfo decl handling.
+ * decl2.c (cxx_decode_option): Support -fno-builtin-foo.
+
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * call.c (build_over_call): Likewise.
+ (cp_convert_parm_for_inlining): New fn.
+ (convert_for_arg_passing): New fn.
+ (convert_default_arg, build_over_call): Use it.
+ (type_passed_as): New fn.
+ * pt.c (tsubst_decl): Use it.
+ * decl2.c (cp_build_parm_decl): New fn.
+ (build_artificial_parm): Use it.
+ (start_static_storage_duration_function): Likewise.
+ * decl.c (start_cleanup_fn, grokdeclarater): Likewise.
+ (grokparms): Don't mess with DECL_ARG_TYPE.
+ * typeck.c (convert_arguments): Use convert_for_arg_passing.
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Define.
+ * cp-tree.h: Declare new fns.
+
+2002-07-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h (flag_operator_names): Remove.
+ * decl2.c (flag_operator_names): Remove.
+ (lang_f_options): Remove operator-names.
+ * lex.c (D_OPNAME): Remove.
+ (reswords): Remove operator names.
+ (rid_to_yy): Remove operator names.
+ (init_reswords): No need to handle D_OPNAME.
+ * spew.c (read_process_identifier): There are no operator
+ names.
+
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * dump.c (cp_dump_tree): Call c_dump_tree.
+ * Make-lang.in (CXX_C_OBJS): Add c-dump.o.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * error.c (print_whitespace): Remove.
+ * g++spec.c (LIBUNWIND): Move.
+ * mangle.c (mangled_position, write_signed_number): Remove.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * decl2.c (cxx_decode_option): Similarly.
+
+2002-07-25 Gabriel Dos Reis <gdr@nerim.net>
+
+ * cp-tree.h (cxx_sizeof_nowarn): Now a macro.
+ (cxx_sizeof_or_alignof_type): Take a third argument.
+ (cxx_sizeof): Adjust definition.
+ (cxx_alignof): Likewise.
+ * init.c (build_delete): Use cxx_sizeof_nowarn to reflect reality.
+ * typeck.c (cxx_sizeof_or_alignof_type): Take a third argument for
+ complaining.
+ (c_sizeof_nowarn): Remove definition.
+ (build_unary_op): Use cxx_sizeof_nowarn.
+
+2002-07-24 Geoffrey Keating <geoffk@redhat.com>
+
+ * tree.c (cp_build_qualified_type_real): When copying
+ pointer-to-method types, unshare the record that holds
+ the cached pointer-to-member-function type.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h (FILE_FUNCTION_PREFIX_LEN): Remove.
+
+2002-07-23 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/7363:
+ * typeck.c (cxx_sizeof_or_alignof_type): New function.
+ (c_sizeof): Remove definition.
+ (expr_sizeof): Use cxx_sizeof.
+ * decl2.c (build_expr_from_tree): Use cxx_sizeof_or_alignof_type.
+ * decl.c (finish_destructor_body): Use cxx_sizeof.
+ * semantics.c (finish_alignof): Likewise.
+ (finish_alignof): Use cxx_alignof.
+ * cp-tree.h (cxx_sizeof, cxx_alignof): New macros.
+ (cxx_sizeof_or_alignof_type): Declare.
+ (my_friendly_assert): Move to ../c-common.h.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * class.c, method.c, pt.c, search.c: Don't define obstack macros.
+
+2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/7347, c++/7348
+ * cp-tree.h (tsubst_flags_t): Add tf_parsing.
+ * decl.c (make_typename_type): Use it.
+ (make_unbound_class_template): Likewise.
+ (lookup_name_real): Don't call type_access_control if scope is
+ template parameter dependent.
+ * parse.y (template_arg): Call make_unbound_class_template with
+ tf_parsing set.
+ (nest_name_specifier): Call make_typename_type with tf_parsing set.
+ (typename_sub0): Likewise.
+ (typename_sub1): Likewise.
+ (instantiate_decl): Push class scope.
+ * pt.c (regenerate_decl_from_template): Call pushclass and popclass
+ for both static variable and member function template.
+ (instantiate_decl) Call pushclass and popclass when tsubst'ing type
+ and arguments.
+ * search.c (type_access_control): Do type access for TEMPLATE_DECL
+ too.
-2002-07-25 Release Manager
+2002-07-20 Roger Sayle <roger@eyesopen.com>
- * GCC 3.1.1 Released.
+ * decl2.c (cxx_decode_option): Simplify -fhandle-exceptions
+ test by using positive_option. Make whitespace consistent.
+
+2002-07-20 Gabriel Dos Reis <gdr@nerim.net>
+
+ * spew.c (struct unparsed_test): Replace 'filename' and 'lineno'
+ members with 'locus'. Adjust use throughout.
+ (struct feed): Likewise.
+ (alloc_unparsed_test): Change prototype, take a 'const location_t *'.
+ Adjust use.
+ (snarf_defarg): Use error(), not error_with_file_and_line().
+
+2002-07-19 Chris Demetriou <cgd@broadcom.com>
+
+ * lang-specs.h (@c++): Include "%2" (cc1plus_spec) wherever
+ cpp_options is included.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/2862, c++/2863
+ * pt.c (determine_specialization): Compare the length of
+ TYPE_ARG_TYPES. Tidy.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/3797
+ * decl.c (duplicate_decls): Don't propagate inlining parameters from
+ olddecl to newdecl when newdecl is a specialization of the
+ instantiation olddecl.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/4802, c++/5387
+ * decl.c (make_typename_type): Use enforce_access.
+
+2002-07-17 Scott Snyder <snyder@fnal.gov>
+
+ PR c++/7320
+ * rtti.c (get_tinfo_decl): Set DECL_COMDAT.
2002-07-12 Mark Mitchell <mark@codesourcery.com>
@@ -501,21 +2954,77 @@
* tree.c (cp_copy_res_decl_for_inlining): Also copy
TREE_ADDRESSABLE.
+2002-07-10 Graham Stott <graham.stott@btinternet.com>
+
+ * pt.c (template_parm_this_level_p, push_template_decl_real):
+ Pass depth as int pointer.
+
+2002-07-11 Tim Josling <tej@melbpc.org.au>
+
+ Remove front end hard coding from gengtype.c.
+
+ * config-lang.in (gtfiles): Add files needed for this front end.
+
+2002-07-10 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (unqualified_name_lookup_error): Declare it.
+ (begin_function_definition): Adjust prototype.
+ * lex.c (unqualified_name_lookup_error): New function, split out
+ from ...
+ (do_identifier): ... here.
+ * parse.y (parse_begin_function_definition): New function.
+ (fn.def1): Use it.
+ * semantics.c (begin_function_definition): Accept decl-specifiers
+ and attributes as separate parameters.
+
2002-07-10 Jason Merrill <jason@redhat.com>
PR c++/6255
* decl.c (lookup_name_real): Build a new TYPENAME_TYPE rather than
modifying the old one.
+2002-07-09 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (constructor_name_p): Declare it.
+ (check_template_template_default_arg): Likewise.
+ * class.c (handle_using_decl): Use constructor_name_p.
+ * decl.c (grokdeclarator): Likewise.
+ * decl2.c (constructor_name_p): Define it.
+ * init.c (build_member_call): Use constructor_name_p.
+ * parse.y (template_parm): Use check_template_template_default_arg.
+ * pt.c (check_explicit_specialization): Use constructor_name_p.
+ * semantics.c (check_template_template_default_arg): New function.
+
2002-07-08 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* pt.c (can_complete_type_without_circularity): Add static to
function definition.
-2002-07-05 Jim Wilson <wilson@redhat.com>
+2002-07-08 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (have_extern_spec): Declare it
+ * decl.c (have_extern_spec): Define it.
+ (start_decl): Eliminate use of used_extern_spec.
+ (start_function): Likewise.
+ * parse.y (have_extern_spec): Remove declaration.
+ (used_extern_spec): Likewise.
+ (frob_specs): Eliminate use of used_extern_spec.
+ (.hush_warning): Likewise.
+
+2002-07-07 Mark Mitchell <mark@codesourcery.com>
+
+ * Make-lang.in (cp/parse.o): Depend on decl.h.
+ * cp-tree.h (do_decl_instantiation): Change prototype.
+ * parse.y: Include decl.h.
+ (parse_decl_instantiation): New function.
+ (explicit_instantiation): Use it.
+ * pt.c (do_decl_instantiation): Accept a DECL, not a DECLARATOR
+ and DECLSPECS.
- * decl.c (mark_named_label_lists): Add missing & in call to
- mark_binding_level.
+2002-07-07 Roger Sayle <roger@eyesopen.com>
+
+ * error.c (dump_function_name): Use DECL_TEMPLATE_RESULT for
+ constructor and destructor tests when passed a TEMPLATE_DECL.
2002-07-05 Jason Merrill <jason@redhat.com>
@@ -525,11 +3034,14 @@
PR optimization/7145
* tree.c (cp_copy_res_decl_for_inlining): Also copy DECL_INITIAL.
-2002-05-18 Jason Merrill <jason@redhat.com>
+2002-07-05 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/6611
- * decl2.c (import_export_decl): If we clear
- DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+ Repair damage on weak-impared targets caused by my previous patch.
+ * cp-tree.h (import_export_tinfo): Add parameter.
+ * decl2.c (import_export_tinfo): Add parameter, post adjust
+ DECL_COMDAT.
+ * rtti.c (emit_tinfo_decl): DECL_COMDAT is (nearly) always setup by
+ import_export_tinfo.
2002-07-03 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
@@ -539,13 +3051,22 @@
(build_vec_init): Flatten multi-dimensional array during cleanup.
(build_vec_delete_1): Abort if the type of each element is array.
+2002-07-03 Graham Stott <graham.stott@btinternet.com>
+
+ * pt.c (instantiate_class_template): Fix typo.
+
+2002-07-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * typeck2.c (cxx_incomplete_type_diagnostic): Fix typo caused
+ by CVS conflict in my last patch.
+
2002-07-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6716
* pt.c (can_complete_type_without_circularity): New function.
(instantiate_class_template): Use it.
- * typeck2.c (incomplete_type_error): Improve error message
- due to incomplete fields.
+ * typeck2.c (cxx_incomplete_type_diagnostic): Improve error
+ message due to incomplete fields.
2002-07-01 Mark Mitchell <mark@codesourcery.com>
@@ -554,23 +3075,137 @@
applied to a type.
* operators.def: Remove stale comment.
+2002-06-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
+ (CPTI_TYPE_INFO_PTR_TYPE): ... this.
+ (tinfo_decl_type): Replace with ...
+ (type_info_ptr_type): ... this.
+ (import_export_tinfo): Declare.
+ (tinfo_decl_p): Rename to ...
+ (unemitted_tinfo_decl_p): ... this.
+ * decl2.c (import_export_decl): Break out tinfo handling into ...
+ (import_export_tinfo): ... here. New function.
+ (finish_file): Adjust.
+ * rtti.c (TINFO_REAL_NAME): New macro.
+ (init_rtti_processing): Create the tinfo types.
+ (get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
+ (get_tinfo_decl): Adjust.
+ (get_tinfo_ptr): New function.
+ (get_type_id): Use it.
+ (tinfo_base_init): Create vtable decl here, if it doesn't exist.
+ (ptr_initializer): Use get_tinfo_ptr.
+ (ptm_initializer): Likewise.
+ (synthesize_tinfo_var): Break into ...
+ (get_pseudo_ti_init): ... this. Just create the initializer.
+ (get_pseudo_ti_desc): .. and this.
+ (create_real_tinfo_var): Remove.
+ (create_pseudo_type_info): Don't create the vtable decl here.
+ (get_vmi_pseudo_type_info): Remove.
+ (create_tinfo_types): Adjust.
+ (tinfo_decl_p): Rename to ...
+ (unemitted_tinfo_decl_p): ... here. Adjust.
+ (emit_tinfo_decl): Adjust. Create the initializer.
+
2002-06-27 Mark Mitchell <mark@codesourcery.com>
PR c++/6695
* pt.c (tsubst_friend_class): Substitute into the context of the
friend before using it.
+2002-06-26 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (xref_tag): Change prototype.
+ (handle_class_head): Likewise.
+ (build_x_component_ref): Likewise.
+ * decl.c (cxx_init_decl_processing): Adjust call to xref_tag.
+ (xref_tag): Take attributes as a separate parameter.
+ (xref_tag_from_type): Adjust call to xref_tag.
+ * decl2.c (build_expr_from_tree): Adjust call to
+ build_x_component_ref.
+ (handle_class_head): Take attributes as a separate parameter.
+ * parse.y (parse_xref_tag): New function.
+ (parse_handle_class_head): Likewise.
+ (primary): Use parse_xref_tag.
+ (class_head_decl): Use parse_handle_class_head.
+ (class_head_defn): Likewise.
+ * rtti.c (init_rtti_processing): Adjust call to xref_tag.
+ (build_dynamic_cast_1): Likewise.
+ (create_pseudo_type_info): Likewise.
+ (emit_support_tinfos): Likewise.
+ * typeck.c (build_object_ref): Adjust call to
+ build_x_component_ref.
+ (build_x_component_ref): Remove protect parameter.
+
+2002-06-25 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_op_delete_call): Use BASELINK_FUNCTIONS.
+ * class.c (handle_using_decl): Likewise.
+ (instantiate_type): Likewise.
+ * cp-tree.h (BASELINK_FUNCTIONS): New macro.
+ (xref_basetypes): Change prototype.
+ (begin_mem_initializers): New function.
+ (get_overloaded_fn): Likewise.
+ * decl.c (xref_basetypes): Simplify.
+ * error.c (dump_expr): Use BASELINK_FUNCTIONS.
+ * init.c (build_offset_ref): Likewise.
+ * parse.y (base_init): Use begin_mem_initializers().
+ (structsp): Adjust call to xref_basetypes.
+ * pt.c (determine_specialization): Use BASELINK_FUNCTIONS.
+ (instantiate_class_template): Adjust call to xref_basetypes.
+ * semantics.c (begin_mem_initializers): New function.
+ * tree.c (is_overloaded_fn): Use BASELINK_FUNCTIONS.
+ (really_overlaoded_fn): Likewise.
+ (get_overloaded_fn): New function.'
+ (get_first_fn): USe BASELINK_FUNCTIONS.
+
+2002-06-24 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (SCALAR_TYPE_P): New macro.
+ (check_for_out_of_scope_variable): New function.
+ (at_class_scope_p): Likewise.
+ (finish_fname): Likewise.
+ * class.c (finish_struct): Use at_function_scope_p.
+ * decl.c (check_for_out_of_scope_variable): New function, split
+ out from do_identifier.
+ (finish_enum): Use at_function_scope_p.
+ * lex.c (do_identifier): Use check_for_out_of_scope_variable.
+ * parse.y (VAR_FUNC_NAME): Give it <ttype>. Use finish_fname.
+ (primary): Use at_function_scope_p.
+ * search.c (at_class_scope_p): New function.
+ * semantics.c (finish_fname): Likewise.
+ (check_multiple_declarators): Use at_function_scope_p.
+
+2002-06-23 Mark Mitchell <mark@codesourcery.com>
+
+ * parse.y (parse_scoped_id): New function.
+ (primary): Use it.
+ * cp-tree.h (do_scoped_id): Adjust declaration.
+ * lex.c (do_scoped_id): Remove call to yylex.
+ * decl2.c (build_expr_from_tree): Adjust use of do_scoped_id.
+ * typeck2.c (add_exception_specifier): Use tree_cons, rather than
+ expanding it inline.
+
2002-06-23 Matt Thomas <matt@3am-software.com>
* decl.c (finish_function): Change "#ifdef VMS_TARGET" to
"#if VMS_TARGET".
+2002-06-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mangle.c (integer_type_codes): Const-ify.
+
2002-06-20 Richard Henderson <rth@redhat.com>
PR c++/6747
* typeck.c (mark_addressable): Don't test TREE_ADDRESSABLE early.
Call put_var_into_stack.
+2002-06-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * spew.c (remove_last_token): Use ARRAY_SIZE in lieu of explicit
+ array size calculation.
+
2002-06-20 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6892
@@ -583,22 +3218,349 @@
BOUND_TEMPLATE_TEMPLATE_PARM if appeared as a default template
argument.
+2002-06-19 Akim Demaille <akim@epita.fr>
+
+ * parse.y (TYPENAME): Rename as tTYPENAME to avoid the clash with
+ decl.h's TYPENAME.
+ * spew.c, lex.c: Adjust.
+ * parse.y (explicit_instantiation): Add empty action to override
+ the default $$ = $1 where it introduces a type clash.
+
+2002-06-14 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (begin_for_stmt): Push the 'for' scope before
+ adding the FOR_STMT.
+
+ C++ ABI changes.
+ * class.c (build_base_field): Set DECL_PACKED.
+ (layout_class_type): Don't use tail padding of PODs.
+ * mangle.c (write_unqualified_name): Fix template conversion op
+ mangling.
+
2002-06-16 Richard Henderson <rth@redhat.com>
PR opt/6793
* tree.c (cp_cannot_inline_tree_fn): Don't short-circuit test
after template instantiation.
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * cp-tree.h, decl2.c (flag_ms_extensions): Move to c-common.
+
+2002-06-15 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * cp-tree.h (compiler_error): Remove declaration.
+ * lex.c (compiler_error): Remove definition.
+
+2002-06-14 Steve Ellcey <sje@cup.hp.com>
+
+ * g++spec.c (LIBUNWIND): New.
+ (lang_specific_driver): Add it if USE_UNWIND_EXCEPTIONS is set.
+
+2002-06-13 Jessica Han <jessica@cup.hp.com>
+
+ * class.c (build_vtable): Use TARGET_VTABLE_ENTRY_ALIGN.
+ (build_vtbl_initializer): Honor TARGET_VTABLE_DATA_ENTRY_DISTANCE.
+ (build_vbase_offset_vtbl_entries): Likewise.
+ * rtti.c (build_headof): Likewise.
+ (get_tinfo_decl_dynamic): Likewise.
+ (create_pseudo_type_info): Likewise.
+
+2002-06-12 Stan Shebs <shebs@apple.com>
+
+ * mpw-config.in: Remove file, no longer used.
+ * mpw-make.sed: Ditto.
+
+2002-06-07 Zack Weinberg <zack@codesourcery.com>
+
+ * decl2.c: Update call to cpp_handle_option.
+
2002-06-07 H.J. Lu (hjl@gnu.org)
* decl2.c (flag_use_cxa_atexit): Set to DEFAULT_USE_CXA_ATEXIT.
+2002-06-06 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * error.c (cp_error_at): Fix typo.
+
+2002-06-04 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * error.c (cp_diagnostic_starter): Adjust call.
+ (maybe_print_instantiation_context): Change prototype to take a
+ 'diagnostic_info *'.
+ (print_instantiation_full_context): Likewise.
+ (print_instantiation_partial_context): Likewise.
+ (cp_diagnostic_starter): Likewise.
+ (cp_diagnostic_finalizer): Likewise.
+ (cp_print_error_function): Likewise.
+ (cp_printer): Take a secondary parameter as a 'text_info *'.
+ Remove output_state savings. Adjust calls.
+
+2002-06-03 Geoffrey Keating <geoffk@redhat.com>
+
+ * pt.c (inline_parm_levels): Mark for GC.
+
+ * mangle.c (start_mangling): Allocate G.substitutions here...
+ (init_mangle): ... rather than here.
+ (finish_mangling): Clear the varray pointer when done with it.
+ * spew.c (yylexstring): Don't use VARRAY_FREE.
+ * search.c (bfs_walk): Don't use VARRAY_FREE.
+ * decl2.c (pending_statics): Use gengtype to mark.
+ (deferred_fns): Likewise.
+ (ssdf_decls): Likewise.
+ (init_decl2): Delete.
+ * decl.c (pop_from_top_level): Don't use VARRAY_FREE.
+ (cxx_init_decl_processing): Don't call init_decl2.
+ (cxx_pop_function_context): Don't use VARRAY_FREE.
+ * cp-tree.h (struct saved_scope): No need for special marking
+ of varrays.
+ (struct language_function): Likewise.
+ (local_classes): Use gengtype to mark.
+ (init_decl2): Delete prototype.
+ * class.c (init_class_processing): Don't use
+ ggc_add_tree_varray_root.
+ (build_vtbl_initializer): Don't use VARRAY_FREE.
+
+ * decl.c (typename_compare): Don't use same_type_p.
+
+ * decl.c: Include hashtab.h instead of hash.h.
+ (typename_hash): Update to use htab_h.
+ (typename_compare): Likewise.
+ (typename_htab): Use gengtype to mark.
+ (build_typename_type): Update to use htab_h.
+ * Make-lang.in (cp/decl.o): Use HASHTAB_H instead of hash.h.
+
+ * Make-lang.in (gt-cp-tree.h): New rule.
+ (cp/tree.o): Depend on gt-cp-tree.h.
+ * config-lang.in (gtfiles): Add cp/tree.c.
+ * tree.c: Include gt-cp-tree.h.
+ (list_hash_table): Use gengtype to mark.
+ (init_tree): Use gengtype to mark trees.
+
+ * Make-lang.in (cp/decl.o): Add debug.h dependency.
+ * call.c (struct z_candidate): Use gengtype.
+ (USER_CONV_CAND): Use WRAPPER_ZC.
+ (convert_class_to_reference): Use build_zc_wrapper.
+ (build_type_conversion_1): Likewise.
+ (build_over_call): Use WRAPPER_ZC.
+ (add_warning): Use build_zc_wrapper.
+ * cp-lang.c (LANG_HOOKS_MARK_TREE): Delete.
+ * cp-tree.h (struct lang_identifier): Use gengtype.
+ (struct template_parm_index_s): Likewise.
+ (struct ptrmem_cst): Likewise.
+ (struct tree_binding): Likewise.
+ (struct tree_overload): Likewise.
+ (struct tree_srcloc): Likewise.
+ (struct tree_wrapper): Likewise. Also modify to have a pointer
+ to struct z_candidate rather than void.
+ (enum cp_tree_node_structure_enum): New.
+ (union lang_tree_node): New.
+ (cxx_mark_tree): Delete prototype.
+ (cp_tree_node_structure): New prototype.
+ (build_ptr_wrapper): Delete prototype.
+ (build_int_wrapper): Delete prototype.
+ (build_zc_wrapper): New prototype.
+ * decl.c: Include debug.h
+ (cxx_mark_tree): Delete.
+ (cp_tree_node_structure): New.
+ * tree.c (build_ptr_wrapper): Delete.
+ (build_int_wrapper): Delete.
+ (build_zc_wrapper): New.
+
+ * cp-tree.h [! ENABLE_TREE_CHECKING] (LANG_TYPE_PTRMEM_CHECK):
+ Correct typo. Patch from k_fukui@highway.ne.jp.
+
+ * semantics.c (current_stmt_tree): Update for change to
+ struct language_function.
+ (finish_mem_initializers): Likewise.
+ * decl.c (cxx_init_decl_processing): Don't set mark_lang_status.
+ * cp-tree.h (struct language_function): Rename from
+ cp_language_function. Change all uses.
+ (cp_function_chain): Don't need to cast.
+
+ * class.c (duplicate_tag_error): Reset discriminator.
+ (check_bases_and_members): Update for data structure changes.
+ * cp-tree.h (struct lang_id2): Use gengtype.
+ (flagged_type_tree): Likewise.
+ (SET_LANG_ID): Use GGC on struct lang_id2.
+ (struct cp_language_function): Use gengtype. Remove field
+ 'x_vcalls_possible_p'.
+ (current_vcalls_possible_p): Delete.
+ (struct lang_type_header): New.
+ (struct lang_type_class): Rename from struct lang_type. Include
+ struct lang_type_header.
+ (struct lang_type_ptrmem): New.
+ (struct lang_type): New.
+ (LANG_TYPE_CLASS_CHECK): New. Use it in all the appropriate macros.
+ (LANG_TYPE_PTRMEM_CHECK): New. Use it in all the appropriate macros.
+ (TYPE_SET_PTRMEMFUNC_TYPE): Set discriminator, update for changes.
+ (struct lang_decl_flags): Use gengtype. Add discriminators.
+ (struct lang_decl): Use gengtype. Add and use discriminators.
+ Update the macros that reference moved fields.
+ (LANG_DECL_U2_CHECK): New function. Use it when appropriate.
+ (SET_DECL_THUNK_P): Set discriminator too.
+ (clear_inline_text_obstack): Delete prototype.
+ (finish_inline_definitions): Delete prototype.
+ (mark_pending_inlines): Delete prototype.
+ (lang_check_failed): New prototype.
+ * decl.c (struct named_label_use_list): Use gengtype.
+ (struct named_label_list): Likewise.
+ (mark_binding_level): Delete.
+ (mark_named_label_lists): Delete.
+ (push_local_name): Set discriminator on DECL_LANG_SPECIFIC.
+ (cxx_init_decl_processing): Use generated marker routine.
+ (begin_destructor_body): Delete dead set to
+ current_vcalls_possible_p.
+ (mark_lang_function): Delete.
+ (mark_cp_function_context): Delete.
+ (lang_mark_tree): Use generated marker routines.
+ * decl2.c (start_objects): Set discriminator when setting
+ GLOBAL_INIT_PRIORITY.
+ * lex.c (retrofit_lang_decl): Set discriminators.
+ (copy_lang_type): Update for changes to lang_type structure.
+ (cp_make_lang_type): Set discriminator.
+ * parse.y: Use gengtype on YYLVAL. Don't use dots in identifiers.
+ * search.c: Include ggc.h.
+ * semantics.c (anon_aggr_type_p): Use the macro, don't hand-code it.
+ (finish_inline_definitions): Delete.
+ * spew.c (struct token): Use gengtype.
+ (struct token_chunk): New.
+ (struct unparsed_text): Use gengtype. Store tokens in chunks.
+ (struct feed): Use gengtype.
+ (feed_obstack): Delete.
+ (feed): Mark as GC root.
+ (pending_inlines): Mark as GC root.
+ (pending_inlines_tail): Likewise.
+ (processing_these_inlines): Likewise.
+ (token_obstack): Make static.
+ (first_token): Likewise.
+ (init_spew): Don't initialize deleted things; use gengtype for roots.
+ (clear_inline_text_obstack): Delete.
+ (feed_input): Use GC for struct feed. Update for changes to
+ struct unparsed_text.
+ (mark_pending_inlines): Delete.
+ (next_token): Rename from add_token. Change all callers. Update
+ for changes to struct unparsed_text.
+ (space_for_token): New.
+ (remove_last_token): New.
+ (alloc_unparsed_text): New.
+ (snarf_block): Take an unparsed_text. Update for changes to struct
+ unparsed_text.
+ (snarf_method): Update for changes to struct unparsed_text.
+ (snarf_defarg): Update for changes to struct unparsed_text.
+ * tree.c (lang_check_failed): New.
+
+ * Make-lang.in (gt-cp-call.h gt-cp-decl2.h gt-cp-parse.h
+ gt-cp-pt.h gt-cp-repo.h gt-cp-spew.h): New rules.
+ (cp/spew.o): Add dependency on gt-<filename>.h.
+ (cp/decl2.o): Add dependency on gt-<filename>.h.
+ (cp/call.o): Add dependency on gt-<filename>.h.
+ (cp/pt.o): Add dependency on gt-<filename>.h.
+ (cp/repo.o): Add dependency on gt-<filename>.h.
+ (cp/parse.o): Add dependency on gt-<filename>.h.
+ * call.c: Use gengtype for roots.
+ * config-lang.in (gtfiles): Add cp-tree.h decl.h lex.h call.c
+ decl2.c parse.y pt.c repo.c spew.c.
+ * cp-tree.h: Use gengtype for roots.
+ (struct saved_scope): Use GGC, gengtype.
+ (cp_parse_init): Delete prototype.
+ (init_pt): Delete prototype.
+ * decl.c: Use gengtype for roots.
+ (mark_saved_scope): Delete.
+ (cxx_init_decl_processing): Don't call deleted initilisation
+ routines.
+ (signed_size_zero_node): Delete, unused.
+ * decl.h: Use gengtype for roots.
+ * decl2.c: Use gengtype for roots.
+ * lex.h: Use gengtype for roots.
+ * parse.y: Use gengtype for roots.
+ (cp_parse_init): Delete.
+ * pt.c: Use gengtype for roots.
+ (init_pt): Delete.
+ * repo.c: Use gengtype for roots.
+ * spew.c: Use gengtype for roots.
+
+ * Make-lang.in: Allow for filename changes. Add gtype-cp.h.
+ (cp/decl.o): Add dependency on gtype-cp.h.
+ * decl.c: Remove use of add_deletable_root, use GTY marker instead.
+ Include gtype-cp.h. Allow for filename changes.
+
+ * Make-lang.in (cp/gt-decl.h): Generate using gengtype.
+ (cp/decl.o): Add cp/gt-decl.h dependency.
+ * config-lang.in (gtfiles): New.
+ * tree.h: Rename struct binding_level to struct cp_binding_level.
+ * decl.c: Rename struct binding_level to struct cp_binding_level.
+ Include cp/gt-decl.h.
+ (struct cp_binding_level): Use gengtype.
+ (make_binding_level): Use GGC on struct cp_binding_level.
+ (mark_binding_level): Use gt_ggc_m_cp_binding_level.
+ (cxx_init_decl_processing): Mark free_binding_level as
+ deletable.
+
+ * decl.c (mark_cp_function_context): Update calling sequence.
+
+ * decl.c (start_function): Don't free 'struct
+ cp_language_function'.
+ (pop_cp_function_context): Likewise.
+ (save_function_data): Allocate it using GC.
+ * semantics.c (genrtl_start_function): Don't free 'struct
+ cp_language_function'.
+
+2002-05-31 Matthew Woodcraft <mattheww@chiark.greenend.org.uk>
+
+ * lang-specs.h: Use cpp_debug_options.
+
+2002-05-28 Zack Weinberg <zack@codesourcery.com>
+
+ * mangle.c, tree.c: Include real.h.
+ * Make-lang.in: Update dependency lists.
+
+2002-05-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * lex.c: Don't include c-lex.h.
+ * parse.y, spew.c: Don't include c-lex.h; include c-pragma.h.
+
2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+ * spew.c (yyungetc, snarf_block): Remove indent_level handling.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * decl.c (obscure_complex_init): Check for VAR_DECL
+ before using DECL_THREAD_LOCAL.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * decl.c (check_tag_decl): Handle RID_THREAD.
+ (obscure_complex_init): Reject run-time init of tls.
+ (grokvardecl, grokdeclarator): Handle RID_THREAD.
+ * lex.c (reswords): Add __thread.
+ (rid_to_yy): Map RID_THREAD to SCSPEC.
+
+2002-05-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
* cp-lang.c (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
* cp-tree.h (cxx_post_options): Kill.
* cp-lex.c (cxx_post_options): Kill.
+2002-05-21 Richard Henderson <rth@redhat.com>
+
+ * lex.c (rid_to_yy): Add RID_THREAD.
+
+2002-05-21 Alexandre Oliva <aoliva@redhat.com>
+
+ * init.c (build_vec_init): Test for trivial copy-assignment when
+ copy-assigning arrays.
+
+2002-05-20 Andreas Jaeger <aj@suse.de>
+
+ * init.c (build_default_init): Remove unused variable.
+
+2002-05-20 Alexandre Oliva <aoliva@redhat.com>
+
+ * call.c (any_strictly_viable): New.
+ (build_new_op): Use it for COMPOUND_EXPR and ADDR_EXPRs.
+
2002-05-19 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* error.c (dump_type) [TYPEOF_TYPE]: Fix parenthesis printing.
@@ -610,11 +3572,47 @@
instantiation after explicit specialization.
(do_type_instantiation): Likewise.
-2002-05-09 Jason Merrill <jason@redhat.com>
+2002-05-19 Alexandre Oliva <aoliva@redhat.com>
+
+ * cp-tree.h (complete_type_or_diagnostic): Changed prototype,
+ renamed from...
+ (complete_type_or_else): ... this. Redefined as macro.
+ (cxx_incomplete_type_diagnostic): Declare.
+ (cxx_incomplete_type_error): Define as macro.
+ * init.c (build_delete): Warn about incomplete types other than
+ void, and use the built-in operator delete for them.
+ * typeck.c (complete_type_or_diagnostic): Renamed from
+ complete_type_or_else. Added warn_only argument, passed to...
+ * typeck2.c (cxx_incomplete_type_diagnostic): ... this. Print
+ warnings or errors depending on new warn_only argument. Renamed
+ from...
+ (cxx_incomplete_type_error): ... this. New implementation in
+ terms of cxx_incomplete_type_diagnostic.
- * pt.c (tsubst_expr) [ASM_STMT]: Copy ASM_INPUT_P.
+2002-05-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/6611
+ * decl2.c (import_export_decl): If we clear
+ DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+
+2002-05-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
-2002-05-15 Alexandre Oliva <aoliva@redhat.com>
+ PR c++/6620
+ * pt.c (verify_class_unification): Don't check if PARM is template
+ parameter dependent. Simplify.
+ (unify) [TEMPLATE_PARM_INDEX]: Handle when ARG is a template
+ parameter dependent expression.
+
+2002-05-14 Jason Merrill <jason@redhat.com>
+
+ * rtti.c (get_tinfo_decl): Don't call comdat_linkage.
+ Do set DECL_COMDAT.
+ (synthesize_tinfo_var): Take the public decl.
+ (create_real_tinfo_var): Likewise. Check DECL_COMDAT.
+ (emit_tinfo_decl): Adjust. Call import_export_decl.
+ * decl2.c (import_export_decl): Simplify tinfo decl handling.
+
+2002-05-14 Alexandre Oliva <aoliva@redhat.com>
* cp-tree.h (struct lang_type): Added non_zero_init.
(CLASSTYPE_NON_ZERO_INIT_P): New macro.
@@ -633,28 +3631,49 @@
(process_init_constructor): Create non-trivial zero-initializers
for array members and class fields.
-2002-05-14 Release Manager
+2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk>
- * GCC 3.1 Released.
+ * lang-specs.h: Remove redundant -lang-c++.
-2002-05-03 Jason Merrill <jason@redhat.com>
+2002-05-13 Jason Merrill <jason@redhat.com>
- * decl.c (BOOL_TYPE_SIZE): Move default to defaults.h.
+ * class.c (build_vtbl_ref_1): Use fixed_type_or_null.
+ (fixed_type_or_null): See through reference vars.
+ (build_base_path): Vtable contents are constant.
+ * typeck.c (get_member_function_from_ptrfunc): Likewise.
-2002-05-02 Mark Mitchell <mark@codesourcery.com>
+2002-05-12 Jason Merrill <jason@redhat.com>
- * init.c (perform_base_cleanups): Correct order of base class
- cleanups.
+ * cp-lang.c (ok_to_generate_alias_set_for_type): Backend-created
+ structs are safe.
-2002-05-01 Mark Mitchell <mark@codesourcery.com>
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/6527
- * init.c (perform_base_cleanups): Emit cleanups in reverse order
- of construction.
+ * cp-tree.h (flag_ansi): Remove.
+ * decl2.c (flag_ansi): Remove.
+ (cxx_decode_option): Set flag_iso and flag_undef.
-2002-05-01 Gabriel Dos Reis <gdr@codesourcery.com>
+2002-05-09 Jason Merrill <jason@redhat.com>
- * error.c (dump_type): Be careful about implicit typenames.
+ * typeck.c (get_member_function_from_ptrfunc): Reorganize.
+ Use subtraction rather than a bitmask to get the index.
+ * cvt.c (cp_convert_to_pointer): Bail on an error_mark_node.
+
+ * pt.c (tsubst_expr) [ASM_STMT]: Copy ASM_INPUT_P.
+
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Make-lang.in (decl2.o): Update.
+ * cp-tree.h (warn_multichar): Remove.
+ * decl2.c: Include c-common.h.
+ (warn_multichar): Remove.
+
+2002-05-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (build_cplus_array_type): Only const and volatile get
+ special handling.
+
+ * decl.c (BOOL_TYPE_SIZE): Move default to defaults.h.
2002-04-30 Mark Mitchell <mark@codesourcery.com>
@@ -700,22 +3719,69 @@
PR c/6343
* decl.c (duplicate_decls): Call merge_weak.
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * parse.y (malloced_yyss, malloced_yyvs): New.
+ (yyoverflow): Re-add. Set them.
+ (free_parser_stacks): New.
+
2002-04-26 Mark Mitchell <mark@codesourcery.com>
- PR c++/6479
+ PR c++/6497
* method.c (do_build_assign_ref): Pass a derivation to
build_method_call when calling base class assignment operators.
-2002-04-24 Mark Mitchell <mark@codesourcery.com>
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * parse.y (yyoverflow): Revert.
- * mangle.c (write_type): Don't use TYPE_MAIN_VARIANT when writing
- out an array type.
- (write_CV_qualifiers_for_type): Use TYPE_QUALS, not cp_type_quals,
- to determine qualifiers.
+2002-04-26 Richard Henderson <rth@redhat.com>
+ PR c/3581
+ * parse.y (string): Remove. Update all uses to use STRING
+ instead, and not call combine_strings.
+ * rtti.c (tinfo_name): Use fix_string_type.
+ * semantics.c (finish_asm_stmt): Don't call combine_strings.
+ * spew.c (yylexstring): New.
+ (read_token): Use it.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ PR c/2161
+ * parse.y (yyoverflow): New.
+
+2002-04-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/5607
+ * search.c (check_final_overrider): No longer static.
+ * class.c (update_vtable_entry_for_fn): Call it.
+ * cp-tree.h: Adjust.
+
+2002-04-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SET_YYDEBUG): Remove.
+ * cp-tree.h (cxx_set_yydebug): Die.
+ * lex.c (YYDEBUG): Get from c-lex.h.
+ (cxx_set_yydebug): Remove.
+ * parse.y: Include c-lex.h.
+ (YYDEBUG): Get from c-lex.h.
+
+2002-04-24 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6438.
* cvt.c (convert_to_void): Don't unconditionally make COND_EXPRs
void.
+2002-04-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE,
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, LANG_HOOKS_ATTRIBUTE_TABLE):
+ Redefine.
+ * cp-tree.h (cp_attribute_table): Rename.
+ * decl.c (lang_attribute_table): Remove declaration.
+ (cxx_init_decl_processing): Don't set it.
+ * tree.c (cp_attribute_table): Rename.
+
2002-04-24 Jason Merrill <jason@redhat.com>
PR c++/6331
@@ -729,15 +3795,6 @@
* decl.c (make_rtl_for_nonlocal_decl): Don't mess with #pragma i/i
stuff for comdats.
-2002-04-23 Jason Merrill <jason@redhat.com>
-
- PR c++/5504 - but re-breaks c++/411
- * init.c (push_base_cleanups): Rename to perform_base_cleanups.
- Expand base cleanups now rather than pushing them.
- * decl.c (begin_destructor_body): Don't call push_base_cleanups.
- (finish_destructor_body): Call perform_base_cleanups.
- * cp-tree.h: Adjust prototype.
-
2002-04-23 Jakub Jelinek <jakub@redhat.com>
* parse.y (check_class_key): Allow KEY to be union/enum/struct/class
@@ -758,6 +3815,36 @@
* typeck.c (merge_types): Remember the cv-qualification of pointer
types when merging them.
+2002-04-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_FUNCTION_INIT,
+ LANG_HOOKS_FUNCTION_FREE, LANG_HOOKS_FUNCTION_MARK): Redefine.
+ * cp-tree.h (cxx_push_function_context, cxx_pop_function_context,
+ cxx_mark_function_context): New.
+ * decl.c (push_cp_function_context, pop_cp_function_context,
+ mark_cp_function_context): Rename for consistency.
+ (cxx_init_decl_processing): Don't set old hooks.
+
+2002-04-19 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (convert_type_from_ellipsis): Rename, update.
+ * cp-lang.c (LANG_HOOKS_TYPE_PROMOTES_TO): Redefine.
+ * cp-tree.h (convert_type_from_ellipsis): Rename.
+ * decl.c (cxx_init_decl_processing): Don't set hook.
+
+2002-04-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (build_new_method_call): Update.
+ * cp-lang.c (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): Redefine.
+ * cp-tree.h (cxx_incomplete_type_error): New.
+ * decl.c (grokdeclarator, grokparms): Update.
+ * decl2.c (check_classfn): Update.
+ * pt.c (tsubst): Update.
+ * typeck.c (complete_type_or_else, expr_sizeof,
+ decay_conversion): Update.
+ * typeck2.c (incomplete_type_error): Rename.
+ (add_exception_specifier): Update.
+
2002-04-18 Jason Merrill <jason@redhat.com>
PR c++/5658
@@ -782,25 +3869,47 @@
* decl.c (register_dtor_fn): Pass the address of dso_handle, not
dso_handle itself, to __cxa_atexit.
+2002-04-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ * error.c (cxx_print_error_function): Adjust call to macros.
+
2002-04-14 Jakub Jelinek <jakub@redhat.com>
* class.c (layout_virtual_bases): Do all dsize computation on trees.
+2002-04-14 Jason Merrill <jason@redhat.com>
+
+ * typeck.c (get_member_function_from_ptrfunc): Don't do
+ gratuitious division and multiplication on
+ ptrmemfunc_vbit_in_delta targets.
+
2002-04-12 Mark Mitchell <mark@codesourcery.com>
PR c++/5373.
* semantics.c (finish_expr_stmt): Remember the type of the
expression before any conversions are performed.
+2002-04-12 Mark Mitchell <mark@codesourcery.com>
+
PR c++/5189.
* call.c (add_template_candidate_real): Do not treat member
templates as copy constructors.
+2002-04-12 Mark Mitchell <mark@codesourcery.com>
+
* decl.c (duplicate_decls): Do not copy the RTL for a variable
declaration if the old variable had an incomplete type and the new
variable does not.
(complete_vars): Do not call layout_decl for completed variables.
+2002-04-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * decl.c (duplicate_decls): Don't try to unify an implicit typedef
+ with an explicit one.
+ (follow_tag_typedef): New.
+ (lookup_tag): Use it to extract the tag of an explicit typedef.
+ (xref_tag): Likewise.
+
2002-04-11 Andrew Haley <aph@redhat.com>
* typeck.c (type_after_usual_arithmetic_conversions):
@@ -810,14 +3919,6 @@
if neither operand is one of the standard types, return the type
of the first operand.
-2002-04-12 Richard Sandiford <rsandifo@redhat.com>
-
- * decl.c (duplicate_decls): Don't try to unify an implicit typedef
- with an explicit one.
- (follow_tag_typedef): New.
- (lookup_tag): Use it to extract the tag of an explicit typedef.
- (xref_tag): Likewise.
-
2002-04-10 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5507
@@ -829,6 +3930,9 @@
* semantics.c (genrtl_start_function): Don't free
DECL_SAVED_FUNCTION_DATA for inline functions.
+ * init.c (build_member_call): For now, don't convert to
+ intermediate base if it would cause an error.
+
2002-04-08 Paolo Carlini <pcarlini@unitus.it>
* parse.y (namespace_qualifier, maybe_identifier,
@@ -866,15 +3970,45 @@
* error.c (dump_expr) [CONVERT_EXPR]: Make sure TREE_TYPE (t) is
set before checking it.
+ PR c++/525
+ * init.c (build_member_call): Use build_scoped_ref.
+ (resolve_offset_ref): Likewise.
+ * call.c (build_scoped_method_call): Likewise.
+ * tree.c (maybe_dummy_object): Kludge around current_class_type being
+ wrong.
+ * typeck2.c (build_scoped_ref): Return the binfo via binfo_p parm.
+ * cp-tree.h: Adjust.
+
+ * init.c (push_base_cleanups): Just use build_scoped_method_call.
+
PR c++/6179
* method.c (implicitly_declare_fn): Pass unqualified type to
synthesize_exception_spec.
-2002-04-03 Jason Merrill <jason@redhat.com>
+2002-04-04 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/525
- * init.c (build_member_call): Convert to intermediate base even
- with -pedantic.
+ * cp-lang.c (LANG_HOOKS_TRUTHVALUE_CONVERSION): Redefine.
+ * cvt.c: Update comment.
+ * init.c (expand_cleanup_for_base): Update.
+ * semantics.c (finish_parenthesized_expr): Update.
+ * typeck.c (cp_truthvalue_conversion): Update.
+
+2002-04-04 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (finish_eh_cleanup): New fn.
+ * cp-tree.h: Add prototype.
+ * init.c (perform_member_init, expand_cleanup_for_base): Use
+ finish_eh_cleanup.
+ * cp-tree.def (SUBOBJECT, CTOR_STMT): Remove.
+ * cp-tree.h: Remove references.
+ * decl.c (begin_constructor_body, end_constructor_body): Likewise.
+ * dump.c (cp_dump_tree): Likewise.
+ * pt.c (tsubst_expr): Likewise.
+ * semantics.c (genrtl_ctor_stmt, genrtl_subobject): Remove.
+ (cp_expand_stmt): Remove handling of CTOR_STMT and SUBOBJECT.
+ * tree.c (cp_statement_code_p): Likewise.
+
+ * init.c (build_new_1): Set CLEANUP_EH_ONLY on deleting cleanup.
PR c++/5636
* semantics.c (nullify_returns_r): Just set CLEANUP_EH_ONLY on
@@ -885,12 +4019,38 @@
specifiers.
[METHOD_TYPE]: Use same code as FUNCTION_TYPE.
+2002-04-03 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (cxx_warn_unused_global_decl): New.
+ (LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL): New.
+
+2002-04-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SET_DECL_ASSEMBLER_NAME): Redefine.
+ * tree.c (init_tree): Don't set hook.
+
2002-04-03 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
* decl.c (duplicate_decls): Don't mess with assembler names when
redeclaring builtin functions as static.
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (build_addr_func): Update.
+ * class.c (resolve_address_of_overloaded_function): Update.
+ * cp-lang.c (LANG_HOOKS_MARK_ADDRESSABLE): Redefine.
+ * cp-tree.h (cxx_mark_addressable): New.
+ * decl.c (register_dtor_fn, cxx_maybe_build_cleanup): Update.
+ * decl2.c (build_cleanup): Update.
+ * except.c (build_throw): Update.
+ * init.c (resolve_offset_ref): Update.
+ * pt.c (convert_nontype_argument): Update.
+ * semantics.c (finish_asm_stmt, simplify_affr_init_exprs_r): Update.
+ * typeck.c (decay_conversion, build_array_ref, build_unary_op,
+ unary_complex_lvalue): Update.
+ (mark_addressable): Rename.
+
2002-04-01 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
@@ -898,6 +4058,40 @@
when) overwriting a built-in function. Don't use COPY_DECL_RTL,
but follow the SET_DECL_RTL idiom used elsewhere in the function.
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE,
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE): New.
+ * decl.c (grokdeclarator): Update.
+ * mangle.c (write_integer_cst): Update.
+ * typeck.c (build_binary_op): Update.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_UNSAFE_FOR_REEVAL): Redefine.
+ * lex.c (cxx_init): Don't set hook.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Make-lang.in (error.o): Update.
+ * cp-lang.c (LANG_HOOKS_PRINT_ERROR_FUNCTION): Redefine.
+ * cp-tree.h (struct diagnostic_context): Predeclare.
+ (cxx_print_error_function): New.
+ * error.c: Include langhooks-def.h.
+ (lang_print_error_function): Rename. Update.
+ (init_error): Don't set hook.
+
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIZE):
+ Redefine.
+ * cvt.c (cp_convert_to_pointer, type_promotes_to): Use new hooks.
+ * decl.c (finish_enum): Similarly.
+ * error.c (dump_type): Similarly.
+ * lex.c (cxx_init): Similarly.
+ * mangle.c (write_builtin_type): Similarly.
+ * typeck.c (comptypes): Similarly.
+
2002-03-28 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
@@ -921,18 +4115,48 @@
* lex.c (do_scoped_id): Fail to find an identifier in the global
namespace if its still anticipated.
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_MAKE_TYPE): Redefine.
+ * cp-tree.h (cp_make_lang_type): Rename.
+ * lex.c (cp_make_lang_type): Rename.
+ (make_aggr_type): Update.
+ * tree.c (init_tree): Don't set make_lang_type_fn.
+
2002-03-29 Jakub Jelinek <jakub@redhat.com>
PR c++/6073
* class.c (finish_struct_1): Update static field's DECL_MODE even
if its type is a variant of t.
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES): Redefine.
+ * cp-tree.h (cxx_insert_default_attributes): New.
+ * decl.c (insert_default_attributes): Rename.
+
2002-03-27 Mark Mitchell <mark@codesourcery.com>
PR c++/4884
* call.c (build_op_delete_call): Allow for the fact the placement
may be a COMPOUND_EXPR.
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_EXPAND_EXPR): Redefine.
+ * cp-tree.h (init_cplus_expand): Remove.
+ (cxx_expand_expr): New.
+ * expr.c (cplus_expand_expr): Rename cxx_expand_expr,
+ fix prototype.
+ (init_cplus_expand): Remove.
+ * lex.c (cxx_init): Don't call init_cplus_expand.
+
+2002-03-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/4884.
+ * init.c (build_new_1): Allow for the fact the result of
+ build_function_call may be a COMPOUND_EXPR.
+
2002-03-26 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5682
@@ -945,27 +4169,68 @@
(dfs_unmarked_real_bases_queue_p): Just get the canonical binfo.
(dfs_marked_real_bases_queue_p): Likewise.
-2002-03-26 Mark Mitchell <mark@codesourcery.com>
+2002-03-26 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/4884
- * init.c (build_new_1): Allow for the fact the result of
- build_function_call may be a COMPOUND_EXPR.
+ * cp-lang.c (LANG_HOOKS_MARK_TREE): Redefine.
+ * cp-tree.h (cxx_mark_tree): New.
+ * decl.c (lang_mark_tree): Rename cxx_mark_tree.
+
+2002-03-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-tree.h (cxx_maybe_build_cleanup): New.
+ * decl.c (destroy_local_var, hack_incomplete_structures): Update.
+ (maybe_build_cleanup): Rename cxx_maybe_build_cleanup.
+ * tree.c (build_target_expr): Update.
+ * cp-lang.c (LANG_HOOKS_MAYBE_BUILD_CLEANUP): Redefine.
+
+2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
-2002-03-25 Jakub Jelinek <jakub@redhat.com>
+ * decl2.c (cxx_decode_option): Handle -E.
+ * lang-specs.h (default_compilers): Preprocess with cc1plus.
+ * lex.c (cxx_init): Exit quickly if c_common_init returns NULL.
+
+2002-03-23 Jakub Jelinek <jakub@redhat.com>
PR c++/6037
* decl.c (start_enum): Don't set TREE_ADDRESSABLE on TREE_LIST node.
+2002-03-23 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ * error.c (dump_type): Be careful about implicit typenames.
+
+2002-03-21 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ PR C++/3656
+ * semantics.c (finish_base_specifier): Handle erronous base
+ classes.
+
+2002-03-22 Zack Weinberg <zack@codesourcery.com>
+
+ * error.c: Always use REAL_VALUE_TO_DECIMAL; don't test
+ REAL_IS_NOT_DOUBLE.
+
2002-03-22 Jeff Knaggs <jknaggs@redhat.com>
- * typeck.c (expand_ptrmemfunc_cst): Scale idx down to an index
- into the vtable_entry array regardless of
+ * typeck.c (get_member_function_from_ptrfunc): Scale idx down to
+ an index into the vtable_entry array regardless of
TARGET_PTRMEMFUNC_VBIT_LOCATION.
2002-03-21 Aldy Hernandez <aldyh@redhat.com>
* tree.c (cp_cannot_inline_tree_fn): Same.
+2002-03-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-tree.h (pushdecl, pushlevel, poplevel, set_block,
+ insert_block, getdecls, global_bindings_p): New.
+
+2002-03-20 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/4361
+ * mangle.c (struct globals) Add internal_mangling_p member.
+ (write_template_param): Do internal mangling, if needed.
+ (mangle_conv_op_name_for_type): Request internal mangling.
+
2002-03-20 Jason Merrill <jason@redhat.com>
PR c++/2136
@@ -977,6 +4242,15 @@
PR c++/5118
* class.c (get_vfield_name): Use the constructor_name.
+2002-03-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_DECL_PRINTABLE_NAME): Redefine.
+ * cp-tree.h (lang_printable_name): Rename.
+ * error.c (lang_decl_name): Use new hook.
+ * lex.c (cxx_init): Remove old hook.
+ * pt.c (tsubst_decl): Use new hook.
+ * tree.c (lang_printable_name): Rename.
+
2002-03-18 Eric Botcazou <ebotcazou@multimania.com>
PR c++/3882
@@ -984,11 +4258,6 @@
(tsubst_expr) [DECL_STMT]: ...here. And substitute the initializer
only after recording the declaration.
-2002-03-18 Ashif Harji <asharji@uwaterloo.ca>
-
- * lang-specs.h (compiler default_compilers): Add
- -no-integrated-cpp flag to invoke an external cpp.
-
2002-03-18 Jason Merrill <jason@redhat.com>
PR c++/2039
@@ -1019,17 +4288,43 @@
* class.c (build_base_path): Virtual base layout is fixed in
in-charge [cd]tors.
+2002-03-17 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_PARSE_FILE): Redefine.
+ * parse.y (yyparse): Remove macro.
+
+2002-03-17 Jason Merrill <jason@redhat.com>
+
PR c++/5757
* init.c (build_new_1): Pass the right pointer to op delete.
-2002-03-15 Richard Henderson <rth@redhat.com>
+2002-03-16 Nathan Sidwell <nathan@codesourcery.com>
- * init.c (build_new_1): Use size_binop instead of cp_build_binary_op.
+ PR c++/4361
+ * cp-tree.h (CLASSTYPE_METHOD_VEC): Document where templated
+ conversion operators go.
+ (struct lang_decl_flags): Add template_conv_p and unused
+ bitfields.
+ (DECL_TEMPLATE_CONV_FN_P): New macro.
+ * call.c (build_user_type_conversion_1): Don't check second type
+ conversion of overload set first.
+ * class.c (add_method): Make sure templated conversion operators
+ all end up on slot 2.
+ * lex.c (do_identifier): A conversion operator token might be
+ satisfied by a templated conversion operator.
+ * pt.c (check_explicit_specialization): Use
+ CLASSTYPE_FIRST_CONVERSION_SLOT.
+ (template_parm_this_level_p): New function.
+ (push_template_decl_real): Determine DECL_TEMPLATE_CONV_FN_P.
+ * search.c (lookup_fnfields_1): Template conversions will be on
+ the first slot.
+ * typeck.c (build_component_ref): Preserve the type of an
+ conversion operator name on the overload type.
+ (build_x_function_call): Retrieve the conversion operator name.
2002-03-15 Richard Henderson <rth@redhat.com>
- * decl.c (finish_function): Reapply accidentally reverted
- 2002-02-28 patch.
+ * init.c (build_new_1): Use size_binop instead of cp_build_binary_op.
2002-03-15 Mark Mitchell <mark@codesourcery.com>
@@ -1041,12 +4336,6 @@
* semantics.c (cp_expand_stmt): Likewise.
* cp/tree.c (cp_statement_code_p): Likewise.
-2002-03-15 Richard Henderson <rth@redhat.com>
-
- * decl.c: Include c-pragma.h.
- (start_decl, start_function): Invoke maybe_apply_pragma_weak.
- * Make-lang.in: Update dependencies.
-
2002-03-15 Jason Merrill <jason@redhat.com>
PR c++/5857
@@ -1064,6 +4353,12 @@
variables.
* decl2.c (maybe_make_one_only): Also mark the decl as needed.
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ * decl.c: Include c-pragma.h.
+ (start_decl, start_function): Invoke maybe_apply_pragma_weak.
+ * Make-lang.in: Update dependencies.
+
2002-03-14 Jakub Jelinek <jakub@redhat.com>
PR c++/5908
@@ -1075,6 +4370,24 @@
* mangle.c (write_builtin_type): Handle 128-bit integers even if
they are not a standard integer type.
+2002-03-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * cp-tree.h (init_init_processing): Remove declaration.
+ * init.c (BI_header_type, init_init_processing): Remove old ABI stuff.
+ * decl.c (cxx_init_decl_processing): Don't call init_init_processing.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-lang.c (tree_code_type, tree_code_length, tree_code_name):
+ Define.
+ * decl.c (duplicate_decls): Use TREE_CODE_LENGTH, not
+ tree_code_length.
+ * lex.c (cplus_tree_code_type, cplus_tree_code_length,
+ cplus_tree_code_name): Delete.
+ (cxx_init): Don't call add_c_tree_codes, instead set
+ lang_unsafe_for_reeval. Don't try to copy into the various
+ tree_code arrays.
+
2002-03-12 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5659
@@ -1102,11 +4415,35 @@
* typeck.c (build_static_cast): Compare non-qualified types
with pointer to member conversions.
+2002-03-11 Dan Nicolaescu <dann@ics.uci.edu>
+ Daniel Berlin <dan@dberlin.org>
+
+ * cp-lang.c (ok_to_generate_alias_set_for_type): New function.
+ (cxx_get_alias_set): Use it.
+
+2002-03-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (stabilize_expr): Prototype.
+
2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
* cp-tree.h (CLEAR_BINFO_MARKED): Make both parts of
conditional return void.
+2002-03-08 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_UNSAVE): Redefine.
+ * cp-tree.h (cxx_unsave): New.
+ * tree.c (cp_unsave): Rename cxx_unsave, update prototype.
+ (init_tree): Update.
+
+2002-03-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl.c (cxx_init_decl_processing): Use ARRAY_SIZE in lieu of
+ explicit sizeof/sizeof.
+ * decl2.c (cxx_decode_option): Likewise.
+ * lex.c (init_reswords, REDUCE_LENGTH, TOKEN_LENGTH): Likewise.
+
2002-03-02 Nathan Sidwell <nathan@codesourcery.com>
PR c++/775
@@ -1122,13 +4459,22 @@
2002-03-01 Phil Edwards <pme@gcc.gnu.org>
- * cp-tree.h (build_init): Remove prototype.
-
-2002-03-01 Phil Edwards <pme@gcc.gnu.org>
-
* cp-tree.h: Require __GNUC__ to be #defined.
(build_init): Add missing prototype.
+2002-03-01 Jason Merrill <jason@redhat.com>
+
+ * except.c: Don't include decl.h or obstack.h. Do include
+ tree-inline.h.
+ (build_throw): Destroy temporaries from the thrown
+ expression before calling __cxa_throw. Construct a thrown
+ temporary directly into the exception object.
+ (stabilize_throw_expr): New function.
+ (wrap_cleanups_r): New function.
+ * tree.c (stabilize_expr): New function.
+ * init.c (build_init): New function.
+ * Make-lang.in (cp/except.o): Adjust .h deps.
+
2002-02-28 Jason Merrill <jason@redhat.com>
* search.c (lookup_base_r): Don't clear is_non_public just because
@@ -1137,6 +4483,21 @@
* decl.c (finish_function): Only warn about missing return
statement with -Wreturn-type.
+2002-02-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * class.c (build_clone): Update.
+ * cp-lang.c (LANG_HOOKS_DUP_LANG_SPECIFIC_DECL): Redefine.
+ * cp-tree.h (cxx_dup_lang_specific_decl): New.
+ * lex.c (copy_lang_decl): Rename cxx_dup_lang_specific_decl.
+ (copy_decl): Update.
+ * method.c (make_thunk): Update.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * decl2.c: Delete traditional-mode-related code copied from
+ the C front end but not used, or used only to permit the
+ compiler to link.
+
2002-02-24 Craig Rodrigues <rodrigc@gcc.gnu.org>
PR c++/4093
@@ -1166,7 +4527,7 @@
* pt.c (convert_template_argument): Adjust make_typename_type
return value.
(tsubst): Adjust cp_build_qualified_type_real calls.
- (check_cv_quals_for_unify): Cope with alowing bad qualifications
+ (check_cv_quals_for_unify): Cope with allowing bad qualifications
on template type parms.
(instantiate_decl): Recheck substitutions to give warnings on bad
qualifications.
@@ -2301,7 +5662,7 @@ Tue Nov 27 09:03:47 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* search.c (get_vbase_1): Remove.
(get_vbase): Remove.
(convert_pointer_to_vbase): Remove.
- (lookup_base_recursive): New function.
+ (lookup_base_r): New function.
(lookup_base): New function.
* typeck.c (require_complete_type): Use lookup_base &
build_base_path instead of convert_pointer_to.
@@ -3144,7 +6505,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
PR c++/3621
* spew.c (yylex): Only copy the token's lineno, if it is
- non-zero.
+ nonzero.
2001-07-26 Nathan Sidwell <nathan@codesourcery.com>
@@ -3235,7 +6596,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
2001-07-23 Graham Stott <grahams@redhat.com>
- * cp/class.c (type_requires_array_cookie): Fix use of uninitialised
+ * cp/class.c (type_requires_array_cookie): Fix use of uninitialized
variable has_two_argument_delete_p.
2001-07-21 Nathan Sidwell <nathan@codesourcery.com>
@@ -3282,7 +6643,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
2001-07-20 Nathan Sidwell <nathan@codesourcery.com>
Remove old-abi remnants. Remove comments about old abi
- behaviour. Remove references to 'new-abi' in comments.
+ behavior. Remove references to 'new-abi' in comments.
* cp-tree.h: Adjust comments.
(vbase_offsets_in_vtable_p): Delete.
(vcall_offsets_in_vtable_p): Delete.
@@ -4484,7 +7845,7 @@ Thu Apr 5 16:54:29 2001 J"orn Rennecke <amylaar@redhat.com>
(maybe_commonize_var): Allow inlining functions even if they have
static local variables, use comdat_linkage for them if flag_weak.
(check_initializer): Call obscure_complex_init if
- grok_reference_init returned non-zero.
+ grok_reference_init returned nonzero.
(save_function_data): Clear x_local_names.
(pop_cp_function_context): Free x_local_names.
(mark_inlined_fns): Remove.
@@ -5731,7 +9092,7 @@ Sun Feb 4 15:52:44 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
(cp_make_fname_decl): Use size_int, not build_int_2.
(push_inline_template_parms_recursive): Likewise.
(end_template_parm_list): Likewise.
- (for_each_tempalte_parm): Do not use walk_tree_without_duplicates.
+ (for_each_template_parm): Do not use walk_tree_without_duplicates.
(tsubst_template_parms): Use size_int, not build_int_2.
(tsubst): Likewise.
* rtti.c (get_vmi_pseudo_type_info): Likewise.
@@ -6223,7 +9584,7 @@ Thu Nov 23 02:16:47 2000 J"orn Rennecke <amylaar@redhat.com>
2000-11-17 Nathan Sidwell <nathan@codesourcery.com>
- * typeck2.c (incomplete_type_error): Reorganise to avoid
+ * typeck2.c (incomplete_type_error): Reorganize to avoid
excessive diagnostics.
2000-11-16 Zack Weinberg <zack@wolery.stanford.edu>
@@ -11631,7 +14992,7 @@ Sun Feb 27 16:40:33 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
(add_method): Used functions are hidden by local functions.
(check_bases_and_members): Handle using-decls before finalizing
CLASSTYPE_METHOD_VEC.
- * call.c (add_function_candidate): Add ctype parm; if non-zero,
+ * call.c (add_function_candidate): Add ctype parm; if nonzero,
override the type of 'this' accordingly.
(add_template_candidate, add_template_candidate_real): Add ctype parm.
(convert_class_to_reference, build_user_type_conversion_1,
diff --git a/contrib/gcc/cp/ChangeLog.1 b/contrib/gcc/cp/ChangeLog.1
index b411f18..4b4afd3 100644
--- a/contrib/gcc/cp/ChangeLog.1
+++ b/contrib/gcc/cp/ChangeLog.1
@@ -5729,7 +5729,7 @@ Tue May 17 13:34:46 1994 Jason Merrill <jason@deneb.cygnus.com>
Mon May 16 23:04:01 1994 Stephen R. van den Berg <berg@pool.informatik.rwth-aachen.de>
* cp/typeck.c (common_type): Attribute merging.
- (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro.
+ (comp_types): Utilize COMP_TYPE_ATTRIBUTES macro.
* cp/parse.y: Revamp attribute parsing.
@@ -6168,7 +6168,7 @@ Wed May 4 11:19:45 1994 Jason Merrill <jason@deneb.cygnus.com>
Tue May 3 16:02:53 1994 Per Bothner <bothner@kalessin.cygnus.com>
Give a vtable entries a unique named type, for the sake of gdb.
- * class.c (build_vtable_entry): The addres of a thunk now has
+ * class.c (build_vtable_entry): The address of a thunk now has
type vtable_entry_type, not ptr_type_node.
* method.c (make_thunk): Fix type of THUNK_DECL.
* class.c (add_virtual_function, override_one_vtable): Use
diff --git a/contrib/gcc/cp/ChangeLog.2 b/contrib/gcc/cp/ChangeLog.2
index 179d6d7..26dc387 100644
--- a/contrib/gcc/cp/ChangeLog.2
+++ b/contrib/gcc/cp/ChangeLog.2
@@ -1264,7 +1264,7 @@ Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
1999-10-06 Brendan Kehoe <brendan@cygnus.com>
- * decl.c (grokdeclarator): Only warn about non-zero arrays if
+ * decl.c (grokdeclarator): Only warn about nonzero arrays if
!in_system_header (linux socketbits.h can give this for
__cmsg_data, which is using a GNU extension).
@@ -19205,7 +19205,7 @@ Mon Mar 4 22:38:39 1996 Gerald Baumgartner <gb@alexander.cs.purdue.edu>
* sig.c (build_signature_pointer_or_reference_type): Align
signature pointers/references on 8-byte boundaries so they can be
- grabbed 2 words at a time on a Sparc.
+ grabbed 2 words at a time on a SPARC.
Tue Mar 5 10:21:01 1996 Jason Merrill <jason@yorick.cygnus.com>
diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in
index aef2d35..afeb7ab 100644
--- a/contrib/gcc/cp/Make-lang.in
+++ b/contrib/gcc/cp/Make-lang.in
@@ -40,17 +40,12 @@
# Actual names to use when installing a native compiler.
CXX_INSTALL_NAME = `echo c++|sed '$(program_transform_name)'`
GXX_INSTALL_NAME = `echo g++|sed '$(program_transform_name)'`
-DEMANGLER_INSTALL_NAME = `echo c++filt|sed '$(program_transform_name)'`
CXX_TARGET_INSTALL_NAME = $(target_alias)-`echo c++|sed '$(program_transform_name)'`
GXX_TARGET_INSTALL_NAME = $(target_alias)-`echo g++|sed '$(program_transform_name)'`
# Actual names to use when installing a cross-compiler.
CXX_CROSS_NAME = `echo c++|sed '$(program_transform_cross_name)'`
GXX_CROSS_NAME = `echo g++|sed '$(program_transform_cross_name)'`
-DEMANGLER_CROSS_NAME = `echo c++filt|sed '$(program_transform_cross_name)'`
-
-# The name to use for the demangler program.
-DEMANGLER_PROG = c++filt$(exeext)
#
# Define the names for selecting c++ in LANGUAGES.
@@ -81,22 +76,10 @@ g++-cross$(exeext): g++$(exeext)
-rm -f g++-cross$(exeext)
cp g++$(exeext) g++-cross$(exeext)
-# The demangler.
-cxxmain.o: $(srcdir)/../libiberty/cplus-dem.c $(DEMANGLE_H) $(CONFIG_H)
- rm -f cxxmain.c
- $(LN_S) $(srcdir)/../libiberty/cplus-dem.c cxxmain.c
- $(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- -DVERSION=\"$(version)\" cxxmain.c
-
-# 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)
-
# The compiler itself.
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
- $(CXX_TARGET_OBJS)
+ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
@@ -131,13 +114,17 @@ $(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
false ; \
fi
+gtype-cp.h gt-cp-call.h gt-cp-decl.h gt-cp-decl2.h : s-gtype; @true
+gt-cp-parse.h gt-cp-pt.h gt-cp-repo.h gt-cp-spew.h : s-gtype; @true
+gt-cp-tree.h gt-cp-mangle.h : s-gtype; @true
+
#
# Build hooks:
c++.all.build: g++$(exeext)
-c++.all.cross: g++-cross$(exeext) $(DEMANGLER_PROG)
+c++.all.cross: g++-cross$(exeext)
c++.start.encap: g++$(exeext)
-c++.rest.encap: $(DEMANGLER_PROG)
+c++.rest.encap:
c++.info:
c++.dvi:
@@ -182,17 +169,6 @@ c++.install-common: installdirs
( cd $(DESTDIR)$(bindir) && \
$(LN) $(CXX_INSTALL_NAME)$(exeext) $(CXX_TARGET_INSTALL_NAME)$(exeext) ); \
fi ; \
- if [ x$(DEMANGLER_PROG) != x ] && [ -x "$(DEMANGLER_PROG)" ]; then \
- if [ -f g++-cross$(exeext) ] ; then \
- rm -f $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- chmod a+x $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- else \
- rm -f $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- chmod a+x $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- fi ; \
- fi ; \
fi
c++.install-info:
@@ -215,8 +191,6 @@ c++.uninstall:
-rm -rf $(DESTDIR)$(bindir)/$(CXX_CROSS_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(GXX_INSTALL_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(GXX_CROSS_NAME)$(exeext)
- -rm -rf $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext)
- -rm -rf $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext)
-rm -rf $(DESTDIR)$(man1dir)/$(GXX_INSTALL_NAME)$(man1ext)
-rm -rf $(DESTDIR)$(man1dir)/$(GXX_CROSS_NAME)$(man1ext)
#
@@ -225,7 +199,8 @@ c++.uninstall:
# We just have to delete files specific to us.
c++.mostlyclean:
- -rm -f cp/*$(objext) $(DEMANGLER_PROG)
+ -rm -f cp/*$(objext)
+ -rm -f cp/*$(coverageexts)
c++.clean:
c++.distclean:
-rm -f cp/config.status cp/Makefile
@@ -252,53 +227,58 @@ CXX_TREE_H = $(TREE_H) cp/cp-tree.h c-common.h cp/cp-tree.def c-common.def \
function.h varray.h $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \
$(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h
-cp/spew.o: cp/spew.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h toplev.h
-cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \
- toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h cp/operators.def \
- $(TM_P_H)
+cp/spew.o: cp/spew.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+ toplev.h gt-cp-spew.h
+cp/lex.o: cp/lex.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+ c-pragma.h toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h \
+ cp/operators.def $(TM_P_H)
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h $(LANGHOOKS_DEF_H) \
c-common.h
cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
- output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
- cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h
+ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(GGC_H) $(RTL_H) \
+ cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
+ debug.h gt-cp-decl.h gtype-cp.h timevar.h input.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
- output.h except.h toplev.h $(GGC_H) $(RTL_H)
+ output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h gt-cp-decl2.h \
+ timevar.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h
cp/class.o: cp/class.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
cp/call.o: cp/call.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
- $(GGC_H) diagnostic.h
+ $(GGC_H) diagnostic.h gt-cp-call.h
cp/friend.o: cp/friend.c $(CXX_TREE_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
cp/init.o: cp/init.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
$(GGC_H) except.h
cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
- $(TM_P_H)
+ $(TM_P_H) $(TARGET_H)
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
- insn-config.h integrate.h tree-inline.h
+ insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
- cp/cfns.h $(EXPR_H) libfuncs.h cp/decl.h $(OBSTACK_H)
+ cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \
- $(GGC_H) $(RTL_H) except.h tree-inline.h
-cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h
-cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h
+cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h $(srcdir)/cp/parse.h cp/lex.h \
+ toplev.h $(GGC_H) $(RTL_H) except.h tree-inline.h gt-cp-pt.h
+cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h \
+ $(LANGHOOKS_DEF_H)
+cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h \
+ gt-cp-repo.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
input.h $(PARAMS_H) debug.h tree-inline.h
-cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
+cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h real.h gt-cp-mangle.h $(TM_P_H)
cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
- $(SYSTEM_H) toplev.h $(GGC_H)
+ cp/decl.h $(SYSTEM_H) toplev.h $(GGC_H) gt-cp-parse.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
$(srcdir)/cp/parse.c $(OUTPUT_OPTION)
#
diff --git a/contrib/gcc/cp/NEWS b/contrib/gcc/cp/NEWS
index 97d4cd8..36720c6 100644
--- a/contrib/gcc/cp/NEWS
+++ b/contrib/gcc/cp/NEWS
@@ -1,4 +1,6 @@
-*** Changes in GCC 3.2.2:
+*** Changes in GCC 3.3:
+
+* The "new X = 3" extension has been removed; you must now use "new X(3)".
* G++ no longer allows in-class initializations of static data members
that do not have arithmetic or enumeration type. For example:
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index c8dcaf0..ac7aeb8 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,6 +1,6 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
@@ -38,20 +38,20 @@ Boston, MA 02111-1307, USA. */
extern int inhibit_warnings;
-static tree build_new_method_call PARAMS ((tree, tree, tree, tree, int));
-
-static tree build_field_call PARAMS ((tree, tree, tree, tree));
+static tree build_field_call PARAMS ((tree, tree, tree));
static struct z_candidate * tourney PARAMS ((struct z_candidate *));
static int equal_functions PARAMS ((tree, tree));
static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PARAMS ((tree, tree));
static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
static tree build_java_interface_fn_ref PARAMS ((tree, tree));
-#define convert_like(CONV, EXPR) \
- convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
- convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
-static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
+#define convert_like(CONV, EXPR) \
+ convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
+ /*issue_conversion_warnings=*/true)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
+ convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
+ /*issue_conversion_warnings=*/true)
+static tree convert_like_real (tree, tree, tree, int, int, bool);
static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
tree, const char *));
static tree build_object_call PARAMS ((tree, tree));
@@ -62,38 +62,39 @@ static void print_z_candidates PARAMS ((struct z_candidate *));
static tree build_this PARAMS ((tree));
static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
static int any_viable PARAMS ((struct z_candidate *));
+static int any_strictly_viable PARAMS ((struct z_candidate *));
static struct z_candidate * add_template_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
- unification_kind_t));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, unification_kind_t));
static struct z_candidate * add_template_candidate_real
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
- tree, unification_kind_t));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, tree, unification_kind_t));
static struct z_candidate * add_template_conv_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree));
-static struct z_candidate * add_builtin_candidates
- PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree, tree));
+static void add_builtin_candidates
+ PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int));
-static struct z_candidate * add_builtin_candidate
- PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
+static void add_builtin_candidate
+ PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
tree, tree, tree, tree *, tree *, int));
static int is_complete PARAMS ((tree));
-static struct z_candidate * build_builtin_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
+static void build_builtin_candidate
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree *, tree *,
int));
static struct z_candidate * add_conv_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree));
static struct z_candidate * add_function_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, int));
+ (struct z_candidate **, tree, tree, tree, tree, tree, int);
static tree implicit_conversion PARAMS ((tree, tree, tree, int));
static tree standard_conversion PARAMS ((tree, tree, tree));
-static tree reference_binding PARAMS ((tree, tree, tree, int));
+static tree reference_binding (tree, tree, tree, int);
static tree non_reference PARAMS ((tree));
static tree build_conv PARAMS ((enum tree_code, tree, tree));
static int is_subseq PARAMS ((tree, tree));
static tree maybe_handle_ref_bind PARAMS ((tree*));
static void maybe_handle_implicit_object PARAMS ((tree*));
-static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
- tree, tree, int));
+static struct z_candidate *add_candidate
+ (struct z_candidate **, tree, tree, tree, tree, int);
static tree source_type PARAMS ((tree));
static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
static int reference_related_p PARAMS ((tree, tree));
@@ -102,56 +103,46 @@ static tree convert_class_to_reference PARAMS ((tree, tree, tree));
static tree direct_reference_binding PARAMS ((tree, tree));
static int promoted_arithmetic_type_p PARAMS ((tree));
static tree conditional_conversion PARAMS ((tree, tree));
+static tree call_builtin_trap PARAMS ((void));
+static tree merge_conversion_sequences (tree, tree);
tree
build_vfield_ref (datum, type)
tree datum, type;
{
- tree rval;
-
if (datum == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
- if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type))
- rval = build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
- datum, TYPE_VFIELD (type));
- else
- rval = build_component_ref (datum, DECL_NAME (TYPE_VFIELD (type)), NULL_TREE, 0);
+ if (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
+ && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
+ datum = convert_to_base (datum, type, /*check_access=*/false);
- return rval;
+ return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
+ datum, TYPE_VFIELD (type));
}
/* Build a call to a member of an object. I.e., one that overloads
operator ()(), or is a pointer-to-function or pointer-to-method. */
static tree
-build_field_call (basetype_path, instance_ptr, name, parms)
- tree basetype_path, instance_ptr, name, parms;
+build_field_call (tree instance_ptr, tree decl, tree parms)
{
- tree field, instance;
-
- if (IDENTIFIER_CTOR_OR_DTOR_P (name))
- return NULL_TREE;
-
- /* Speed up the common case. */
- if (instance_ptr == current_class_ptr
- && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
- return NULL_TREE;
-
- field = lookup_field (basetype_path, name, 1, 0);
+ tree instance;
- if (field == error_mark_node || field == NULL_TREE)
- return field;
+ if (decl == error_mark_node || decl == NULL_TREE)
+ return decl;
- if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
+ if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL)
{
/* 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);
- instance = build_component_ref_1 (instance, field, 0);
+ instance = build_class_member_access_expr (instance, decl,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
if (instance == error_mark_node)
return error_mark_node;
@@ -298,27 +289,10 @@ build_scoped_method_call (exp, basetype, name, parms)
return error_mark_node;
}
- if (! binfo)
- {
- binfo = lookup_base (type, basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (! binfo)
- error_not_base_type (basetype, type);
- }
+ decl = build_scoped_ref (exp, basetype, &binfo);
if (binfo)
{
- if (TREE_CODE (exp) == INDIRECT_REF)
- {
- decl = build_base_path (PLUS_EXPR,
- build_unary_op (ADDR_EXPR, exp, 0),
- binfo, 1);
- decl = build_indirect_ref (decl, NULL);
- }
- else
- decl = build_scoped_ref (exp, basetype);
-
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
@@ -355,7 +329,7 @@ build_addr_func (function)
type = build_pointer_type (type);
- if (mark_addressable (function) == 0)
+ if (!cxx_mark_addressable (function))
return error_mark_node;
addr = build1 (ADDR_EXPR, type, function);
@@ -386,6 +360,7 @@ build_call (function, parms)
tree tmp;
tree decl;
tree result_type;
+ tree fntype;
function = build_addr_func (function);
@@ -395,7 +370,8 @@ build_call (function, parms)
return error_mark_node;
}
- result_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (function)));
+ fntype = TREE_TYPE (TREE_TYPE (function));
+ result_type = TREE_TYPE (fntype);
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
@@ -408,11 +384,12 @@ build_call (function, parms)
nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
- if (decl && TREE_THIS_VOLATILE (decl))
+ if (decl && TREE_THIS_VOLATILE (decl) && cfun)
current_function_returns_abnormally = 1;
if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
+ require_complete_eh_spec_types (fntype, decl);
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
@@ -492,7 +469,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
tree instance, name, parms, basetype_path;
int flags;
{
- tree basetype, instance_ptr;
+ tree fn;
+ tree object_type;
+ tree template_args = NULL_TREE;
+ bool has_template_args = false;
#ifdef GATHER_STATISTICS
n_build_method_call++;
@@ -501,7 +481,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (instance == error_mark_node
|| name == error_mark_node
|| parms == error_mark_node
- || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
+ || (instance && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
if (processing_template_decl)
@@ -524,39 +504,111 @@ build_method_call (instance, name, parms, basetype_path, flags)
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
+ if (TREE_CODE (instance) == OFFSET_REF)
+ instance = resolve_offset_ref (instance);
+ if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+ instance = convert_from_reference (instance);
+ object_type = TREE_TYPE (instance);
+
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
+ tree instance_ptr;
+
if (parms)
error ("destructors take no parameters");
- basetype = TREE_TYPE (instance);
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- basetype = TREE_TYPE (basetype);
- if (! check_dtor_name (basetype, name))
+ if (! check_dtor_name (object_type, name))
error
("destructor name `~%T' does not match type `%T' of expression",
- TREE_OPERAND (name, 0), basetype);
+ TREE_OPERAND (name, 0), object_type);
- if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
+ /* The destructor type must be complete. */
+ object_type = complete_type_or_else (object_type, NULL_TREE);
+ if (!object_type || object_type == error_mark_node)
+ return error_mark_node;
+
+ if (! TYPE_HAS_DESTRUCTOR (object_type))
return cp_convert (void_type_node, instance);
instance = default_conversion (instance);
instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- return build_delete (build_pointer_type (basetype),
+ return build_delete (build_pointer_type (object_type),
instance_ptr, sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
- return build_new_method_call (instance, name, parms, basetype_path, flags);
+ if (!CLASS_TYPE_P (object_type))
+ {
+ if ((flags & LOOKUP_COMPLAIN)
+ && TREE_TYPE (instance) != error_mark_node)
+ error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ name, instance, object_type);
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ template_args = TREE_OPERAND (name, 1);
+ has_template_args = true;
+ name = TREE_OPERAND (name, 0);
+ }
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ else if (TREE_CODE (name) == LOOKUP_EXPR)
+ name = TREE_OPERAND (name, 0);
+ else if (DECL_P (name))
+ name = DECL_NAME (name);
+ if (has_template_args)
+ fn = lookup_fnfields (object_type, name, /*protect=*/2);
+ else
+ fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/0);
+
+ if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
+ {
+ error ("request for member `%D' is ambiguous", name);
+ print_candidates (fn);
+ return error_mark_node;
+ }
+
+ /* If the name could not be found, issue an error. */
+ if (!fn)
+ {
+ unqualified_name_lookup_error (name);
+ return error_mark_node;
+ }
+
+ if (BASELINK_P (fn) && has_template_args)
+ BASELINK_FUNCTIONS (fn)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fn),
+ template_args);
+ if (BASELINK_P (fn) && basetype_path)
+ BASELINK_ACCESS_BINFO (fn) = basetype_path;
+
+ return build_new_method_call (instance, fn, parms,
+ /*conversion_path=*/NULL_TREE, flags);
}
/* New overloading code. */
-struct z_candidate {
+struct z_candidate GTY(()) {
+ /* The FUNCTION_DECL that will be called if this candidate is
+ selected by overload resolution. */
tree fn;
tree convs;
tree second_conv;
int viable;
- tree basetype_path;
+ /* If FN is a member function, the binfo indicating the path used to
+ qualify the name of FN at the call site. This path is used to
+ determine whether or not FN is accessible if it is selected by
+ overload resolution. The DECL_CONTEXT of FN will always be a
+ (possibly improper) base of this binfo. */
+ tree access_path;
+ /* If FN is a non-static member function, the binfo indicating the
+ subobject to which the `this' pointer should be converted if FN
+ is selected by overload resolution. The type pointed to the by
+ the `this' pointer must correspond to the most derived class
+ indicated by the CONVERSION_PATH. */
+ tree conversion_path;
tree template;
tree warnings;
struct z_candidate *next;
@@ -588,8 +640,7 @@ struct z_candidate {
should be created to hold the result of the conversion. */
#define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE)
-#define USER_CONV_CAND(NODE) \
- ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
int
@@ -607,8 +658,8 @@ null_ptr_cst_p (t)
}
-/* Returns non-zero if PARMLIST consists of only default parms and/or
- ellipsis. */
+/* Returns nonzero if PARMLIST consists of only default parms and/or
+ ellipsis. */
int
sufficient_parms_p (parmlist)
@@ -654,7 +705,7 @@ build_conv (code, type, from)
break;
}
ICS_STD_RANK (t) = rank;
- ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
+ ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));
ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
return t;
}
@@ -801,8 +852,7 @@ standard_conversion (to, from, expr)
(TREE_TYPE (TREE_TYPE (from)),
TREE_TYPE (TREE_TYPE (to)))))
{
- from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
- from = build_pointer_type (from);
+ from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
conv = build_conv (PMEM_CONV, from, conv);
}
}
@@ -899,7 +949,7 @@ standard_conversion (to, from, expr)
return conv;
}
-/* Returns non-zero if T1 is reference-related to T2. */
+/* Returns nonzero if T1 is reference-related to T2. */
static int
reference_related_p (t1, t2)
@@ -919,7 +969,7 @@ reference_related_p (t1, t2)
&& DERIVED_FROM_P (t1, t2)));
}
-/* Returns non-zero if T1 is reference-compatible with T2. */
+/* Returns nonzero if T1 is reference-compatible with T2. */
static int
reference_compatible_p (t1, t2)
@@ -947,9 +997,14 @@ convert_class_to_reference (t, s, expr)
tree conversions;
tree arglist;
tree conv;
+ tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
+ conversions = lookup_conversions (s);
+ if (!conversions)
+ return NULL_TREE;
+
/* [over.match.ref]
Assuming that "cv1 T" is the underlying type of the reference
@@ -975,10 +1030,10 @@ convert_class_to_reference (t, s, expr)
arglist = build_int_2 (0, 0);
TREE_TYPE (arglist) = build_pointer_type (s);
arglist = build_tree_list (NULL_TREE, arglist);
-
- for (conversions = lookup_conversions (s);
- conversions;
- conversions = TREE_CHAIN (conversions))
+
+ reference_type = build_reference_type (t);
+
+ while (conversions)
{
tree fns = TREE_VALUE (conversions);
@@ -986,43 +1041,58 @@ convert_class_to_reference (t, s, expr)
{
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
- struct z_candidate *old_candidates = candidates;
+
+ cand = NULL;
/* If this is a template function, try to get an exact
match. */
if (TREE_CODE (f) == TEMPLATE_DECL)
{
- candidates
- = add_template_candidate (candidates,
- f, s,
- NULL_TREE,
- arglist,
- build_reference_type (t),
- LOOKUP_NORMAL,
- DEDUCE_CONV);
+ cand = add_template_candidate (&candidates,
+ f, s,
+ NULL_TREE,
+ arglist,
+ reference_type,
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
+ LOOKUP_NORMAL,
+ DEDUCE_CONV);
- if (candidates != old_candidates)
+ if (cand)
{
/* Now, see if the conversion function really returns
an lvalue of the appropriate type. From the
point of view of unification, simply returning an
rvalue of the right type is good enough. */
- f = candidates->fn;
+ f = cand->fn;
t2 = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (t2) != REFERENCE_TYPE
|| !reference_compatible_p (t, TREE_TYPE (t2)))
- candidates = candidates->next;
+ {
+ candidates = candidates->next;
+ cand = NULL;
+ }
}
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
- candidates
- = add_function_candidate (candidates, f, s, arglist,
- LOOKUP_NORMAL);
-
- if (candidates != old_candidates)
- candidates->basetype_path = TYPE_BINFO (s);
+ cand = add_function_candidate (&candidates, f, s, arglist,
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
+ LOOKUP_NORMAL);
+
+ if (cand)
+ /* Build a standard conversion sequence indicating the
+ binding from the reference type returned by the
+ function to the desired REFERENCE_TYPE. */
+ cand->second_conv
+ = (direct_reference_binding
+ (reference_type,
+ build1 (IDENTITY_CONV,
+ TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
+ NULL_TREE)));
}
+ conversions = TREE_CHAIN (conversions);
}
/* If none of the conversion functions worked out, let our caller
@@ -1035,16 +1105,21 @@ convert_class_to_reference (t, s, expr)
if (!cand)
return NULL_TREE;
- conv = build1 (IDENTITY_CONV, s, expr);
- conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
- conv);
- TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
- ICS_USER_FLAG (conv) = 1;
+ /* Build a user-defined conversion sequence representing the
+ conversion. */
+ conv = build_conv (USER_CONV,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+ TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
+
+ /* Merge it with the standard conversion sequence from the
+ conversion function's return type to the desired type. */
+ cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
+
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
- cand->second_conv = conv;
- return conv;
+ return cand->second_conv;
}
/* A reference of the indicated TYPE is being bound directly to the
@@ -1056,7 +1131,13 @@ direct_reference_binding (type, conv)
tree type;
tree conv;
{
- tree t = TREE_TYPE (type);
+ tree t;
+
+ my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 20030306);
+ my_friendly_assert (TREE_CODE (TREE_TYPE (conv)) != REFERENCE_TYPE,
+ 20030306);
+
+ t = TREE_TYPE (type);
/* [over.ics.rank]
@@ -1093,9 +1174,7 @@ direct_reference_binding (type, conv)
the conversion returned. */
static tree
-reference_binding (rto, rfrom, expr, flags)
- tree rto, rfrom, expr;
- int flags;
+reference_binding (tree rto, tree rfrom, tree expr, int flags)
{
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
@@ -1173,7 +1252,7 @@ reference_binding (rto, rfrom, expr, flags)
in the second case. */
conv = convert_class_to_reference (to, from, expr);
if (conv)
- return direct_reference_binding (rto, conv);
+ return conv;
}
/* From this point on, we conceptually need temporaries, even if we
@@ -1207,11 +1286,13 @@ reference_binding (rto, rfrom, expr, flags)
-- The reference is bound to the object represented by the rvalue
or to a sub-object within that object.
- In this case, the implicit conversion sequence is supposed to be
- same as we would obtain by generating a temporary. Fortunately,
- if the types are reference compatible, then this is either an
- identity conversion or the derived-to-base conversion, just as
- for direct binding. */
+ -- ...
+
+ We use the first alternative. The implicit conversion sequence
+ is supposed to be same as we would obtain by generating a
+ temporary. Fortunately, if the types are reference compatible,
+ then this is either an identity conversion or the derived-to-base
+ conversion, just as for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
@@ -1251,7 +1332,6 @@ implicit_conversion (to, from, expr, flags)
int flags;
{
tree conv;
- struct z_candidate *cand;
/* Resolve expressions like `A::p' that we thought might become
pointers-to-members. */
@@ -1265,11 +1345,6 @@ implicit_conversion (to, from, expr, flags)
|| expr == error_mark_node)
return NULL_TREE;
- /* Make sure both the FROM and TO types are complete so that
- user-defined conversions are available. */
- complete_type (from);
- complete_type (to);
-
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
@@ -1282,6 +1357,8 @@ implicit_conversion (to, from, expr, flags)
|| IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
+ struct z_candidate *cand;
+
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
@@ -1299,18 +1376,20 @@ implicit_conversion (to, from, expr, flags)
functions. */
static struct z_candidate *
-add_candidate (candidates, fn, convs, viable)
- struct z_candidate *candidates;
- tree fn, convs;
- int viable;
+add_candidate (struct z_candidate **candidates,
+ tree fn, tree convs, tree access_path, tree
+ conversion_path, int viable)
{
struct z_candidate *cand
= (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
cand->fn = fn;
cand->convs = convs;
+ cand->access_path = access_path;
+ cand->conversion_path = conversion_path;
cand->viable = viable;
- cand->next = candidates;
+ cand->next = *candidates;
+ *candidates = cand;
return cand;
}
@@ -1323,10 +1402,10 @@ add_candidate (candidates, fn, convs, viable)
comes from for purposes of overload resolution. */
static struct z_candidate *
-add_function_candidate (candidates, fn, ctype, arglist, flags)
- struct z_candidate *candidates;
- tree fn, ctype, arglist;
- int flags;
+add_function_candidate (struct z_candidate **candidates,
+ tree fn, tree ctype, tree arglist,
+ tree access_path, tree conversion_path,
+ int flags)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
@@ -1334,6 +1413,11 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
tree parmnode, argnode;
int viable = 1;
+ /* Built-in functions that haven't been declared don't really
+ exist. */
+ if (DECL_ANTICIPATED (fn))
+ return NULL;
+
/* The `this', `in_chrg' and VTT arguments to constructors are not
considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
@@ -1438,7 +1522,8 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
}
out:
- return add_candidate (candidates, fn, convs, viable);
+ return add_candidate (candidates, fn, convs, access_path,
+ conversion_path, viable);
}
/* Create an overload candidate for the conversion function FN which will
@@ -1453,9 +1538,12 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
instead of the function. */
static struct z_candidate *
-add_conv_candidate (candidates, fn, obj, arglist)
- struct z_candidate *candidates;
+add_conv_candidate (candidates, fn, obj, arglist, access_path,
+ conversion_path)
+ struct z_candidate **candidates;
tree fn, obj, arglist;
+ tree access_path;
+ tree conversion_path;
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
@@ -1473,8 +1561,8 @@ add_conv_candidate (candidates, fn, obj, arglist)
flags = LOOKUP_NORMAL;
/* Don't bother looking up the same type twice. */
- if (candidates && candidates->fn == totype)
- return candidates;
+ if (*candidates && (*candidates)->fn == totype)
+ return NULL;
for (i = 0; i < len; ++i)
{
@@ -1515,13 +1603,14 @@ add_conv_candidate (candidates, fn, obj, arglist)
if (!sufficient_parms_p (parmnode))
viable = 0;
- return add_candidate (candidates, totype, convs, viable);
+ return add_candidate (candidates, totype, convs, access_path,
+ conversion_path, viable);
}
-static struct z_candidate *
+static void
build_builtin_candidate (candidates, fnname, type1, type2,
args, argtypes, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
tree fnname, type1, type2, *args, *argtypes;
int flags;
@@ -1564,7 +1653,10 @@ build_builtin_candidate (candidates, fnname, type1, type2,
viable = 0;
}
- return add_candidate (candidates, fnname, convs, viable);
+ add_candidate (candidates, fnname, convs,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ viable);
}
static int
@@ -1574,7 +1666,7 @@ is_complete (t)
return COMPLETE_TYPE_P (complete_type (t));
}
-/* Returns non-zero if TYPE is a promoted arithmetic type. */
+/* Returns nonzero if TYPE is a promoted arithmetic type. */
static int
promoted_arithmetic_type_p (type)
@@ -1602,10 +1694,10 @@ promoted_arithmetic_type_p (type)
of which TYPE1 and TYPE2 are, we add both candidates
CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
-static struct z_candidate *
+static void
add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
args, argtypes, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
enum tree_code code, code2;
tree fnname, type1, type2, *args, *argtypes;
int flags;
@@ -1645,7 +1737,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case POSTDECREMENT_EXPR:
case PREDECREMENT_EXPR:
if (TREE_CODE (type1) == BOOLEAN_TYPE)
- return candidates;
+ return;
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
@@ -1653,7 +1745,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type1 = build_reference_type (type1);
break;
}
- return candidates;
+ return;
/* 7 For every cv-qualified or cv-unqualified complete object type T, there
exist candidate operator functions of the form
@@ -1669,7 +1761,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
&& (TYPE_PTROB_P (type1)
|| TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
break;
- return candidates;
+ return;
/* 9 For every type T, there exist candidate operator functions of the form
T* operator+(T*);
@@ -1686,7 +1778,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1))
break;
- return candidates;
+ return;
/* 11For every promoted integral type T, there exist candidate operator
functions of the form
@@ -1695,7 +1787,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type1))
break;
- return candidates;
+ return;
/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1
is the same type as C2 or is a derived class of C2, T is a complete
@@ -1718,7 +1810,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| is_complete (TREE_TYPE (TREE_TYPE (type2)))))
break;
}
- return candidates;
+ return;
/* 13For every pair of promoted arithmetic types L and R, there exist can-
didate operator functions of the form
@@ -1774,7 +1866,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
- return candidates;
+ return;
case EQ_EXPR:
case NE_EXPR:
@@ -1816,7 +1908,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type1 = type2;
break;
}
- return candidates;
+ return;
case PLUS_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
@@ -1832,7 +1924,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type2 = ptrdiff_type_node;
break;
}
- return candidates;
+ return;
/* 18For every pair of promoted integral types L and R, there exist candi-
date operator functions of the form
@@ -1853,7 +1945,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
- return candidates;
+ return;
/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration
type, VQ is either volatile or empty, and R is a promoted arithmetic
@@ -1905,7 +1997,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
- return candidates;
+ return;
case TRUNC_MOD_EXPR:
case BIT_AND_EXPR:
@@ -1915,7 +2007,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
- return candidates;
+ return;
case NOP_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
@@ -1930,7 +2022,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type2 = type1;
break;
}
- return candidates;
+ return;
default:
abort ();
@@ -1965,16 +2057,13 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2)))
- return candidates;
+ return;
/* We don't check that the two types are the same; the logic
below will actually create two candidates; one in which both
parameter types are TYPE1, and one in which both parameter
types are TYPE2. */
- break;
-
- /* These arguments do not make for a legal overloaded operator. */
- return candidates;
+ break;
default:
abort ();
@@ -1991,13 +2080,14 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
- candidates = build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type2, type2, args, argtypes, flags);
+ return;
}
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type1, type2, args, argtypes, flags);
}
@@ -2023,11 +2113,11 @@ type_decays_to (type)
Here we generate a superset of the possible candidates for this particular
case. That is a subset of the full set the standard defines, plus some
other cases which the standard disallows. add_builtin_candidate will
- filter out the illegal set. */
+ filter out the invalid set. */
-static struct z_candidate *
+static void
add_builtin_candidates (candidates, code, code2, fnname, args, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
enum tree_code code, code2;
tree fnname, *args;
int flags;
@@ -2070,20 +2160,22 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
bool operator||(bool, bool); */
case TRUTH_NOT_EXPR:
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, boolean_type_node,
NULL_TREE, args, argtypes, flags);
+ return;
case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR:
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, boolean_type_node,
boolean_type_node, args, argtypes, flags);
+ return;
case ADDR_EXPR:
case COMPOUND_EXPR:
case COMPONENT_REF:
- return candidates;
+ return;
case COND_EXPR:
case EQ_EXPR:
@@ -2110,7 +2202,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
- return candidates;
+ return;
convs = lookup_conversions (argtypes[i]);
@@ -2125,7 +2217,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
}
else if (! convs)
- return candidates;
+ return;
for (; convs; convs = TREE_CHAIN (convs))
{
@@ -2177,16 +2269,16 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
{
if (types[1])
for (type = types[1]; type; type = TREE_CHAIN (type))
- candidates = add_builtin_candidate
+ add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
TREE_VALUE (type), args, argtypes, flags);
else
- candidates = add_builtin_candidate
+ add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
NULL_TREE, args, argtypes, flags);
}
- return candidates;
+ return;
}
@@ -2202,10 +2294,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
static struct z_candidate*
add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, flags,
- obj, strict)
- struct z_candidate *candidates;
+ arglist, return_type, access_path,
+ conversion_path, flags, obj, strict)
+ struct z_candidate **candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
int flags;
tree obj;
unification_kind_t strict;
@@ -2232,11 +2326,11 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
return_type, strict, -1);
if (i != 0)
- return candidates;
+ return NULL;
fn = instantiate_template (tmpl, targs);
if (fn == error_mark_node)
- return candidates;
+ return NULL;
/* In [class.copy]:
@@ -2265,15 +2359,17 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
- return candidates;
+ return NULL;
}
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
- cand = add_conv_candidate (candidates, fn, obj, arglist);
+ cand = add_conv_candidate (candidates, fn, obj, access_path,
+ conversion_path, arglist);
else
cand = add_function_candidate (candidates, fn, ctype,
- arglist, flags);
+ arglist, access_path,
+ conversion_path, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
@@ -2302,27 +2398,35 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
static struct z_candidate *
add_template_candidate (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, flags, strict)
- struct z_candidate *candidates;
+ arglist, return_type, access_path,
+ conversion_path, flags, strict)
+ struct z_candidate **candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
int flags;
unification_kind_t strict;
{
return
add_template_candidate_real (candidates, tmpl, ctype,
- explicit_targs, arglist, return_type, flags,
- NULL_TREE, strict);
+ explicit_targs, arglist, return_type,
+ access_path, conversion_path,
+ flags, NULL_TREE, strict);
}
static struct z_candidate *
-add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
- struct z_candidate *candidates;
+add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type,
+ access_path, conversion_path)
+ struct z_candidate **candidates;
tree tmpl, obj, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
- arglist, return_type, 0, obj, DEDUCE_CONV);
+ arglist, return_type, access_path,
+ conversion_path, 0, obj, DEDUCE_CONV);
}
@@ -2336,6 +2440,16 @@ any_viable (cands)
return 0;
}
+static int
+any_strictly_viable (cands)
+ struct z_candidate *cands;
+{
+ for (; cands; cands = cands->next)
+ if (cands->viable == 1)
+ return 1;
+ return 0;
+}
+
static struct z_candidate *
splice_viable (cands)
struct z_candidate *cands;
@@ -2361,11 +2475,51 @@ build_this (obj)
return build_unary_op (ADDR_EXPR, obj, 0);
}
+/* Returns true iff functions are equivalent. Equivalent functions are
+ not '==' only if one is a function-local extern function or if
+ both are extern "C". */
+
+static inline int
+equal_functions (fn1, fn2)
+ tree fn1;
+ tree fn2;
+{
+ if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
+ || DECL_EXTERN_C_FUNCTION_P (fn1))
+ return decls_match (fn1, fn2);
+ return fn1 == fn2;
+}
+
static void
-print_z_candidates (candidates)
- struct z_candidate *candidates;
+print_z_candidates (struct z_candidate *candidates)
{
- const char *str = "candidates are:";
+ const char *str;
+ struct z_candidate *cand1;
+ struct z_candidate **cand2;
+
+ /* There may be duplicates in the set of candidates. We put off
+ checking this condition as long as possible, since we have no way
+ to eliminate duplicates from a set of functions in less than n^2
+ time. Now we are about to emit an error message, so it is more
+ permissible to go slowly. */
+ for (cand1 = candidates; cand1; cand1 = cand1->next)
+ {
+ tree fn = cand1->fn;
+ /* Skip builtin candidates and conversion functions. */
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ continue;
+ cand2 = &cand1->next;
+ while (*cand2)
+ {
+ if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ && equal_functions (fn, (*cand2)->fn))
+ *cand2 = (*cand2)->next;
+ else
+ cand2 = &(*cand2)->next;
+ }
+ }
+
+ str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@@ -2392,6 +2546,35 @@ print_z_candidates (candidates)
}
}
+/* USER_SEQ is a user-defined conversion sequence, beginning with a
+ USER_CONV. STD_SEQ is the standard conversion sequence applied to
+ the result of the conversion function to convert it to the final
+ desired type. Merge the the two sequences into a single sequence,
+ and return the merged sequence. */
+
+static tree
+merge_conversion_sequences (tree user_seq, tree std_seq)
+{
+ tree *t;
+
+ my_friendly_assert (TREE_CODE (user_seq) == USER_CONV,
+ 20030306);
+
+ /* Find the end of the second conversion sequence. */
+ t = &(std_seq);
+ while (TREE_CODE (*t) != IDENTITY_CONV)
+ t = &TREE_OPERAND (*t, 0);
+
+ /* Replace the identity conversion with the user conversion
+ sequence. */
+ *t = user_seq;
+
+ /* The entire sequence is a user-conversion sequence. */
+ ICS_USER_FLAG (std_seq) = 1;
+
+ return std_seq;
+}
+
/* Returns the best overload candidate to perform the requested
conversion. This function is used for three the overloading situations
described in [over.match.copy], [over.match.conv], and [over.match.ref].
@@ -2405,9 +2588,8 @@ build_user_type_conversion_1 (totype, expr, flags)
{
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
- tree ctors = NULL_TREE, convs = NULL_TREE, *p;
+ tree ctors = NULL_TREE, convs = NULL_TREE;
tree args = NULL_TREE;
- tree templates = NULL_TREE;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
@@ -2430,7 +2612,7 @@ build_user_type_conversion_1 (totype, expr, flags)
{
tree t;
- ctors = TREE_VALUE (ctors);
+ ctors = BASELINK_FUNCTIONS (ctors);
t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
@@ -2449,22 +2631,20 @@ build_user_type_conversion_1 (totype, expr, flags)
continue;
if (TREE_CODE (ctor) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, ctor, templates);
- candidates =
- add_template_candidate (candidates, ctor, totype,
- NULL_TREE, args, NULL_TREE, flags,
- DEDUCE_CALL);
- }
+ cand = add_template_candidate (&candidates, ctor, totype,
+ NULL_TREE, args, NULL_TREE,
+ TYPE_BINFO (totype),
+ TYPE_BINFO (totype),
+ flags,
+ DEDUCE_CALL);
else
- candidates = add_function_candidate (candidates, ctor, totype,
- args, flags);
+ cand = add_function_candidate (&candidates, ctor, totype,
+ args, TYPE_BINFO (totype),
+ TYPE_BINFO (totype),
+ flags);
- if (candidates)
- {
- candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
- candidates->basetype_path = TYPE_BINFO (totype);
- }
+ if (cand)
+ cand->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
}
if (convs)
@@ -2472,9 +2652,9 @@ build_user_type_conversion_1 (totype, expr, flags)
for (; convs; convs = TREE_CHAIN (convs))
{
- tree fns = TREE_VALUE (convs);
+ tree fns;
+ tree conversion_path = TREE_PURPOSE (convs);
int convflags = LOOKUP_NO_CONVERSION;
- tree ics;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
@@ -2482,73 +2662,50 @@ build_user_type_conversion_1 (totype, expr, flags)
look for a temporary binding. */
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
+
+ for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+
+ /* [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.
- if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
- else
- /* We can't compute this yet. */
- ics = error_mark_node;
+ So we pass fromtype as CTYPE to add_*_candidate. */
- if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
- /* ignore the near match. */;
- else if (ics)
- for (; fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- struct z_candidate *old_candidates = candidates;
-
- /* [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.
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ cand = add_template_candidate (&candidates, fn, fromtype, NULL_TREE,
+ args, totype,
+ TYPE_BINFO (fromtype),
+ conversion_path,
+ flags,
+ DEDUCE_CONV);
+ else
+ cand = add_function_candidate (&candidates, fn, fromtype,
+ args,
+ TYPE_BINFO (fromtype),
+ conversion_path,
+ flags);
- So we pass fromtype as CTYPE to add_*_candidate. */
+ if (cand)
+ {
+ tree ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0, convflags);
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates =
- add_template_candidate (candidates, fn, fromtype, NULL_TREE,
- args, totype, flags,
- DEDUCE_CONV);
- }
- else
- candidates = add_function_candidate (candidates, fn, fromtype,
- args, flags);
-
- if (candidates != old_candidates)
- {
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
- 0, convflags);
-
- candidates->second_conv = ics;
- candidates->basetype_path = TYPE_BINFO (fromtype);
-
- if (ics == NULL_TREE)
- candidates->viable = 0;
- else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
- candidates->viable = -1;
- }
- }
+ cand->second_conv = ics;
+
+ if (ics == NULL_TREE)
+ cand->viable = 0;
+ else if (cand->viable == 1 && ICS_BAD_FLAG (ics))
+ cand->viable = -1;
+ }
+ }
}
if (! any_viable (candidates))
- {
-#if 0
- if (flags & LOOKUP_COMPLAIN)
- {
- if (candidates && ! candidates->next)
- /* say why this one won't work or try to be loose */;
- else
- error ("no viable candidates");
- }
-#endif
-
- return 0;
- }
+ return 0;
candidates = splice_viable (candidates);
cand = tourney (candidates);
@@ -2565,23 +2722,29 @@ build_user_type_conversion_1 (totype, expr, flags)
cand = candidates; /* any one will do */
cand->second_conv = build1 (AMBIG_CONV, totype, expr);
ICS_USER_FLAG (cand->second_conv) = 1;
- ICS_BAD_FLAG (cand->second_conv) = 1;
+ if (!any_strictly_viable (candidates))
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+ /* If there are viable candidates, don't set ICS_BAD_FLAG; an
+ ambiguous conversion is no worse than another user-defined
+ conversion. */
return cand;
}
- for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
- p = &(TREE_OPERAND (*p, 0));
-
- *p = build
+ /* Build the user conversion sequence. */
+ convs = build_conv
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
- expr, build_ptr_wrapper (cand));
-
- ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
+ build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+ TREE_OPERAND (convs, 1) = build_zc_wrapper (cand);
+
+ /* Combine it with the second conversion sequence. */
+ cand->second_conv = merge_conversion_sequences (convs,
+ cand->second_conv);
+
if (cand->viable == -1)
- ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
+ ICS_BAD_FLAG (cand->second_conv) = 1;
return cand;
}
@@ -2603,6 +2766,78 @@ build_user_type_conversion (totype, expr, flags)
return NULL_TREE;
}
+/* Find the possibly overloaded set of functions corresponding to a
+ call of the form SCOPE::NAME (...). NAME might be a
+ TEMPLATE_ID_EXPR, OVERLOAD, _DECL, IDENTIFIER_NODE or LOOKUP_EXPR. */
+
+tree
+resolve_scoped_fn_name (tree scope, tree name)
+{
+ tree fn;
+ tree template_args = NULL_TREE;
+ bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
+
+ if (is_template_id)
+ {
+ template_args = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ }
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ else if (TREE_CODE (name) == LOOKUP_EXPR)
+ name = TREE_OPERAND (name, 0);
+
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ fn = lookup_namespace_name (scope, name);
+ else if (!CLASS_TYPE_P (scope))
+ {
+ error ("`%T' is not a class type", scope);
+ return error_mark_node;
+ }
+ else
+ {
+ if (!TYPE_BEING_DEFINED (scope)
+ && !COMPLETE_TYPE_P (complete_type (scope)))
+ {
+ error ("incomplete type '%T' cannot be used to name a scope",
+ scope);
+ return error_mark_node;
+ }
+
+ if (BASELINK_P (name))
+ fn = name;
+ else
+ fn = lookup_member (scope, name, /*protect=*/1, /*prefer_type=*/0);
+ if (fn && current_class_type)
+ fn = (adjust_result_of_qualified_name_lookup
+ (fn, scope, current_class_type));
+
+ /* It might be the name of a function pointer member. */
+ if (fn && TREE_CODE (fn) == FIELD_DECL)
+ fn = resolve_offset_ref (build_offset_ref (scope, fn));
+ }
+
+ if (!fn)
+ {
+ error ("'%D' has no member named '%E'", scope, name);
+ return error_mark_node;
+ }
+ if (is_template_id)
+ {
+ tree fns = fn;
+
+ if (BASELINK_P (fn))
+ fns = BASELINK_FUNCTIONS (fns);
+ fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args);
+ if (BASELINK_P (fn))
+ BASELINK_FUNCTIONS (fn) = fns;
+ else
+ fn = fns;
+ }
+
+ return fn;
+}
+
/* Do any initial processing on the arguments to a function call. */
static tree
@@ -2628,6 +2863,9 @@ resolve_args (args)
}
return args;
}
+
+/* Return an expression for a call to FN (a namespace-scope function)
+ with the ARGS. */
tree
build_new_function_call (fn, args)
@@ -2637,6 +2875,15 @@ build_new_function_call (fn, args)
tree explicit_targs = NULL_TREE;
int template_only = 0;
+ /* Check FN and ARGS. */
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
+ || TREE_CODE (fn) == TEMPLATE_DECL
+ || TREE_CODE (fn) == OVERLOAD
+ || TREE_CODE (fn) == TEMPLATE_ID_EXPR,
+ 20020712);
+ my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+ 20020712);
+
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (fn, 1);
@@ -2644,30 +2891,30 @@ build_new_function_call (fn, args)
template_only = 1;
}
- if (really_overloaded_fn (fn))
+ if (really_overloaded_fn (fn)
+ || TREE_CODE (fn) == TEMPLATE_DECL)
{
tree t1;
- tree templates = NULL_TREE;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
- for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
+ for (t1 = fn; t1; t1 = OVL_NEXT (t1))
{
- tree t = OVL_FUNCTION (t1);
+ tree t = OVL_CURRENT (t1);
if (TREE_CODE (t) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, t, templates);
- candidates = add_template_candidate
- (candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE,
- LOOKUP_NORMAL, DEDUCE_CALL);
- }
+ add_template_candidate
+ (&candidates, t, NULL_TREE, explicit_targs, args,
+ NULL_TREE,
+ /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
+ LOOKUP_NORMAL, DEDUCE_CALL);
else if (! template_only)
- candidates = add_function_candidate
- (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
+ add_function_candidate
+ (&candidates, t, NULL_TREE, args, /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
@@ -2675,7 +2922,7 @@ build_new_function_call (fn, args)
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
error ("no matching function for call to `%D(%A)'",
- DECL_NAME (OVL_FUNCTION (fn)), args);
+ DECL_NAME (OVL_CURRENT (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
@@ -2694,7 +2941,7 @@ build_new_function_call (fn, args)
return build_over_call (cand, args, LOOKUP_NORMAL);
}
- /* This is not really overloaded. */
+ /* This is not really overloaded. */
fn = OVL_CURRENT (fn);
return build_function_call (fn, args);
@@ -2727,25 +2974,22 @@ build_object_call (obj, args)
if (fns)
{
- tree base = BINFO_TYPE (TREE_PURPOSE (fns));
+ tree base = BINFO_TYPE (BASELINK_BINFO (fns));
mem_args = tree_cons (NULL_TREE, build_this (obj), args);
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- candidates
- = add_template_candidate (candidates, fn, base, NULL_TREE,
- mem_args, NULL_TREE,
- LOOKUP_NORMAL, DEDUCE_CALL);
- }
+ add_template_candidate (&candidates, fn, base, NULL_TREE,
+ mem_args, NULL_TREE,
+ TYPE_BINFO (type),
+ TYPE_BINFO (type),
+ LOOKUP_NORMAL, DEDUCE_CALL);
else
- candidates = add_function_candidate
- (candidates, fn, base, mem_args, LOOKUP_NORMAL);
-
- if (candidates)
- candidates->basetype_path = TYPE_BINFO (type);
+ add_function_candidate
+ (&candidates, fn, base, mem_args, TYPE_BINFO (type),
+ TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
@@ -2767,15 +3011,14 @@ build_object_call (obj, args)
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- candidates = add_template_conv_candidate (candidates,
- fn,
- obj,
- args,
- totype);
- }
+ add_template_conv_candidate
+ (&candidates, fn, obj, args, totype,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE);
else
- candidates = add_conv_candidate (candidates, fn, obj, args);
+ add_conv_candidate (&candidates, fn, obj, args,
+ /*conversion_path=*/NULL_TREE,
+ /*access_path=*/NULL_TREE);
}
}
@@ -2826,23 +3069,27 @@ op_error (code, code2, arg1, arg2, arg3, problem)
switch (code)
{
case COND_EXPR:
- error ("%s for `%T ? %T : %T' operator", problem,
- error_type (arg1), error_type (arg2), error_type (arg3));
+ error ("%s for ternary 'operator?:' in '%E ? %E : %E'",
+ problem, arg1, arg2, arg3);
break;
+
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
+ error ("%s for 'operator%s' in '%E%s'", problem, opname, arg1, opname);
break;
+
case ARRAY_REF:
- error ("%s for `%T [%T]' operator", problem,
- error_type (arg1), error_type (arg2));
+ error ("%s for 'operator[]' in '%E[%E]'", problem, arg1, arg2);
break;
+
default:
if (arg2)
- error ("%s for `%T %s %T' operator", problem,
- error_type (arg1), opname, error_type (arg2));
+ error ("%s for 'operator%s' in '%E %s %E'",
+ problem, opname, arg1, opname, arg2);
else
- error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
+ error ("%s for 'operator%s' in '%s%E'",
+ problem, opname, opname, arg1);
+ break;
}
}
@@ -2857,6 +3104,7 @@ conditional_conversion (e1, e2)
tree t1 = non_reference (TREE_TYPE (e1));
tree t2 = non_reference (TREE_TYPE (e2));
tree conv;
+ bool good_base;
/* [expr.cond]
@@ -2885,10 +3133,9 @@ conditional_conversion (e1, e2)
changed to an rvalue of type T2 that still refers to the original
source class object (or the appropriate subobject thereof). */
if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
- && same_or_base_type_p (TYPE_MAIN_VARIANT (t2),
- TYPE_MAIN_VARIANT (t1)))
+ && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
{
- if (at_least_as_qualified_p (t2, t1))
+ if (good_base && at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
if (!same_type_p (TYPE_MAIN_VARIANT (t1),
@@ -2899,19 +3146,17 @@ conditional_conversion (e1, e2)
else
return NULL_TREE;
}
+ else
+ /* [expr.cond]
- /* [expr.cond]
-
- E1 can be converted to match E2 if E1 can be implicitly converted
- to the type that expression E2 would have if E2 were converted to
- an rvalue (or the type it has, if E2 is an rvalue). */
- return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
+ Otherwise: E1 can be converted to match E2 if E1 can be implicitly
+ converted to the type that expression E2 would have if E2 were
+ converted to an rvalue (or the type it has, if E2 is an rvalue). */
+ return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
- arguments to the conditional expression. By the time this function
- is called, any suitable candidate functions are included in
- CANDIDATES. */
+ arguments to the conditional expression. */
tree
build_conditional_expr (arg1, arg2, arg3)
@@ -2984,7 +3229,7 @@ build_conditional_expr (arg1, arg2, arg3)
type of the other and is an rvalue.
--Both the second and the third operands have type void; the
- result is of type void and is an rvalue. */
+ result is of type void and is an rvalue. */
if ((TREE_CODE (arg2) == THROW_EXPR)
^ (TREE_CODE (arg3) == THROW_EXPR))
result_type = ((TREE_CODE (arg2) == THROW_EXPR)
@@ -3085,12 +3330,12 @@ build_conditional_expr (arg1, arg2, arg3)
args[0] = arg2;
args[1] = arg3;
args[2] = arg1;
- candidates = add_builtin_candidates (candidates,
- COND_EXPR,
- NOP_EXPR,
- ansi_opname (COND_EXPR),
- args,
- LOOKUP_NORMAL);
+ add_builtin_candidates (&candidates,
+ COND_EXPR,
+ NOP_EXPR,
+ ansi_opname (COND_EXPR),
+ args,
+ LOOKUP_NORMAL);
/* [expr.cond]
@@ -3138,18 +3383,10 @@ build_conditional_expr (arg1, arg2, arg3)
We use ocp_convert rather than build_user_type_conversion because the
latter returns NULL_TREE on failure, while the former gives an error. */
- if (IS_AGGR_TYPE (TREE_TYPE (arg2)) && real_lvalue_p (arg2))
- arg2 = ocp_convert (TREE_TYPE (arg2), arg2,
- CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
- else
- arg2 = decay_conversion (arg2);
+ arg2 = force_rvalue (arg2);
arg2_type = TREE_TYPE (arg2);
- if (IS_AGGR_TYPE (TREE_TYPE (arg3)) && real_lvalue_p (arg3))
- arg3 = ocp_convert (TREE_TYPE (arg3), arg3,
- CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
- else
- arg3 = decay_conversion (arg3);
+ arg3 = force_rvalue (arg3);
arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == error_mark_node)
@@ -3206,7 +3443,7 @@ build_conditional_expr (arg1, arg2, arg3)
qualification conversions (_conv.qual_) are performed to bring
them to a common type, whose cv-qualification shall match the
cv-qualification of either the second or the third operand.
- The result is of the common type. */
+ The result is of the common type. */
else if ((null_ptr_cst_p (arg2)
&& (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
|| TYPE_PTRMEMFUNC_P (arg3_type)))
@@ -3255,8 +3492,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
struct z_candidate *candidates = 0, *cand;
tree fns, mem_arglist = NULL_TREE, arglist, fnname;
enum tree_code code2 = NOP_EXPR;
- tree templates = NULL_TREE;
tree conv;
+ bool viable_candidates;
if (arg1 == error_mark_node
|| arg2 == error_mark_node
@@ -3283,6 +3520,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (arg1) == OFFSET_REF)
arg1 = resolve_offset_ref (arg1);
arg1 = convert_from_reference (arg1);
+ if (CLASS_TYPE_P (TREE_TYPE (arg1))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg1)))
+ /* Make sure the template type is instantiated now. */
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)));
switch (code)
{
@@ -3290,7 +3531,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
case VEC_NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
- /* Use build_op_new_call and build_op_delete_call instead. */
+ /* Use build_op_new_call and build_op_delete_call instead. */
abort ();
case CALL_EXPR:
@@ -3305,12 +3546,18 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (arg2) == OFFSET_REF)
arg2 = resolve_offset_ref (arg2);
arg2 = convert_from_reference (arg2);
+ if (CLASS_TYPE_P (TREE_TYPE (arg2))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg2)))
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg2)));
}
if (arg3)
{
if (TREE_CODE (arg3) == OFFSET_REF)
arg3 = resolve_offset_ref (arg3);
arg3 = convert_from_reference (arg3);
+ if (CLASS_TYPE_P (TREE_TYPE (arg3))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg3)))
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg3)));
}
if (code == COND_EXPR)
@@ -3344,16 +3591,17 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates
- = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
- arglist, TREE_TYPE (fnname),
- flags, DEDUCE_CALL);
- }
+ add_template_candidate (&candidates, fn, NULL_TREE, NULL_TREE,
+ arglist, TREE_TYPE (fnname),
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ flags, DEDUCE_CALL);
else
- candidates = add_function_candidate (candidates, fn, NULL_TREE,
- arglist, flags);
+ add_function_candidate (&candidates, fn, NULL_TREE,
+ arglist,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
@@ -3367,12 +3615,14 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (fns)
{
- tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
+ tree conversion_path = BASELINK_BINFO (fns);
+
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree this_arglist;
+ tree access_path = TYPE_BINFO (TREE_TYPE (arg1));
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
this_arglist = mem_arglist;
@@ -3380,20 +3630,17 @@ build_new_op (code, flags, arg1, arg2, arg3)
this_arglist = arglist;
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- /* A member template. */
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates
- = add_template_candidate (candidates, fn, basetype, NULL_TREE,
- this_arglist, TREE_TYPE (fnname),
- flags, DEDUCE_CALL);
- }
+ /* A member template. */
+ add_template_candidate (&candidates, fn,
+ BINFO_TYPE (conversion_path),
+ NULL_TREE,
+ this_arglist, TREE_TYPE (fnname),
+ access_path, conversion_path,
+ flags, DEDUCE_CALL);
else
- candidates = add_function_candidate
- (candidates, fn, basetype, this_arglist, flags);
-
- if (candidates)
- candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
+ add_function_candidate
+ (&candidates, fn, BINFO_TYPE (conversion_path), this_arglist,
+ access_path, conversion_path, flags);
}
}
@@ -3417,11 +3664,28 @@ build_new_op (code, flags, arg1, arg2, arg3)
args[2] = NULL_TREE;
}
- candidates = add_builtin_candidates
- (candidates, code, code2, fnname, args, flags);
+ add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
}
- if (! any_viable (candidates))
+ switch (code)
+ {
+ case COMPOUND_EXPR:
+ case ADDR_EXPR:
+ /* For these, the built-in candidates set is empty
+ [over.match.oper]/3. We don't want non-strict matches
+ because exact matches are always possible with built-in
+ operators. The built-in candidate set for COMPONENT_REF
+ would be empty too, but since there are no such built-in
+ operators, we accept non-strict matches for them. */
+ viable_candidates = any_strictly_viable (candidates);
+ break;
+
+ default:
+ viable_candidates = any_viable (candidates);
+ break;
+ }
+
+ if (! viable_candidates)
{
switch (code)
{
@@ -3656,10 +3920,10 @@ build_op_delete_call (code, addr, size, flags, placement)
tree alloc_fn;
tree call_expr;
- /* Find the allocation function that is being called. */
+ /* Find the allocation function that is being called. */
call_expr = placement;
/* Sometimes we have a COMPOUND_EXPR, rather than a simple
- CALL_EXPR. */
+ CALL_EXPR. */
while (TREE_CODE (call_expr) == COMPOUND_EXPR)
call_expr = TREE_OPERAND (call_expr, 1);
/* Extract the function. */
@@ -3698,7 +3962,7 @@ build_op_delete_call (code, addr, size, flags, placement)
/* Go through the `operator delete' functions looking for one
with a matching type. */
- for (fn = BASELINK_P (fns) ? TREE_VALUE (fns) : fns;
+ for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
fn;
fn = OVL_NEXT (fn))
{
@@ -3776,18 +4040,17 @@ enforce_access (basetype_path, decl)
return 1;
}
-/* Perform the conversions in CONVS on the expression EXPR.
- FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1
- indicates the `this' argument of a method. INNER is non-zero when
+/* Perform the conversions in CONVS on the expression EXPR. FN and
+ ARGNUM are used for diagnostics. ARGNUM is zero based, -1
+ indicates the `this' argument of a method. INNER is nonzero when
being called to continue a conversion chain. It is negative when a
- reference binding will be applied, positive otherwise. */
+ reference binding will be applied, positive otherwise. If
+ ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious
+ conversions will be emitted if appropriate. */
static tree
-convert_like_real (convs, expr, fn, argnum, inner)
- tree convs, expr;
- tree fn;
- int argnum;
- int inner;
+convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
+ bool issue_conversion_warnings)
{
int savew, savee;
@@ -3803,11 +4066,13 @@ convert_like_real (convs, expr, fn, argnum, inner)
{
if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
- expr = convert_like_real (t, expr, fn, argnum, 1);
+ expr = convert_like_real (t, expr, fn, argnum, 1,
+ /*issue_conversion_warnings=*/false);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
- return convert_like_real (t, expr, fn, argnum, 1);
+ return convert_like_real (t, expr, fn, argnum, 1,
+ /*issue_conversion_warnings=*/false);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
@@ -3817,15 +4082,14 @@ convert_like_real (convs, expr, fn, argnum, inner)
return cp_convert (totype, expr);
}
- if (!inner)
+ if (issue_conversion_warnings)
expr = dubious_conversion_warnings
(totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
{
- struct z_candidate *cand
- = WRAPPER_PTR (TREE_OPERAND (convs, 1));
+ struct z_candidate *cand = USER_CONV_CAND (convs);
tree convfn = cand->fn;
tree args;
@@ -3863,7 +4127,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
&& (inner >= 0 || !lvalue_p (expr)))
{
savew = warningcount, savee = errorcount;
- expr = build_new_method_call
+ expr = build_special_member_call
(NULL_TREE, complete_ctor_identifier,
build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
/* Core issue 84, now a DR, says that we don't allow UDCs
@@ -3910,7 +4174,8 @@ convert_like_real (convs, expr, fn, argnum, inner)
};
expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
- TREE_CODE (convs) == REF_BIND ? -1 : 1);
+ TREE_CODE (convs) == REF_BIND ? -1 : 1,
+ /*issue_conversion_warnings=*/false);
if (expr == error_mark_node)
return error_mark_node;
@@ -3945,10 +4210,10 @@ convert_like_real (convs, expr, fn, argnum, inner)
type is the same class as, or a derived class of, the class of the
destination [is treated as direct-initialization]. [dcl.init] */
savew = warningcount, savee = errorcount;
- expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (totype),
- LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
+ expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (totype),
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
if (fn)
{
if (warningcount > savew)
@@ -3963,7 +4228,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
tree ref_type = totype;
/* If necessary, create a temporary. */
- if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
+ if (NEED_TEMPORARY_P (convs) || !non_cast_lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
expr = build_target_expr_with_type (expr, type);
@@ -3981,9 +4246,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),
expr);
/* Convert the pointer to the desired reference type. */
- expr = build1 (NOP_EXPR, ref_type, expr);
-
- return expr;
+ return build_nop (ref_type, expr);
}
case LVALUE_CONV:
@@ -4001,6 +4264,22 @@ convert_like_real (convs, expr, fn, argnum, inner)
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
+/* Build a call to __builtin_trap which can be used in an expression. */
+
+static tree
+call_builtin_trap ()
+{
+ tree fn = get_identifier ("__builtin_trap");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ abort ();
+
+ fn = build_call (fn, NULL_TREE);
+ fn = build (COMPOUND_EXPR, integer_type_node, fn, integer_zero_node);
+ return fn;
+}
+
/* ARG is being passed to a varargs function. Perform any conversions
required. Array/function to pointer decay must have already happened.
Return the converted value. */
@@ -4022,12 +4301,13 @@ convert_arg_to_ellipsis (arg)
if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
{
- /* Undefined behaviour [expr.call] 5.2.2/7. We used to just warn
+ /* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
here and do a bitwise copy, but now cp_expr_size will abort if we
try to do that. */
- error ("cannot pass objects of non-POD type `%#T' through `...'",
- TREE_TYPE (arg));
- arg = error_mark_node;
+ warning ("cannot pass objects of non-POD type `%#T' through `...'; \
+call will abort at runtime",
+ TREE_TYPE (arg));
+ arg = call_builtin_trap ();
}
return arg;
@@ -4050,7 +4330,7 @@ build_x_va_arg (expr, type)
if (! pod_type_p (type))
{
- /* Undefined behaviour [expr.call] 5.2.2/7. */
+ /* Undefined behavior [expr.call] 5.2.2/7. */
warning ("cannot receive objects of non-POD type `%#T' through `...'",
type);
}
@@ -4058,24 +4338,27 @@ build_x_va_arg (expr, type)
return build_va_arg (expr, type);
}
-/* TYPE has been given to va_arg. Apply the default conversions which would
- have happened when passed via ellipsis. Return the promoted type, or
- NULL_TREE, if there is no change. */
+/* TYPE has been given to va_arg. Apply the default conversions which
+ would have happened when passed via ellipsis. Return the promoted
+ type, or the passed type if there is no change. */
tree
-convert_type_from_ellipsis (type)
+cxx_type_promotes_to (type)
tree type;
{
tree promote;
-
+
if (TREE_CODE (type) == ARRAY_TYPE)
- promote = build_pointer_type (TREE_TYPE (type));
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- promote = build_pointer_type (type);
- else
- promote = type_promotes_to (type);
+ return build_pointer_type (TREE_TYPE (type));
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ return build_pointer_type (type);
+
+ promote = type_promotes_to (type);
+ if (same_type_p (type, promote))
+ promote = type;
- return same_type_p (type, promote) ? NULL_TREE : promote;
+ return promote;
}
/* ARG is a default argument expression being passed to a parameter of
@@ -4128,15 +4411,48 @@ convert_default_arg (type, arg, fn, parmnum)
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- arg = default_conversion (arg);
+ arg = convert_for_arg_passing (type, arg);
}
return arg;
}
+/* Returns the type which will really be used for passing an argument of
+ type TYPE. */
+
+tree
+type_passed_as (type)
+ tree type;
+{
+ /* Pass classes with copy ctors by invisible reference. */
+ if (TREE_ADDRESSABLE (type))
+ type = build_reference_type (type);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ type = integer_type_node;
+
+ return type;
+}
+
+/* Actually perform the appropriate conversion. */
+
+tree
+convert_for_arg_passing (type, val)
+ tree type, val;
+{
+ if (val == error_mark_node)
+ ;
+ /* Pass classes with copy ctors by invisible reference. */
+ else if (TREE_ADDRESSABLE (type))
+ val = build1 (ADDR_EXPR, build_reference_type (type), val);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ val = default_conversion (val);
+ return val;
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
@@ -4159,10 +4475,10 @@ build_over_call (cand, args, flags)
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
for (val = cand->warnings; val; val = TREE_CHAIN (val))
- joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
+ joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
- enforce_access (cand->basetype_path, fn);
+ enforce_access (cand->access_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
@@ -4191,7 +4507,9 @@ build_over_call (cand, args, flags)
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
- tree t;
+ tree converted_arg;
+ tree base_binfo;
+
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
TREE_TYPE (argtype), fn);
@@ -4203,10 +4521,22 @@ build_over_call (cand, args, flags)
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
- t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
- TREE_TYPE (parmtype), ba_ignore, NULL);
- t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
- converted_args = tree_cons (NULL_TREE, t, converted_args);
+ /* Convert to the base in which the function was declared. */
+ my_friendly_assert (cand->conversion_path != NULL_TREE, 20020730);
+ converted_arg = build_base_path (PLUS_EXPR,
+ TREE_VALUE (arg),
+ cand->conversion_path,
+ 1);
+ /* If fn was found by a using declaration, the conversion path
+ will be to the derived class, not the base declaring fn. We
+ must convert from derived to base. */
+ base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
+ TREE_TYPE (parmtype), ba_ignore, NULL);
+
+ converted_arg = build_base_path (PLUS_EXPR, converted_arg,
+ base_binfo, 1);
+
+ converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
@@ -4222,10 +4552,7 @@ build_over_call (cand, args, flags)
val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- val = default_conversion (val);
+ val = convert_for_arg_passing (type, val);
converted_args = tree_cons (NULL_TREE, val, converted_args);
}
@@ -4296,20 +4623,13 @@ build_over_call (cand, args, flags)
temp or an INIT_EXPR otherwise. */
if (integer_zerop (TREE_VALUE (args)))
{
- if (! real_lvalue_p (arg))
+ if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
- else if ((!real_lvalue_p (arg)
- || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
- /* Empty classes have padding which can be hidden
- inside an (empty) base of the class. This must not
- be touched as it might overlay things. When the
- gcc core learns about empty classes, we can treat it
- like other classes. */
- && !(is_empty_class (DECL_CONTEXT (fn))
- && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))))
+ else if (TREE_CODE (arg) == TARGET_EXPR
+ || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
tree address;
tree to = stabilize_reference
@@ -4331,24 +4651,7 @@ build_over_call (cand, args, flags)
(build_indirect_ref (TREE_VALUE (converted_args), 0));
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
- if (is_empty_class (TREE_TYPE (to)))
- {
- TREE_USED (arg) = 1;
-
- val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
- /* Even though the assignment may not actually result in any
- code being generated, we do not want to warn about the
- assignment having no effect. That would be confusing to
- users who may be performing the assignment as part of a
- generic algorithm, for example.
-
- Ideally, the notions of having side-effects and of being
- useless would be orthogonal. */
- TREE_SIDE_EFFECTS (val) = 1;
- TREE_NO_UNUSED_WARNING (val) = 1;
- }
- else
- val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
@@ -4358,7 +4661,7 @@ build_over_call (cand, args, flags)
{
tree t, *p = &TREE_VALUE (converted_args);
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
- DECL_VIRTUAL_CONTEXT (fn),
+ DECL_CONTEXT (fn),
ba_any, NULL);
my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
@@ -4377,10 +4680,22 @@ build_over_call (cand, args, flags)
else
fn = build_addr_func (fn);
+ return build_cxx_call (fn, args, converted_args);
+}
+
+/* Build and return a call to FN, using the the CONVERTED_ARGS. ARGS
+ gives the original form of the arguments. This function performs
+ no overload resolution, conversion, or other high-level
+ operations. */
+
+tree
+build_cxx_call(tree fn, tree args, tree converted_args)
+{
+ tree fndecl;
+
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
to do something useful. */
-
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
@@ -4391,20 +4706,32 @@ build_over_call (cand, args, flags)
return exp;
}
- /* Some built-in function calls will be evaluated at
- compile-time in fold (). */
- fn = fold (build_call (fn, converted_args));
+ fn = build_call (fn, converted_args);
+
+ /* If this call might throw an exception, note that fact. */
+ fndecl = get_callee_fndecl (fn);
+ if ((!fndecl || !TREE_NOTHROW (fndecl))
+ && at_function_scope_p ()
+ && cfun)
+ cp_function_chain->can_throw = 1;
+
+ /* Some built-in function calls will be evaluated at compile-time in
+ fold (). */
+ fn = fold (fn);
+
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
+
fn = require_complete_type (fn);
if (fn == error_mark_node)
return error_mark_node;
+
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn);
return convert_from_reference (fn);
}
-static tree java_iface_lookup_fn;
+static GTY(()) tree java_iface_lookup_fn;
/* Make an expression which yields the address of the Java interface
method FN. This is achieved by generating a call to libjava's
@@ -4428,16 +4755,15 @@ build_java_interface_fn_ref (fn, instance)
java_iface_lookup_fn
= builtin_function ("_Jv_LookupInterfaceMethodIdx",
build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL);
- ggc_add_tree_root (&java_iface_lookup_fn, 1);
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
}
/* Look up the pointer to the runtime java.lang.Class object for `instance'.
- This is the first entry in the vtable. */
+ This is the first entry in the vtable. */
klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0),
integer_zero_node);
- /* Get the java.lang.Class pointer for the interface being called. */
+ /* Get the java.lang.Class pointer for the interface being called. */
iface = DECL_CONTEXT (fn);
iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
@@ -4449,7 +4775,7 @@ build_java_interface_fn_ref (fn, instance)
}
iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
- /* Determine the itable index of FN. */
+ /* Determine the itable index of FN. */
i = 1;
for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
{
@@ -4493,143 +4819,190 @@ in_charge_arg_for_name (name)
return NULL_TREE;
}
-static tree
-build_new_method_call (instance, name, args, basetype_path, flags)
- tree instance, name, args, basetype_path;
- int flags;
+/* Build a call to a constructor, destructor, or an assignment
+ operator for INSTANCE, an expression with class type. NAME
+ indicates the special member function to call; ARGS are the
+ arguments. BINFO indicates the base of INSTANCE that is to be
+ passed as the `this' parameter to the member function called.
+
+ FLAGS are the LOOKUP_* flags to use when processing the call.
+
+ If NAME indicates a complete object constructor, INSTANCE may be
+ NULL_TREE. In this case, the caller will call build_cplus_new to
+ store the newly constructed object into a VAR_DECL. */
+
+tree
+build_special_member_call (tree instance, tree name, tree args,
+ tree binfo, int flags)
+{
+ tree fns;
+ /* The type of the subobject to be constructed or destroyed. */
+ tree class_type;
+
+ my_friendly_assert (name == complete_ctor_identifier
+ || name == base_ctor_identifier
+ || name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier
+ || name == ansi_assopname (NOP_EXPR),
+ 20020712);
+ my_friendly_assert (binfo != NULL_TREE, 20020712);
+
+ class_type = BINFO_TYPE (binfo);
+
+ /* Handle the special case where INSTANCE is NULL_TREE. */
+ if (name == complete_ctor_identifier && !instance)
+ {
+ instance = build_int_2 (0, 0);
+ TREE_TYPE (instance) = build_pointer_type (class_type);
+ instance = build1 (INDIRECT_REF, class_type, instance);
+ }
+ else if (name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier)
+ my_friendly_assert (args == NULL_TREE, 20020712);
+
+ my_friendly_assert (instance != NULL_TREE, 20020712);
+
+ /* Resolve the name. */
+ if (!complete_type_or_else (BINFO_TYPE (binfo), NULL_TREE))
+ return error_mark_node;
+
+ fns = lookup_fnfields (binfo, name, 1);
+
+ /* When making a call to a constructor or destructor for a subobject
+ that uses virtual base classes, pass down a pointer to a VTT for
+ the subobject. */
+ if ((name == base_ctor_identifier
+ || name == base_dtor_identifier)
+ && TYPE_USES_VIRTUAL_BASECLASSES (class_type))
+ {
+ tree vtt;
+ tree sub_vtt;
+
+ /* If the current function is a complete object constructor
+ or destructor, then we fetch the VTT directly.
+ Otherwise, we look it up using the VTT we were given. */
+ vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type));
+ vtt = decay_conversion (vtt);
+ vtt = build (COND_EXPR, TREE_TYPE (vtt),
+ build (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
+ current_vtt_parm,
+ vtt);
+ if (TREE_VIA_VIRTUAL (binfo))
+ binfo = binfo_for_vbase (class_type, current_class_type);
+ my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110);
+ sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
+ BINFO_SUBVTT_INDEX (binfo));
+
+ args = tree_cons (NULL_TREE, sub_vtt, args);
+ }
+
+ return build_new_method_call (instance, fns, args, binfo, flags);
+}
+
+/* Build a call to "INSTANCE.FN (ARGS)". */
+
+tree
+build_new_method_call (tree instance, tree fns, tree args,
+ tree conversion_path, int flags)
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
- tree basetype, mem_args = NULL_TREE, fns, instance_ptr;
- tree pretty_name;
+ tree basetype = NULL_TREE;
+ tree access_binfo;
+ tree optype;
+ tree mem_args = NULL_TREE, instance_ptr;
+ tree name, pretty_name;
tree user_args;
- tree templates = NULL_TREE;
tree call;
int template_only = 0;
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- explicit_targs = TREE_OPERAND (name, 1);
- name = TREE_OPERAND (name, 0);
- if (DECL_P (name))
- 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));
- }
+ my_friendly_assert (instance != NULL_TREE, 20020729);
- template_only = 1;
- }
+ if (instance == error_mark_node || fns == error_mark_node
+ || args == error_mark_node)
+ return error_mark_node;
+ /* Process the argument list. */
user_args = args;
args = resolve_args (args);
-
if (args == error_mark_node)
return error_mark_node;
- if (instance == NULL_TREE)
- basetype = BINFO_TYPE (basetype_path);
- else
+ if (TREE_CODE (instance) == OFFSET_REF)
+ instance = resolve_offset_ref (instance);
+ if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+ instance = convert_from_reference (instance);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
+ instance_ptr = build_this (instance);
+
+ if (!BASELINK_P (fns))
{
- if (TREE_CODE (instance) == OFFSET_REF)
- instance = resolve_offset_ref (instance);
- if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- instance = convert_from_reference (instance);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
+ call = build_field_call (instance_ptr, fns, args);
+ if (call)
+ return call;
+ error ("call to non-function `%D'", fns);
+ return error_mark_node;
+ }
- /* XXX this should be handled before we get here. */
- if (! IS_AGGR_TYPE (basetype))
- {
- if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- name, instance, basetype);
+ if (!conversion_path)
+ conversion_path = BASELINK_BINFO (fns);
+ access_binfo = BASELINK_ACCESS_BINFO (fns);
+ optype = BASELINK_OPTYPE (fns);
+ fns = BASELINK_FUNCTIONS (fns);
- return error_mark_node;
- }
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ {
+ explicit_targs = TREE_OPERAND (fns, 1);
+ fns = TREE_OPERAND (fns, 0);
+ template_only = 1;
}
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
+ my_friendly_assert (TREE_CODE (fns) == FUNCTION_DECL
+ || TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD,
+ 20020712);
- if (instance)
+ /* XXX this should be handled before we get here. */
+ if (! IS_AGGR_TYPE (basetype))
{
- instance_ptr = build_this (instance);
+ if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
+ error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ fns, instance, basetype);
- if (! template_only)
- {
- /* XXX this should be handled before we get here. */
- fns = build_field_call (basetype_path, instance_ptr, name, args);
- if (fns)
- return fns;
- }
- }
- else
- {
- instance_ptr = build_int_2 (0, 0);
- TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
+ return error_mark_node;
}
- /* Callers should explicitly indicate whether they want to construct
- the complete object or just the part without virtual bases. */
- my_friendly_assert (name != ctor_identifier, 20000408);
- /* Similarly for destructors. */
- my_friendly_assert (name != dtor_identifier, 20000408);
+ name = DECL_NAME (get_first_fn (fns));
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
- int constructor_p;
-
- constructor_p = (name == complete_ctor_identifier
- || name == base_ctor_identifier);
- pretty_name = (constructor_p
- ? constructor_name (basetype) : dtor_identifier);
-
- /* If we're a call to a constructor or destructor for a
- subobject that uses virtual base classes, then we need to
- pass down a pointer to a VTT for the subobject. */
- if ((name == base_ctor_identifier
- || name == base_dtor_identifier)
- && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- tree vtt;
- tree sub_vtt;
- tree basebinfo = basetype_path;
-
- /* If the current function is a complete object constructor
- or destructor, then we fetch the VTT directly.
- Otherwise, we look it up using the VTT we were given. */
- vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
- vtt = decay_conversion (vtt);
- vtt = build (COND_EXPR, TREE_TYPE (vtt),
- build (EQ_EXPR, boolean_type_node,
- current_in_charge_parm, integer_zero_node),
- current_vtt_parm,
- vtt);
- if (TREE_VIA_VIRTUAL (basebinfo))
- basebinfo = binfo_for_vbase (basetype, current_class_type);
- my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
- sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
- BINFO_SUBVTT_INDEX (basebinfo));
-
- args = tree_cons (NULL_TREE, sub_vtt, args);
- }
+ /* Callers should explicitly indicate whether they want to construct
+ the complete object or just the part without virtual bases. */
+ my_friendly_assert (name != ctor_identifier, 20000408);
+ /* Similarly for destructors. */
+ my_friendly_assert (name != dtor_identifier, 20000408);
+
+ if (name == complete_ctor_identifier
+ || name == base_ctor_identifier)
+ pretty_name = constructor_name (basetype);
+ else
+ pretty_name = dtor_identifier;
}
else
pretty_name = name;
- fns = lookup_fnfields (basetype_path, name, 1);
-
- if (fns == error_mark_node)
- return error_mark_node;
if (fns)
{
- tree base = BINFO_TYPE (TREE_PURPOSE (fns));
- tree fn = TREE_VALUE (fns);
+ tree fn;
+ tree class_type = (conversion_path
+ ? BINFO_TYPE (conversion_path)
+ : NULL_TREE);
+
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
- for (; fn; fn = OVL_NEXT (fn))
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
tree this_arglist;
@@ -4645,20 +5018,22 @@ build_new_method_call (instance, name, args, basetype_path, flags)
this_arglist = args;
if (TREE_CODE (t) == TEMPLATE_DECL)
- {
- /* A member template. */
- templates = tree_cons (NULL_TREE, t, templates);
- candidates =
- add_template_candidate (candidates, t, base, explicit_targs,
- this_arglist,
- TREE_TYPE (name), flags, DEDUCE_CALL);
- }
+ /* A member template. */
+ add_template_candidate (&candidates, t,
+ class_type,
+ explicit_targs,
+ this_arglist, optype,
+ access_binfo,
+ conversion_path,
+ flags,
+ DEDUCE_CALL);
else if (! template_only)
- candidates = add_function_candidate (candidates, t, base,
- this_arglist, flags);
-
- if (candidates)
- candidates->basetype_path = basetype_path;
+ add_function_candidate (&candidates, t,
+ class_type,
+ this_arglist,
+ access_binfo,
+ conversion_path,
+ flags);
}
}
@@ -4668,7 +5043,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
- incomplete_type_error (instance_ptr, basetype);
+ cxx_incomplete_type_error (instance_ptr, basetype);
else
error ("no matching function for call to `%T::%D(%A)%#V'",
basetype, pretty_name, user_args,
@@ -4713,16 +5088,16 @@ build_new_method_call (instance, name, args, basetype_path, flags)
else
{
call = build_over_call (cand, args, flags);
- /* Do evaluate the object parameter in a call to a static member
- function. */
- if (TREE_SIDE_EFFECTS (instance))
+ /* In an expression of the form `a->f()' where `f' turns out to
+ be a static member function, `a' is none-the-less evaluated. */
+ if (instance && TREE_SIDE_EFFECTS (instance))
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
}
return call;
}
-/* Returns non-zero iff standard conversion sequence ICS1 is a proper
+/* Returns nonzero iff standard conversion sequence ICS1 is a proper
subsequence of ICS2. */
static int
@@ -4762,7 +5137,7 @@ is_subseq (ics1, ics2)
}
}
-/* Returns non-zero iff DERIVED is derived from BASE. The inputs may
+/* Returns nonzero iff DERIVED is derived from BASE. The inputs may
be any _TYPE nodes. */
int
@@ -4860,7 +5235,7 @@ compare_ics (ics1, ics2)
tree deref_to_type2 = NULL_TREE;
int rank1, rank2;
- /* REF_BINDING is non-zero if the result of the conversion sequence
+ /* REF_BINDING is nonzero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the
type referred to by the reference. */
tree target_type1;
@@ -5206,25 +5581,10 @@ add_warning (winner, loser)
struct z_candidate *winner, *loser;
{
winner->warnings = tree_cons (NULL_TREE,
- build_ptr_wrapper (loser),
+ build_zc_wrapper (loser),
winner->warnings);
}
-/* Returns true iff functions are equivalent. Equivalent functions are
- not '==' only if one is a function-local extern function or if
- both are extern "C". */
-
-static inline int
-equal_functions (fn1, fn2)
- tree fn1;
- tree fn2;
-{
- if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
- || DECL_EXTERN_C_FUNCTION_P (fn1))
- return decls_match (fn1, fn2);
- return fn1 == fn2;
-}
-
/* Compare two candidates for overloading as described in
[over.match.best]. Return values:
@@ -5359,7 +5719,7 @@ joust (cand1, cand2, warn)
&& TREE_CODE (convn) == QUAL_CONV)
/* Don't complain about `operator char *()' beating
`operator const char *() const'. */;
- else if (warn)
+ else if (warn && warn_conversion)
{
tree source = source_type (TREE_VEC_ELT (w->convs, 0));
if (! DECL_CONSTRUCTOR_P (w->fn))
@@ -5488,11 +5848,9 @@ tweak:
if (winner)
{
if (warn)
- {
- pedwarn ("choosing `%D' over `%D'", w->fn, l->fn);
- pedwarn (
-" because worst conversion for the former is better than worst conversion for the latter");
- }
+ pedwarn ("ISO C++ says that `%D' and `%D' are ambiguous \
+even though the worst conversion for the former is better than the worst \
+conversion for the latter", w->fn, l->fn);
else
add_warning (w, l);
return winner;
@@ -5559,7 +5917,7 @@ tourney (candidates)
return champ;
}
-/* Returns non-zero if things of type FROM can be converted to TO. */
+/* Returns nonzero if things of type FROM can be converted to TO. */
int
can_convert (to, from)
@@ -5568,7 +5926,7 @@ can_convert (to, from)
return can_convert_arg (to, from, NULL_TREE);
}
-/* Returns non-zero if ARG (of type FROM) can be converted to TO. */
+/* Returns nonzero if ARG (of type FROM) can be converted to TO. */
int
can_convert_arg (to, from, arg)
@@ -5614,17 +5972,81 @@ perform_implicit_conversion (type, expr)
return convert_like (conv, expr);
}
+/* Convert EXPR to TYPE (as a direct-initialization) if that is
+ permitted. If the conversion is valid, the converted expression is
+ returned. Otherwise, NULL_TREE is returned. */
+
+tree
+perform_direct_initialization_if_possible (tree type, tree expr)
+{
+ tree conv;
+
+ if (type == error_mark_node || error_operand_p (expr))
+ return error_mark_node;
+ conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ LOOKUP_NORMAL);
+ if (!conv || ICS_BAD_FLAG (conv))
+ return NULL_TREE;
+ return convert_like_real (conv, expr, NULL_TREE, 0, 0,
+ /*issue_conversion_warnings=*/false);
+}
+
+/* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference
+ is being bound to a temporary. Create and return a new VAR_DECL
+ with the indicated TYPE; this variable will store the value to
+ which the reference is bound. */
+
+tree
+make_temporary_var_for_ref_to_temp (tree decl, tree type)
+{
+ tree var;
+
+ /* Create the variable. */
+ var = build_decl (VAR_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (var) = 1;
+ TREE_USED (var) = 1;
+
+ /* Register the variable. */
+ if (TREE_STATIC (decl))
+ {
+ /* Namespace-scope or local static; give it a mangled name. */
+ tree name;
+
+ TREE_STATIC (var) = 1;
+ name = mangle_ref_init_variable (decl);
+ DECL_NAME (var) = name;
+ SET_DECL_ASSEMBLER_NAME (var, name);
+ var = pushdecl_top_level (var);
+ }
+ else
+ {
+ /* Create a new cleanup level if necessary. */
+ maybe_push_cleanup_level (type);
+ /* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
+ DECL_CONTEXT (var) = current_function_decl;
+ }
+
+ return var;
+}
+
/* Convert EXPR to the indicated reference TYPE, in a way suitable for
- initializing a variable of that TYPE. Return the converted
- expression. */
+ initializing a variable of that TYPE. If DECL is non-NULL, it is
+ the VAR_DECL being initialized with the EXPR. (In that case, the
+ type of DECL will be TYPE.)
+
+ Return the converted expression. */
tree
-initialize_reference (type, expr)
+initialize_reference (type, expr, decl)
tree type;
tree expr;
+ tree decl;
{
tree conv;
+ if (type == error_mark_node || error_operand_p (expr))
+ return error_mark_node;
+
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
@@ -5632,5 +6054,101 @@ initialize_reference (type, expr)
return error_mark_node;
}
+ /* If DECL is non-NULL, then this special rule applies:
+
+ [class.temporary]
+
+ The temporary to which the reference is bound or the temporary
+ that is the complete object to which the reference is bound
+ persists for the lifetime of the reference.
+
+ The temporaries created during the evaluation of the expression
+ initializing the reference, except the temporary to which the
+ reference is bound, are destroyed at the end of the
+ full-expression in which they are created.
+
+ In that case, we store the converted expression into a new
+ VAR_DECL in a new scope.
+
+ However, we want to be careful not to create temporaries when
+ they are not required. For example, given:
+
+ struct B {};
+ struct D : public B {};
+ D f();
+ const B& b = f();
+
+ there is no need to copy the return value from "f"; we can just
+ extend its lifetime. Similarly, given:
+
+ struct S {};
+ struct T { operator S(); };
+ T t;
+ const S& s = t;
+
+ we can extend the lifetime of the return value of the conversion
+ operator. */
+ my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
+ if (decl)
+ {
+ tree var;
+ tree base_conv_type;
+
+ /* Skip over the REF_BIND. */
+ conv = TREE_OPERAND (conv, 0);
+ /* If the next conversion is a BASE_CONV, skip that too -- but
+ remember that the conversion was required. */
+ if (TREE_CODE (conv) == BASE_CONV && !NEED_TEMPORARY_P (conv))
+ {
+ base_conv_type = TREE_TYPE (conv);
+ conv = TREE_OPERAND (conv, 0);
+ }
+ else
+ base_conv_type = NULL_TREE;
+ /* Perform the remainder of the conversion. */
+ expr = convert_like (conv, expr);
+ if (!real_non_cast_lvalue_p (expr))
+ {
+ tree init;
+ tree type;
+
+ /* Create the temporary variable. */
+ type = TREE_TYPE (expr);
+ var = make_temporary_var_for_ref_to_temp (decl, type);
+ layout_decl (var, 0);
+ if (at_function_scope_p ())
+ {
+ tree cleanup;
+
+ add_decl_stmt (var);
+ cleanup = cxx_maybe_build_cleanup (var);
+ if (cleanup)
+ finish_decl_cleanup (var, cleanup);
+ }
+ else
+ {
+ rest_of_decl_compilation (var, NULL, /*toplev=*/1, at_eof);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ static_aggregates = tree_cons (NULL_TREE, var,
+ static_aggregates);
+ }
+ init = build (INIT_EXPR, type, var, expr);
+ /* Use its address to initialize the reference variable. */
+ expr = build_address (var);
+ expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
+ }
+ else
+ /* Take the address of EXPR. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ /* If a BASE_CONV was required, perform it now. */
+ if (base_conv_type)
+ expr = (perform_implicit_conversion
+ (build_pointer_type (base_conv_type), expr));
+ return build_nop (type, expr);
+ }
+
+ /* Perform the conversion. */
return convert_like (conv, expr);
}
+
+#include "gt-cp-call.h"
diff --git a/contrib/gcc/cp/cfns.gperf b/contrib/gcc/cp/cfns.gperf
index 0d1e71b..e0e9f23 100644
--- a/contrib/gcc/cp/cfns.gperf
+++ b/contrib/gcc/cp/cfns.gperf
@@ -16,9 +16,9 @@ const char * libc_name_p PARAMS ((const char *, unsigned int));
# exception, unless it calls a program-supplied function that
# throws an exception.
#
-# bsearch and qsort are commented out because they can call such functions.
+# Specific functions are commented out for the reason noted in each case.
#
-abort
+# abort -- synchronous exception from SIGABRT handler
abs
acos
asctime
@@ -29,7 +29,7 @@ atexit
atof
atoi
atol
-#bsearch
+#bsearch -- calls user function which may throw exception
btowc
calloc
ceil
@@ -43,41 +43,41 @@ div
exit
exp
fabs
-fclose
+#fclose -- POSIX thread cancellation point
feof
ferror
-fflush
-fgetc
-fgetpos
-fgets
-fgetwc
-fgetws
+#fflush -- POSIX thread cancellation point
+#fgetc -- POSIX thread cancellation point
+#fgetpos -- POSIX thread cancellation point
+#fgets -- POSIX thread cancellation point
+#fgetwc -- POSIX thread cancellation point
+#fgetws -- POSIX thread cancellation point
floor
fmod
-fopen
-fprintf
-fputc
-fputs
-fputwc
-fputws
-fread
+#fopen -- POSIX thread cancellation point
+#fprintf -- POSIX thread cancellation point
+#fputc -- POSIX thread cancellation point
+#fputs -- POSIX thread cancellation point
+#fputwc -- POSIX thread cancellation point
+#fputws -- POSIX thread cancellation point
+#fread -- POSIX thread cancellation point
free
-freopen
+#freopen -- POSIX thread cancellation point
frexp
-fscanf
+#fscanf -- POSIX thread cancellation point
fseek
-fsetpos
-ftell
+#fsetpos -- POSIX thread cancellation point
+#ftell -- POSIX thread cancellation point
fwide
-fwprintf
-fwrite
-fwscanf
-getc
-getchar
+#fwprintf -- POSIX thread cancellation point
+#fwrite -- POSIX thread cancellation point
+#fwscanf -- POSIX thread cancellation point
+#getc -- POSIX thread cancellation point
+#getchar -- POSIX thread cancellation point
getenv
-gets
-getwc
-getwchar
+#gets -- POSIX thread cancellation point
+#getwc -- POSIX thread cancellation point
+#getwchar -- POSIX thread cancellation point
gmtime
isalnum
isalpha
@@ -125,22 +125,22 @@ memmove
memset
mktime
modf
-perror
+#perror -- POSIX thread cancellation point
pow
-printf
-putc
-putchar
-puts
-putwc
-putwchar
-#qsort
-raise
+#printf -- POSIX thread cancellation point
+#putc -- POSIX thread cancellation point
+#putchar -- POSIX thread cancellation point
+#puts -- POSIX thread cancellation point
+#putwc -- POSIX thread cancellation point
+#putwchar -- POSIX thread cancellation point
+#qsort -- calls user function which may throw exception
+#raise -- synchronous exception from signal handler
rand
realloc
-remove
-rename
-rewind
-scanf
+#remove -- POSIX thread cancellation point
+#rename -- POSIX thread cancellation point
+#rewind -- POSIX thread cancellation point
+#scanf -- POSIX thread cancellation point
setbuf
setlocale
setvbuf
@@ -157,7 +157,7 @@ strcmp
strcoll
strcpy
strcspn
-strerror
+#strerror -- POSIX thread cancellation point
strftime
strlen
strncat
@@ -174,25 +174,25 @@ strtoul
strxfrm
swprintf
swscanf
-system
+#system -- POSIX thread cancellation point
tan
tanh
time
-tmpfile
-tmpnam
+#tmpfile -- POSIX thread cancellation point
+#tmpnam -- POSIX thread cancellation point
tolower
toupper
towctrans
towlower
towupper
-ungetc
-ungetwc
-vfprintf
-vfwprintf
-vprintf
+#ungetc -- POSIX thread cancellation point
+#ungetwc -- POSIX thread cancellation point
+#vfprintf -- POSIX thread cancellation point
+#vfwprintf -- POSIX thread cancellation point
+#vprintf -- POSIX thread cancellation point
vsprintf
vswprintf
-vwprintf
+#vwprintf -- POSIX thread cancellation point
wcrtomb
wcscat
wcschr
@@ -225,5 +225,5 @@ wmemcmp
wmemcpy
wmemmove
wmemset
-wprintf
-wscanf
+#wprintf -- POSIX thread cancellation point
+#wscanf -- POSIX thread cancellation point
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 2ac4e30..82eede5 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -35,10 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "target.h"
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -91,6 +87,9 @@ typedef struct vtbl_init_data_s
/* Nonzero if we are building the initializer for a construction
vtable. */
int ctor_vtbl_p;
+ /* True when adding vcall offset entries to the vtable. False when
+ merely computing the indices. */
+ bool generate_vcall_entries;
} vtbl_init_data;
/* The type of a function passed to walk_subobject_offsets. */
@@ -107,7 +106,6 @@ varray_type local_classes;
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_basefndecls PARAMS ((tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
@@ -119,16 +117,15 @@ static void delete_duplicate_fields PARAMS ((tree));
static void finish_struct_bits PARAMS ((tree));
static int alter_access PARAMS ((tree, tree, tree));
static void handle_using_decl PARAMS ((tree, tree));
-static int strictly_overrides PARAMS ((tree, tree));
static void check_for_override PARAMS ((tree, tree));
static tree dfs_modify_vtables PARAMS ((tree, void *));
-static tree modify_all_vtables PARAMS ((tree, int *, tree));
-static void determine_primary_base PARAMS ((tree, int *));
+static tree modify_all_vtables PARAMS ((tree, tree));
+static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
static int field_decl_cmp PARAMS ((const tree *, const tree *));
static int method_name_cmp PARAMS ((const tree *, const tree *));
-static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
+static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree));
@@ -138,29 +135,28 @@ static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
-static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
-static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
- int *));
-static bool build_base_field PARAMS ((record_layout_info, tree, int *,
- splay_tree, tree));
-static bool build_base_fields PARAMS ((record_layout_info, int *,
- splay_tree, tree));
+static void check_field_decl (tree, tree, int *, int *, int *, int *);
+static void check_field_decls (tree, tree *, int *, int *, int *);
+static tree *build_base_field (record_layout_info, tree, splay_tree, tree *);
+static void build_base_fields (record_layout_info, splay_tree, tree *);
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
-static void check_bases_and_members PARAMS ((tree, int *));
-static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *));
-static void layout_class_type PARAMS ((tree, int *, int *, tree *));
+static void check_bases_and_members (tree);
+static tree create_vtable_ptr (tree, tree *);
+static void include_empty_classes (record_layout_info);
+static void layout_class_type (tree, tree *);
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
-static void set_primary_base PARAMS ((tree, tree, int *));
+static void set_primary_base PARAMS ((tree, tree));
static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
-static void layout_virtual_bases PARAMS ((tree, splay_tree));
+static void layout_virtual_bases (record_layout_info, splay_tree);
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset (tree, tree, vtbl_init_data *);
static void layout_vtable_decl PARAMS ((tree, int));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
@@ -175,14 +171,12 @@ static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
- tree, tree,
- splay_tree, tree));
-static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
+ tree, tree, splay_tree));
+static tree end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
tree));
-static void set_vindex PARAMS ((tree, int *));
static void build_rtti_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vtbl_init_data *));
@@ -212,8 +206,14 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
-static void warn_about_ambiguous_direct_bases PARAMS ((tree));
+static void warn_about_ambiguous_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
+static bool contains_empty_class_p (tree);
+static tree dfs_base_derived_from (tree, void *);
+static bool base_derived_from (tree, tree);
+static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
+static tree end_of_base (tree);
+static tree get_vcall_index (tree, tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -288,13 +288,15 @@ build_base_path (code, expr, binfo, nonnull)
return error_mark_node;
}
+ if (!want_pointer)
+ /* This must happen before the call to save_expr. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
- if (!want_pointer)
- expr = build_unary_op (ADDR_EXPR, expr, 0);
- else if (!nonnull)
+ if (want_pointer && !nonnull)
null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
offset = BINFO_OFFSET (binfo);
@@ -304,8 +306,27 @@ build_base_path (code, expr, binfo, nonnull)
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
V_BINFO. That offset is an entry in D_BINFO's vtable. */
- tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
- TREE_TYPE (TREE_TYPE (expr)));
+ tree v_offset;
+
+ if (fixed_type_p < 0 && in_base_initializer)
+ {
+ /* In a base member initializer, we cannot rely on
+ the vtable being set up. We have to use the vtt_parm. */
+ tree derived = v_binfo;
+
+ while (BINFO_INHERITANCE_CHAIN (derived))
+ derived = BINFO_INHERITANCE_CHAIN (derived);
+
+ v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
+ current_vtt_parm, BINFO_VPTR_INDEX (derived));
+
+ v_offset = build1 (INDIRECT_REF,
+ TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
+ v_offset);
+ }
+ else
+ v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ TREE_TYPE (TREE_TYPE (expr)));
v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (d_binfo));
@@ -315,7 +336,8 @@ build_base_path (code, expr, binfo, nonnull)
build_pointer_type (ptrdiff_type_node),
v_offset);
v_offset = build_indirect_ref (v_offset, NULL);
-
+ TREE_CONSTANT (v_offset) = 1;
+
offset = cp_convert (ptrdiff_type_node,
size_diffop (offset, BINFO_OFFSET (v_binfo)));
@@ -361,6 +383,24 @@ build_base_path (code, expr, binfo, nonnull)
return expr;
}
+/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
+ message is emitted if TYPE is inaccessible. OBJECT is assumed to
+ be non-NULL. */
+
+tree
+convert_to_base (tree object, tree type, bool check_access)
+{
+ tree binfo;
+
+ binfo = lookup_base (TREE_TYPE (object), type,
+ check_access ? ba_check : ba_ignore,
+ NULL);
+ if (!binfo || binfo == error_mark_node)
+ return error_mark_node;
+
+ return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+}
+
/* Virtual function things. */
@@ -400,75 +440,36 @@ static tree
build_vtbl_ref_1 (instance, idx)
tree instance, idx;
{
- tree vtbl, aref;
- tree basetype = TREE_TYPE (instance);
+ tree aref;
+ tree vtbl = NULL_TREE;
+
+ /* Try to figure out what a reference refers to, and
+ access its virtual function table directly. */
+
+ int cdtorp = 0;
+ tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
+ tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (instance == current_class_ref)
- vtbl = build_vfield_ref (instance, basetype);
- else
+ if (fixed_type && !cdtorp)
{
- if (optimize)
- {
- /* Try to figure out what a reference refers to, and
- access its virtual function table directly. */
- tree ref = NULL_TREE;
-
- if (TREE_CODE (instance) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)
- ref = TREE_OPERAND (instance, 0);
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- ref = instance;
-
- if (ref && TREE_CODE (ref) == VAR_DECL
- && DECL_INITIAL (ref))
- {
- tree init = DECL_INITIAL (ref);
-
- while (TREE_CODE (init) == NOP_EXPR
- || TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == ADDR_EXPR)
- {
- init = TREE_OPERAND (init, 0);
- if (IS_AGGR_TYPE (TREE_TYPE (init))
- && (TREE_CODE (init) == PARM_DECL
- || TREE_CODE (init) == VAR_DECL))
- instance = init;
- }
- }
- }
+ tree binfo = lookup_base (fixed_type, basetype,
+ ba_ignore|ba_quiet, NULL);
+ if (binfo)
+ vtbl = BINFO_VTABLE (binfo);
+ }
- if (IS_AGGR_TYPE (TREE_TYPE (instance))
- && (TREE_CODE (instance) == RESULT_DECL
- || TREE_CODE (instance) == PARM_DECL
- || TREE_CODE (instance) == VAR_DECL))
- {
- vtbl = TYPE_BINFO_VTABLE (basetype);
- /* Knowing the dynamic type of INSTANCE we can easily obtain
- the correct vtable entry. We resolve this back to be in
- terms of the primary vtable. */
- if (TREE_CODE (vtbl) == PLUS_EXPR)
- {
- idx = fold (build (PLUS_EXPR,
- TREE_TYPE (idx),
- idx,
- build (EXACT_DIV_EXPR,
- TREE_TYPE (idx),
- TREE_OPERAND (vtbl, 1),
- TYPE_SIZE_UNIT (vtable_entry_type))));
- vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
- }
- }
- else
- vtbl = build_vfield_ref (instance, basetype);
+ if (!vtbl)
+ {
+ vtbl = build_vfield_ref (instance, basetype);
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
+ TREE_CONSTANT (aref) = 1;
return aref;
}
@@ -547,6 +548,8 @@ build_vtable (class_type, name, vtable_type)
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
+
import_export_vtable (decl, class_type, 0);
return decl;
@@ -554,7 +557,7 @@ build_vtable (class_type, name, vtable_type)
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
or even complete. If this does not exist, create it. If COMPLETE is
- non-zero, then complete the definition of it -- that will render it
+ nonzero, then complete the definition of it -- that will render it
impossible to actually build the vtable, but is useful to get at those
which are known to exist in the runtime. */
@@ -563,21 +566,14 @@ get_vtable_decl (type, complete)
tree type;
int complete;
{
- tree name = get_vtable_name (type);
- tree decl = IDENTIFIER_GLOBAL_VALUE (name);
-
- if (decl)
- {
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- && DECL_VIRTUAL_P (decl), 20000118);
- return decl;
- }
-
- decl = build_vtable (type, name, void_type_node);
- decl = pushdecl_top_level (decl);
- my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
- 20000517);
+ tree decl;
+
+ if (CLASSTYPE_VTABLES (type))
+ return CLASSTYPE_VTABLES (type);
+ decl = build_vtable (type, get_vtable_name (type), void_type_node);
+ CLASSTYPE_VTABLES (type) = decl;
+
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
@@ -604,10 +600,7 @@ copy_virtuals (binfo)
copies = copy_list (BINFO_VIRTUALS (binfo));
for (t = copies; t; t = TREE_CHAIN (t))
- {
- BV_VCALL_INDEX (t) = NULL_TREE;
- BV_USE_VCALL_INDEX_P (t) = 0;
- }
+ BV_VCALL_INDEX (t) = NULL_TREE;
return copies;
}
@@ -615,7 +608,7 @@ copy_virtuals (binfo)
/* Build the primary virtual function table for TYPE. If BINFO is
non-NULL, build the vtable starting with the initial approximation
that it is the same as the one which is the head of the association
- list. Returns a non-zero value if a new vtable is actually
+ list. Returns a nonzero value if a new vtable is actually
created. */
static int
@@ -667,7 +660,7 @@ build_primary_vtable (binfo, type)
FOR_TYPE is the most derived type which caused this table to
be needed.
- Returns non-zero if we haven't met BINFO before.
+ Returns nonzero if we haven't met BINFO before.
The order in which vtables are built (by calling this function) for
an object must remain the same, otherwise a binary incompatibility
@@ -698,7 +691,7 @@ build_secondary_vtable (binfo, for_type)
}
/* Create a new vtable for BINFO which is the hierarchy dominated by
- T. Return non-zero if we actually created a new vtable. */
+ T. Return nonzero if we actually created a new vtable. */
static int
make_new_vtable (t, binfo)
@@ -760,37 +753,9 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
BV_DELTA (v) = delta;
BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl;
-
- /* Now assign virtual dispatch information, if unset. We can
- dispatch this through any overridden base function.
-
- FIXME this can choose a secondary vtable if the primary is not
- also lexically first, leading to useless conversions.
- In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
- ever be different from DECL_CONTEXT. */
- if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- {
- DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
- DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
- }
}
}
-/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
- functions present in the vtable so far. */
-
-static void
-set_vindex (decl, vfuns_p)
- tree decl;
- int *vfuns_p;
-{
- int vindex;
-
- vindex = *vfuns_p;
- *vfuns_p += (TARGET_VTABLE_USES_DESCRIPTORS
- ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
- DECL_VINDEX (decl) = build_shared_int_cst (vindex);
-}
/* Add method METHOD to class TYPE. If ERROR_P is true, we are adding
the method after the class has already been defined because a
@@ -807,6 +772,8 @@ add_method (type, method, error_p)
int len;
int slot;
tree method_vec;
+ int template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (method));
if (!CLASSTYPE_METHOD_VEC (type))
/* Make a new method vector. We start with 8 entries. We must
@@ -831,14 +798,36 @@ add_method (type, method, error_p)
slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
+ int have_template_convs_p = 0;
+
/* See if we already have an entry with this name. */
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
- if (!TREE_VEC_ELT (method_vec, slot)
- || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
- slot)))
- == DECL_NAME (method)))
- break;
-
+ {
+ tree m = TREE_VEC_ELT (method_vec, slot);
+
+ if (!m)
+ break;
+ m = OVL_CURRENT (m);
+
+ if (template_conv_p)
+ {
+ have_template_convs_p = (TREE_CODE (m) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (m));
+
+ /* If we need to move things up, see if there's
+ space. */
+ if (!have_template_convs_p)
+ {
+ slot = len - 1;
+ if (TREE_VEC_ELT (method_vec, slot))
+ slot++;
+ }
+ break;
+ }
+ if (DECL_NAME (m) == DECL_NAME (method))
+ break;
+ }
+
if (slot == len)
{
/* We need a bigger method vector. */
@@ -871,22 +860,27 @@ add_method (type, method, error_p)
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)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
+ if (template_conv_p)
+ slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ else
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
+ {
+ 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 (!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))
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ /* We can insert the new function right at the
+ SLOTth position. */
+ break;
+ }
+
+ if (template_conv_p && have_template_convs_p)
+ /*OK*/;
+ else if (!TREE_VEC_ELT (method_vec, slot))
/* There is nothing in the Ith slot, so we can avoid
moving anything. */
;
@@ -985,7 +979,7 @@ add_method (type, method, error_p)
TREE_VEC_ELT (method_vec, slot)
= build_overload (method, TREE_VEC_ELT (method_vec, slot));
- /* Add the new binding. */
+ /* Add the new binding. */
if (!DECL_CONSTRUCTOR_P (method)
&& !DECL_DESTRUCTOR_P (method))
push_class_level_binding (DECL_NAME (method),
@@ -1157,6 +1151,9 @@ handle_using_decl (using_decl, t)
tree flist = NULL_TREE;
tree old_value;
+ if (ctype == error_mark_node)
+ return;
+
binfo = lookup_base (t, ctype, ba_any, NULL);
if (! binfo)
{
@@ -1164,14 +1161,12 @@ handle_using_decl (using_decl, t)
return;
}
- if (name == constructor_name (ctype)
- || name == constructor_name_full (ctype))
+ if (constructor_name_p (name, ctype))
{
cp_error_at ("`%D' names constructor", using_decl);
return;
}
- if (name == constructor_name (t)
- || name == constructor_name_full (t))
+ if (constructor_name_p (name, t))
{
cp_error_at ("`%D' invalid in `%T'", using_decl, t);
return;
@@ -1186,8 +1181,8 @@ handle_using_decl (using_decl, t)
}
if (BASELINK_P (fdecl))
- /* Ignore base type this came from. */
- fdecl = TREE_VALUE (fdecl);
+ /* Ignore base type this came from. */
+ fdecl = BASELINK_FUNCTIONS (fdecl);
old_value = IDENTIFIER_CLASS_VALUE (name);
if (old_value)
@@ -1319,7 +1314,7 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
}
if (TREE_VIA_VIRTUAL (base_binfo))
- /* A virtual base does not effect nearly emptiness. */
+ /* A virtual base does not effect nearly emptiness. */
;
else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
@@ -1328,7 +1323,7 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
derived class is not nearly empty either. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
else
- /* Remember we've seen one. */
+ /* Remember we've seen one. */
seen_non_virtual_nearly_empty_base_p = 1;
}
else if (!is_empty_class (basetype))
@@ -1477,7 +1472,7 @@ mark_primary_virtual_base (base_binfo, type)
/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
base, then BINFO has no primary base in this graph. Called from
- mark_primary_bases. DATA is the most derived type. */
+ mark_primary_bases. DATA is the most derived type. */
static tree dfs_unshared_virtual_bases (binfo, data)
tree binfo;
@@ -1510,11 +1505,11 @@ static tree dfs_unshared_virtual_bases (binfo, data)
if (binfo != TYPE_BINFO (t))
/* The vtable fields will have been copied when duplicating the
base binfos. That information is bogus, make sure we don't try
- and use it. */
+ and use it. */
BINFO_VTABLE (binfo) = NULL_TREE;
/* If this is a virtual primary base, make sure its offset matches
- that which it is primary for. */
+ that which it is primary for. */
if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo) &&
binfo_for_vbase (BINFO_TYPE (binfo), t) == binfo)
{
@@ -1543,7 +1538,7 @@ mark_primary_bases (type)
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
- /* Not a dynamic base. */
+ /* Not a dynamic base. */
continue;
base_binfo = get_primary_binfo (binfo);
@@ -1572,10 +1567,9 @@ mark_primary_bases (type)
/* Make the BINFO the primary base of T. */
static void
-set_primary_base (t, binfo, vfuns_p)
+set_primary_base (t, binfo)
tree t;
tree binfo;
- int *vfuns_p;
{
tree basetype;
@@ -1584,16 +1578,13 @@ set_primary_base (t, binfo, vfuns_p)
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
- *vfuns_p = CLASSTYPE_VSIZE (basetype);
}
/* Determine the primary class for T. */
static void
-determine_primary_base (t, vfuns_p)
+determine_primary_base (t)
tree t;
- int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
tree vbases;
@@ -1612,12 +1603,6 @@ determine_primary_base (t, vfuns_p)
if (TYPE_CONTAINS_VPTR_P (basetype))
{
- /* Even a virtual baseclass can contain our RTTI
- information. But, we prefer a non-virtual polymorphic
- baseclass. */
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
-
/* We prefer a non-virtual base, although a virtual one will
do. */
if (TREE_VIA_VIRTUAL (base_binfo))
@@ -1625,7 +1610,7 @@ determine_primary_base (t, vfuns_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- set_primary_base (t, base_binfo, vfuns_p);
+ set_primary_base (t, base_binfo);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
@@ -1727,7 +1712,7 @@ determine_primary_base (t, vfuns_p)
/* If we've got a primary base, use it. */
if (candidate)
{
- set_primary_base (t, candidate, vfuns_p);
+ set_primary_base (t, candidate);
CLASSTYPE_VFIELDS (t)
= copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
}
@@ -1871,7 +1856,7 @@ maybe_warn_about_overly_private_class (t)
return;
has_nonprivate_method = 1;
- break;
+ /* Keep searching for a static member function. */
}
else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
has_member_fn = 1;
@@ -2113,12 +2098,14 @@ duplicate_tag_error (t)
memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
+ TYPE_LANG_SPECIFIC (t)->u.h.is_lang_type_class = 1;
TYPE_BINFO (t) = binfo;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
CLASSTYPE_TEMPLATE_INFO (t) = template_info;
CLASSTYPE_USE_TEMPLATE (t) = use_template;
+ CLASSTYPE_DECL_LIST (t) = NULL_TREE;
}
TYPE_SIZE (t) = NULL_TREE;
TYPE_MODE (t) = VOIDmode;
@@ -2164,7 +2151,7 @@ layout_vtable_decl (binfo, n)
layout_decl (vtable, 0);
/* At one time the vtable info was grabbed 2 words at a time. This
- fails on Sparc unless you have 8-byte alignment. */
+ fails on SPARC unless you have 8-byte alignment. */
DECL_ALIGN (vtable) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (vtable));
}
@@ -2202,6 +2189,29 @@ same_signature_p (fndecl, base_fndecl)
return 0;
}
+/* Called from base_derived_from via dfs_walk. */
+
+static tree
+dfs_base_derived_from (tree binfo, void *data)
+{
+ tree base = (tree) data;
+
+ if (same_type_p (TREE_TYPE (base), TREE_TYPE (binfo))
+ && tree_int_cst_equal (BINFO_OFFSET (base), BINFO_OFFSET (binfo)))
+ return error_mark_node;
+
+ return NULL_TREE;
+}
+
+/* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
+ subobject. */
+
+static bool
+base_derived_from (tree derived, tree base)
+{
+ return dfs_walk (derived, dfs_base_derived_from, NULL, base) != NULL_TREE;
+}
+
typedef struct find_final_overrider_data_s {
/* The function for which we are trying to find a final overrider. */
tree fn;
@@ -2209,14 +2219,8 @@ typedef struct find_final_overrider_data_s {
tree declaring_base;
/* The most derived class in the hierarchy. */
tree most_derived_type;
- /* The final overriding function. */
- tree overriding_fn;
- /* The functions that we thought might be final overriders, but
- aren't. */
+ /* The candidate overriders. */
tree candidates;
- /* The BINFO for the class in which the final overriding function
- appears. */
- tree overriding_base;
} find_final_overrider_data;
/* Called from find_final_overrider via dfs_walk. */
@@ -2240,119 +2244,46 @@ dfs_find_final_overrider (binfo, data)
method = NULL_TREE;
/* We've found a path to the declaring base. Walk down the path
looking for an overrider for FN. */
- for (path = reverse_path (binfo);
- path;
- path = TREE_CHAIN (path))
+ path = reverse_path (binfo);
+ while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
+ ffod->most_derived_type))
+ path = TREE_CHAIN (path);
+ while (path)
{
method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
ffod->fn);
if (method)
- break;
+ {
+ path = TREE_VALUE (path);
+ break;
+ }
+
+ path = TREE_CHAIN (path);
}
/* If we found an overrider, record the overriding function, and
the base from which it came. */
if (path)
{
- tree base;
-
- /* Assume the path is non-virtual. See if there are any
- virtual bases from (but not including) the overrider up
- to and including the base where the function is
- defined. */
- for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
- if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
- {
- base = ffod->declaring_base;
- break;
- }
+ tree *candidate;
- /* If we didn't already have an overrider, or any
- candidates, then this function is the best candidate so
- far. */
- if (!ffod->overriding_fn && !ffod->candidates)
- {
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- }
- else if (ffod->overriding_fn)
+ /* Remove any candidates overridden by this new function. */
+ candidate = &ffod->candidates;
+ while (*candidate)
{
- /* We had a best overrider; let's see how this compares. */
-
- if (ffod->overriding_fn == method
- && (tree_int_cst_equal
- (BINFO_OFFSET (TREE_VALUE (path)),
- BINFO_OFFSET (ffod->overriding_base))))
- /* We found the same overrider we already have, and in the
- same place; it's still the best. */;
- else if (strictly_overrides (ffod->overriding_fn, method))
- /* The old function overrides this function; it's still the
- best. */;
- else if (strictly_overrides (method, ffod->overriding_fn))
- {
- /* The new function overrides the old; it's now the
- best. */
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- }
+ /* If *CANDIDATE overrides METHOD, then METHOD
+ cannot override anything else on the list. */
+ if (base_derived_from (TREE_VALUE (*candidate), path))
+ return NULL_TREE;
+ /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
+ if (base_derived_from (path, TREE_VALUE (*candidate)))
+ *candidate = TREE_CHAIN (*candidate);
else
- {
- /* Ambiguous. */
- ffod->candidates
- = build_tree_list (NULL_TREE,
- ffod->overriding_fn);
- if (method != ffod->overriding_fn)
- ffod->candidates
- = tree_cons (NULL_TREE, method, ffod->candidates);
- ffod->overriding_fn = NULL_TREE;
- ffod->overriding_base = NULL_TREE;
- }
+ candidate = &TREE_CHAIN (*candidate);
}
- else
- {
- /* We had a list of ambiguous overrides; let's see how this
- new one compares. */
-
- tree candidates;
- bool incomparable = false;
-
- /* If there were previous candidates, and this function
- overrides all of them, then it is the new best
- candidate. */
- for (candidates = ffod->candidates;
- candidates;
- candidates = TREE_CHAIN (candidates))
- {
- /* If the candidate overrides the METHOD, then we
- needn't worry about it any further. */
- if (strictly_overrides (TREE_VALUE (candidates),
- method))
- {
- method = NULL_TREE;
- break;
- }
-
- /* If the METHOD doesn't override the candidate,
- then it is incomporable. */
- if (!strictly_overrides (method,
- TREE_VALUE (candidates)))
- incomparable = true;
- }
- /* If METHOD overrode all the candidates, then it is the
- new best candidate. */
- if (!candidates && !incomparable)
- {
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- ffod->candidates = NULL_TREE;
- }
- /* If METHOD didn't override all the candidates, then it
- is another candidate. */
- else if (method && incomparable)
- ffod->candidates
- = tree_cons (NULL_TREE, method, ffod->candidates);
- }
+ /* Add the new function. */
+ ffod->candidates = tree_cons (method, path, ffod->candidates);
}
}
@@ -2361,18 +2292,18 @@ dfs_find_final_overrider (binfo, data)
/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
FN and whose TREE_VALUE is the binfo for the base where the
- overriding occurs. BINFO (in the hierarchy dominated by T) is the
- base object in which FN is declared. */
+ overriding occurs. BINFO (in the hierarchy dominated by the binfo
+ DERIVED) is the base object in which FN is declared. */
static tree
-find_final_overrider (t, binfo, fn)
- tree t;
+find_final_overrider (derived, binfo, fn)
+ tree derived;
tree binfo;
tree fn;
{
find_final_overrider_data ffod;
- /* Getting this right is a little tricky. This is legal:
+ /* Getting this right is a little tricky. This is valid:
struct S { virtual void f (); };
struct T { virtual void f (); };
@@ -2392,41 +2323,42 @@ find_final_overrider (t, binfo, fn)
different overriders along any two, then there is a problem. */
ffod.fn = fn;
ffod.declaring_base = binfo;
- ffod.most_derived_type = t;
- ffod.overriding_fn = NULL_TREE;
- ffod.overriding_base = NULL_TREE;
+ ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE;
- dfs_walk (TYPE_BINFO (t),
+ dfs_walk (derived,
dfs_find_final_overrider,
NULL,
&ffod);
/* If there was no winner, issue an error message. */
- if (!ffod.overriding_fn)
+ if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
{
- error ("no unique final overrider for `%D' in `%T'", fn, t);
+ error ("no unique final overrider for `%D' in `%T'", fn,
+ BINFO_TYPE (derived));
return error_mark_node;
}
- return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
+ return ffod.candidates;
}
-/* Returns the function from the BINFO_VIRTUALS entry in T which matches
- the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
- the function that the slot in T's primary vtable points to. */
+/* Return the index of the vcall offset for FN when TYPE is used as a
+ virtual base. */
-static tree get_matching_virtual PARAMS ((tree, tree));
static tree
-get_matching_virtual (t, fn)
- tree t, fn;
+get_vcall_index (tree fn, tree type)
{
- tree f;
+ tree v;
- for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
- if (same_signature_p (BV_FN (f), fn))
- return BV_FN (f);
- return NULL_TREE;
+ for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
+ if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
+ || same_signature_p (fn, TREE_PURPOSE (v)))
+ break;
+
+ /* There should always be an appropriate index. */
+ my_friendly_assert (v, 20021103);
+
+ return TREE_VALUE (v);
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
@@ -2462,7 +2394,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
first_defn = b;
/* Find the final overrider. */
- overrider = find_final_overrider (t, b, fn);
+ overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
if (overrider == error_mark_node)
return;
@@ -2494,7 +2426,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
/* Compute the constant adjustment to the `this' pointer. The
`this' pointer, when this function is called, will point at BINFO
(or one of its primary bases, which are at the same offset). */
-
if (virtual_base)
/* The `this' pointer needs to be adjusted from the declaration to
the nearest virtual base. */
@@ -2507,36 +2438,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
will be zero, as it will be a primary base. */
delta = size_zero_node;
else
- {
- /* The `this' pointer needs to be adjusted from pointing to
- BINFO to pointing at the base where the final overrider
- appears. */
- delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
- BINFO_OFFSET (binfo));
-
- if (! integer_zerop (delta))
- {
- /* We'll need a thunk. But if we have a (perhaps formerly)
- primary virtual base, we have a vcall slot for this function,
- so we can use it rather than create a non-virtual thunk. */
-
- b = get_primary_binfo (first_defn);
- for (; b; b = get_primary_binfo (b))
- {
- tree f = get_matching_virtual (BINFO_TYPE (b), fn);
- if (!f)
- /* b doesn't have this function; no suitable vbase. */
- break;
- if (TREE_VIA_VIRTUAL (b))
- {
- /* Found one; we can treat ourselves as a virtual base. */
- virtual_base = binfo;
- delta = size_zero_node;
- break;
- }
- }
- }
- }
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+ BINFO_OFFSET (binfo));
modify_vtable_entry (t,
binfo,
@@ -2545,7 +2451,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
virtuals);
if (virtual_base)
- BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+ BV_VCALL_INDEX (*virtuals)
+ = get_vcall_index (TREE_PURPOSE (overrider),
+ BINFO_TYPE (virtual_base));
}
/* Called from modify_all_vtables via dfs_walk. */
@@ -2600,9 +2508,8 @@ dfs_modify_vtables (binfo, data)
should therefore be appended to the end of the vtable for T. */
static tree
-modify_all_vtables (t, vfuns_p, virtuals)
+modify_all_vtables (t, virtuals)
tree t;
- int *vfuns_p;
tree virtuals;
{
tree binfo = TYPE_BINFO (t);
@@ -2626,12 +2533,6 @@ modify_all_vtables (t, vfuns_p, virtuals)
if (!value_member (fn, BINFO_VIRTUALS (binfo))
|| DECL_VINDEX (fn) == error_mark_node)
{
- /* Set the vtable index. */
- set_vindex (fn, vfuns_p);
- /* We don't need to convert to a base class when calling
- this function. */
- DECL_VIRTUAL_CONTEXT (fn) = t;
-
/* We don't need to adjust the `this' pointer when
calling this function. */
BV_DELTA (*fnsp) = integer_zero_node;
@@ -2644,26 +2545,8 @@ modify_all_vtables (t, vfuns_p, virtuals)
/* We've already got an entry for this function. Skip it. */
*fnsp = TREE_CHAIN (*fnsp);
}
-
- return virtuals;
-}
-
-/* Here, we already know that they match in every respect.
- All we have to check is where they had their declarations.
- Return non-zero iff FNDECL1 is declared in a class which has a
- proper base class containing FNDECL2. We don't care about
- ambiguity or accessibility. */
-
-static int
-strictly_overrides (fndecl1, fndecl2)
- tree fndecl1, fndecl2;
-{
- base_kind kind;
-
- return (lookup_base (DECL_CONTEXT (fndecl1), DECL_CONTEXT (fndecl2),
- ba_ignore | ba_quiet, &kind)
- && kind != bk_same_type);
+ return virtuals;
}
/* Get the base virtual function declarations in T that have the
@@ -2678,11 +2561,19 @@ get_basefndecls (name, t)
int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- for (methods = TYPE_METHODS (t); methods; methods = TREE_CHAIN (methods))
- if (TREE_CODE (methods) == FUNCTION_DECL
- && DECL_VINDEX (methods) != NULL_TREE
- && DECL_NAME (methods) == name)
- base_fndecls = tree_cons (NULL_TREE, methods, base_fndecls);
+ /* Find virtual functions in T with the indicated NAME. */
+ i = lookup_fnfields_1 (t, name);
+ if (i != -1)
+ for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
+ methods;
+ methods = OVL_NEXT (methods))
+ {
+ tree method = OVL_CURRENT (methods);
+
+ if (TREE_CODE (method) == FUNCTION_DECL
+ && DECL_VINDEX (method))
+ base_fndecls = tree_cons (NULL_TREE, method, base_fndecls);
+ }
if (base_fndecls)
return base_fndecls;
@@ -2762,11 +2653,11 @@ warn_hidden (t)
base_fndecls);
}
- /* If there are no functions to hide, continue. */
+ /* If there are no functions to hide, continue. */
if (!base_fndecls)
continue;
- /* Remove any overridden functions. */
+ /* Remove any overridden functions. */
for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
{
fndecl = OVL_CURRENT (fns);
@@ -2857,6 +2748,29 @@ finish_struct_anon (t)
}
}
+/* Add T to CLASSTYPE_DECL_LIST of current_class_type which
+ will be used later during class template instantiation.
+ When FRIEND_P is zero, T can be a static member data (VAR_DECL),
+ a non-static member data (FIELD_DECL), a member function
+ (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE),
+ a typedef (TYPE_DECL) or a member class template (TEMPLATE_DECL)
+ When FRIEND_P is nonzero, T is either a friend class
+ (RECORD_TYPE, TEMPLATE_DECL) or a friend function
+ (FUNCTION_DECL, TEMPLATE_DECL). */
+
+void
+maybe_add_class_template_decl_list (type, t, friend_p)
+ tree type;
+ tree t;
+ int friend_p;
+{
+ /* Save some memory by not creating TREE_LIST if TYPE is not template. */
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ CLASSTYPE_DECL_LIST (type)
+ = tree_cons (friend_p ? NULL_TREE : type,
+ t, CLASSTYPE_DECL_LIST (type));
+}
+
/* 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
@@ -2866,7 +2780,7 @@ finish_struct_anon (t)
reference, respectively. If a virtual destructor is created, its
DECL is returned; otherwise the return value is NULL_TREE. */
-static tree
+static void
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
cant_have_const_assignment)
@@ -2937,13 +2851,27 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
/* 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, *f, /*error_p=*/0);
- *f = TYPE_METHODS (t);
- TYPE_METHODS (t) = implicit_fns;
+ {
+ add_method (t, *f, /*error_p=*/0);
+ maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
+ }
+ if (abi_version_at_least (2))
+ /* G++ 3.2 put the implicit destructor at the *beginning* of the
+ list, which cause the destructor to be emitted in an incorrect
+ location in the vtable. */
+ TYPE_METHODS (t) = chainon (TYPE_METHODS (t), implicit_fns);
+ else
+ {
+ if (warn_abi && virtual_dtor)
+ warning ("vtable layout for class `%T' may not be ABI-compliant "
+ "and may change in a future version of GCC due to implicit "
+ "virtual destructor",
+ t);
+ *f = TYPE_METHODS (t);
+ TYPE_METHODS (t) = implicit_fns;
+ }
--adding_implicit_members;
-
- return virtual_dtor;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
@@ -3165,15 +3093,6 @@ check_field_decl (field, t, cant_have_const_ctor,
cp_error_at ("multiple fields in union `%T' initialized");
*any_default_members = 1;
}
-
- /* Non-bit-fields are aligned for their type, except packed fields
- which require only BITS_PER_UNIT alignment. */
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
- (DECL_PACKED (field)
- ? BITS_PER_UNIT
- : TYPE_ALIGN (TREE_TYPE (field))));
- if (! DECL_PACKED (field))
- DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (TREE_TYPE (field));
}
/* Check the data members (both static and non-static), class-scoped
@@ -3206,15 +3125,10 @@ check_field_decl (field, t, cant_have_const_ctor,
fields can be added by adding to this chain. */
static void
-check_field_decls (t, access_decls, empty_p,
- cant_have_default_ctor_p, cant_have_const_ctor_p,
- no_const_asn_ref_p)
- tree t;
- tree *access_decls;
- int *empty_p;
- int *cant_have_default_ctor_p;
- int *cant_have_const_ctor_p;
- int *no_const_asn_ref_p;
+check_field_decls (tree t, tree *access_decls,
+ int *cant_have_default_ctor_p,
+ int *cant_have_const_ctor_p,
+ int *no_const_asn_ref_p)
{
tree *field;
tree *next;
@@ -3252,12 +3166,12 @@ check_field_decls (t, access_decls, empty_p,
tree element_type;
/* The class is non-empty. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
- element_type = strip_array_types (type);
+ element_type = strip_array_types (type);
if (CLASS_TYPE_P (element_type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
@@ -3351,7 +3265,8 @@ check_field_decls (t, access_decls, empty_p,
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
- if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+ if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
+ && extra_warnings)
cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
}
@@ -3385,7 +3300,8 @@ check_field_decls (t, access_decls, empty_p,
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
- if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+ if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
+ && extra_warnings)
cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
}
/* A field that is pseudo-const makes the structure likewise. */
@@ -3469,7 +3385,7 @@ record_subobject_offset (type, offset, offsets)
return 0;
}
-/* Returns non-zero if TYPE is an empty class type and there is
+/* Returns nonzero if TYPE is an empty class type and there is
already an entry in OFFSETS for the same TYPE as the same OFFSET. */
static int
@@ -3498,13 +3414,13 @@ check_subobject_offset (type, offset, offsets)
/* Walk through all the subobjects of TYPE (located at OFFSET). Call
F for every subobject, passing it the type, offset, and table of
- OFFSETS. If VBASES_P is non-zero, then even virtual non-primary
- bases should be traversed; otherwise, they are ignored.
+ OFFSETS. If VBASES_P is one, then virtual non-primary bases should
+ be traversed.
If MAX_OFFSET is non-NULL, then subobjects with an offset greater
than MAX_OFFSET will not be walked.
- If F returns a non-zero value, the traversal ceases, and that value
+ If F returns a nonzero value, the traversal ceases, and that value
is returned. Otherwise, returns zero. */
static int
@@ -3517,15 +3433,24 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
int vbases_p;
{
int r = 0;
+ tree type_binfo = NULL_TREE;
/* If this OFFSET is bigger than the MAX_OFFSET, then we should
stop. */
if (max_offset && INT_CST_LT (max_offset, offset))
return 0;
+ if (!TYPE_P (type))
+ {
+ if (abi_version_at_least (2))
+ type_binfo = type;
+ type = BINFO_TYPE (type);
+ }
+
if (CLASS_TYPE_P (type))
{
tree field;
+ tree binfo;
int i;
/* Avoid recursing into objects that are not interesting. */
@@ -3538,36 +3463,119 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return r;
/* Iterate through the direct base classes of TYPE. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ if (!type_binfo)
+ type_binfo = TYPE_BINFO (type);
+ for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
{
- tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ tree binfo_offset;
+
+ binfo = BINFO_BASETYPE (type_binfo, i);
+
+ if (abi_version_at_least (2)
+ && TREE_VIA_VIRTUAL (binfo))
+ continue;
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
- r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ if (!abi_version_at_least (2))
+ binfo_offset = size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo));
+ else
+ {
+ tree orig_binfo;
+ /* We cannot rely on BINFO_OFFSET being set for the base
+ class yet, but the offsets for direct non-virtual
+ bases can be calculated by going back to the TYPE. */
+ orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ binfo_offset = size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (orig_binfo));
+ }
+
+ r = walk_subobject_offsets (binfo,
f,
- size_binop (PLUS_EXPR,
- offset,
- BINFO_OFFSET (binfo)),
+ binfo_offset,
offsets,
max_offset,
- vbases_p);
+ (abi_version_at_least (2)
+ ? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
}
+ if (abi_version_at_least (2))
+ {
+ tree vbase;
+
+ /* Iterate through the virtual base classes of TYPE. In G++
+ 3.2, we included virtual bases in the direct base class
+ loop above, which results in incorrect results; the
+ correct offsets for virtual bases are only known when
+ working with the most derived type. */
+ if (vbases_p)
+ for (vbase = CLASSTYPE_VBASECLASSES (type);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ binfo = TREE_VALUE (vbase);
+ r = walk_subobject_offsets (binfo,
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ max_offset,
+ /*vbases_p=*/0);
+ if (r)
+ return r;
+ }
+ else
+ {
+ /* We still have to walk the primary base, if it is
+ virtual. (If it is non-virtual, then it was walked
+ above.) */
+ vbase = get_primary_binfo (type_binfo);
+ if (vbase && TREE_VIA_VIRTUAL (vbase))
+ {
+ tree derived = type_binfo;
+ while (BINFO_INHERITANCE_CHAIN (derived))
+ derived = BINFO_INHERITANCE_CHAIN (derived);
+ derived = TREE_TYPE (derived);
+ vbase = binfo_for_vbase (TREE_TYPE (vbase), derived);
+
+ if (BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
+ {
+ r = (walk_subobject_offsets
+ (vbase, f, offset,
+ offsets, max_offset, /*vbases_p=*/0));
+ if (r)
+ return r;
+ }
+ }
+ }
+ }
+
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL)
+ if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
{
+ tree field_offset;
+
+ if (abi_version_at_least (2))
+ field_offset = byte_position (field);
+ else
+ /* In G++ 3.2, DECL_FIELD_OFFSET was used. */
+ field_offset = DECL_FIELD_OFFSET (field);
+
r = walk_subobject_offsets (TREE_TYPE (field),
f,
size_binop (PLUS_EXPR,
offset,
- DECL_FIELD_OFFSET (field)),
+ field_offset),
offsets,
max_offset,
/*vbases_p=*/1);
@@ -3587,8 +3595,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return 0;
/* Step through each of the elements in the array. */
- for (index = size_zero_node;
- INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+ for (index = size_zero_node;
+ /* G++ 3.2 had an off-by-one error here. */
+ (abi_version_at_least (2)
+ ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
+ : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
@@ -3613,7 +3624,7 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
}
/* Record all of the empty subobjects of TYPE (located at OFFSET) in
- OFFSETS. If VBASES_P is non-zero, virtual bases of TYPE are
+ OFFSETS. If VBASES_P is nonzero, virtual bases of TYPE are
examined. */
static void
@@ -3627,8 +3638,8 @@ record_subobject_offsets (type, offset, offsets, vbases_p)
offsets, /*max_offset=*/NULL_TREE, vbases_p);
}
-/* Returns non-zero if any of the empty subobjects of TYPE (located at
- OFFSET) conflict with entries in OFFSETS. If VBASES_P is non-zero,
+/* Returns nonzero if any of the empty subobjects of TYPE (located at
+ OFFSET) conflict with entries in OFFSETS. If VBASES_P is nonzero,
virtual bases of TYPE are examined. */
static int
@@ -3656,22 +3667,34 @@ layout_conflict_p (type, offset, offsets, vbases_p)
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, OFFSETS maps offsets to
- types already located at those offsets. T is the most derived
- type. This function determines the position of the DECL. */
+ types already located at those offsets. This function determines
+ the position of the DECL. */
static void
-layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
- record_layout_info rli;
- tree decl;
- tree binfo;
- splay_tree offsets;
- tree t;
+layout_nonempty_base_or_field (record_layout_info rli,
+ tree decl,
+ tree binfo,
+ splay_tree offsets)
{
+ tree t = rli->t;
tree offset = NULL_TREE;
- tree type = TREE_TYPE (decl);
- /* If we are laying out a base class, rather than a field, then
- DECL_ARTIFICIAL will be set on the FIELD_DECL. */
- int field_p = !DECL_ARTIFICIAL (decl);
+ bool field_p;
+ tree type;
+
+ if (binfo)
+ {
+ /* For the purposes of determining layout conflicts, we want to
+ use the class type of BINFO; TREE_TYPE (DECL) will be the
+ CLASSTYPE_AS_BASE version, which does not contain entries for
+ zero-sized bases. */
+ type = TREE_TYPE (binfo);
+ field_p = false;
+ }
+ else
+ {
+ type = TREE_TYPE (decl);
+ field_p = true;
+ }
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
@@ -3696,13 +3719,15 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
offset zero -- its S component would be at the same address
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
- empty class, have non-zero size, any overlap can happen only
+ empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
- if (layout_conflict_p (TREE_TYPE (decl),
- offset,
- offsets,
- field_p))
+ /* G++ 3.2 did not check for overlaps when placing a non-empty
+ virtual base. */
+ if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
+ break;
+ if (layout_conflict_p (field_p ? type : binfo, offset,
+ offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
@@ -3725,15 +3750,32 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ /* Indirect virtual bases may have a nonzero BINFO_OFFSET at
+ this point because their BINFO_OFFSET is copied from another
+ hierarchy. Therefore, we may not need to add the entire
+ OFFSET. */
propagate_binfo_offsets (binfo,
- convert (ssizetype, offset), t);
+ size_diffop (convert (ssizetype, offset),
+ convert (ssizetype,
+ BINFO_OFFSET (binfo))),
+ t);
+}
+
+/* Returns true if TYPE is empty and OFFSET is nonzero. */
+
+static int
+empty_base_at_nonzero_offset_p (tree type,
+ tree offset,
+ splay_tree offsets ATTRIBUTE_UNUSED)
+{
+ return is_empty_class (type) && !integer_zerop (offset);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a
class of the type indicated by BINFO; OFFSETS gives the offsets of
the empty bases allocated so far. T is the most derived
- type. Return non-zero iff we added it at the end. */
+ type. Return nonzero iff we added it at the end. */
static bool
layout_empty_base (binfo, eoc, offsets, t)
@@ -3745,14 +3787,21 @@ layout_empty_base (binfo, eoc, offsets, t)
tree alignment;
tree basetype = BINFO_TYPE (binfo);
bool atend = false;
-
+
/* This routine should only be used for empty classes. */
my_friendly_assert (is_empty_class (basetype), 20000321);
alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
+
+ if (abi_version_at_least (2))
+ BINFO_OFFSET (binfo) = size_zero_node;
+ if (warn_abi && !integer_zerop (BINFO_OFFSET (binfo)))
+ warning ("offset of empty base `%T' may not be ABI-compliant and may"
+ "change in a future version of GCC",
+ BINFO_TYPE (binfo));
/* This is an empty base class. We first try to put it at offset
zero. */
- if (layout_conflict_p (BINFO_TYPE (binfo),
+ if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3763,7 +3812,7 @@ layout_empty_base (binfo, eoc, offsets, t)
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1)
{
- if (!layout_conflict_p (BINFO_TYPE (binfo),
+ if (!layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3777,103 +3826,141 @@ layout_empty_base (binfo, eoc, offsets, t)
return atend;
}
-/* Build a FIELD_DECL for the base given by BINFO in the class
- indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
- *BASE_ALIGN is a running maximum of the alignments of any base
- class. OFFSETS gives the location of empty base subobjects. T is
- the most derived type. Return non-zero if the new object cannot be
- nearly-empty. */
+/* Layout the the base given by BINFO in the class indicated by RLI.
+ *BASE_ALIGN is a running maximum of the alignments of
+ any base class. OFFSETS gives the location of empty base
+ subobjects. T is the most derived type. Return nonzero if the new
+ object cannot be nearly-empty. A new FIELD_DECL is inserted at
+ *NEXT_FIELD, unless BINFO is for an empty base class.
-static bool
-build_base_field (rli, binfo, empty_p, offsets, t)
- record_layout_info rli;
- tree binfo;
- int *empty_p;
- splay_tree offsets;
- tree t;
+ Returns the location at which the next field should be inserted. */
+
+static tree *
+build_base_field (record_layout_info rli, tree binfo,
+ splay_tree offsets, tree *next_field)
{
+ tree t = rli->t;
tree basetype = BINFO_TYPE (binfo);
- tree decl;
- bool atend = false;
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
- return atend;
+ return next_field;
- decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
- DECL_ARTIFICIAL (decl) = 1;
- DECL_FIELD_CONTEXT (decl) = rli->t;
- DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
- DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
- DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
- DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
- /* Tell the backend not to round up to TYPE_ALIGN. */
- DECL_PACKED (decl) = 1;
-
- if (!integer_zerop (DECL_SIZE (decl)))
+ /* Place the base class. */
+ if (!is_empty_class (basetype))
{
+ tree decl;
+
/* The containing class is non-empty because it has a non-empty
base class. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
+
+ /* Create the FIELD_DECL. */
+ decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_FIELD_CONTEXT (decl) = t;
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+ DECL_IGNORED_P (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
- layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+ /* Add the new FIELD_DECL to the list of fields for T. */
+ TREE_CHAIN (decl) = *next_field;
+ *next_field = decl;
+ next_field = &TREE_CHAIN (decl);
}
else
{
- unsigned HOST_WIDE_INT eoc;
+ tree eoc;
+ bool atend;
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
- eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
- eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
- atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
+ eoc = round_up (rli_size_unit_so_far (rli),
+ CLASSTYPE_ALIGN_UNIT (basetype));
+ atend = layout_empty_base (binfo, eoc, offsets, t);
+ /* A nearly-empty class "has no proper base class that is empty,
+ not morally virtual, and at an offset other than zero." */
+ if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
+ {
+ if (atend)
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ /* The check above (used in G++ 3.2) is insufficient because
+ an empty class placed at offset zero might itself have an
+ empty base at a nonzero offset. */
+ else if (walk_subobject_offsets (basetype,
+ empty_base_at_nonzero_offset_p,
+ size_zero_node,
+ /*offsets=*/NULL,
+ /*max_offset=*/NULL_TREE,
+ /*vbases_p=*/true))
+ {
+ if (abi_version_at_least (2))
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ else if (warn_abi)
+ warning ("class `%T' will be considered nearly empty in a "
+ "future version of GCC", t);
+ }
+ }
+
+ /* We do not create a FIELD_DECL for empty base classes because
+ it might overlap some other field. We want to be able to
+ create CONSTRUCTORs for the class by iterating over the
+ FIELD_DECLs, and the back end does not handle overlapping
+ FIELD_DECLs. */
+
+ /* An empty virtual base causes a class to be non-empty
+ -- but in that case we do not need to clear CLASSTYPE_EMPTY_P
+ here because that was already done when the virtual table
+ pointer was created. */
}
/* Record the offsets of BINFO and its base subobjects. */
- record_subobject_offsets (BINFO_TYPE (binfo),
+ record_subobject_offsets (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
- return atend;
+
+ return next_field;
}
/* Layout all of the non-virtual base classes. Record empty
- subobjects in OFFSETS. T is the most derived type. Return
- non-zero if the type cannot be nearly empty. */
+ subobjects in OFFSETS. T is the most derived type. Return nonzero
+ if the type cannot be nearly empty. The fields created
+ corresponding to the base classes will be inserted at
+ *NEXT_FIELD. */
-static bool
-build_base_fields (rli, empty_p, offsets, t)
- record_layout_info rli;
- int *empty_p;
- splay_tree offsets;
- tree t;
+static void
+build_base_fields (record_layout_info rli,
+ splay_tree offsets, tree *next_field)
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
- tree rec = rli->t;
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
+ tree t = rli->t;
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- bool atend = 0;
/* The primary base class is always allocated first. */
- if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
- build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
- empty_p, offsets, t);
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
+ offsets, next_field);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
- if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
+ if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
continue;
/* A primary virtual base class is allocated just like any other
@@ -3883,9 +3970,9 @@ build_base_fields (rli, empty_p, offsets, t)
&& !BINFO_PRIMARY_P (base_binfo))
continue;
- atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
+ next_field = build_base_field (rli, base_binfo,
+ offsets, next_field);
}
- return atend;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4013,7 +4100,7 @@ build_clone (fn, name)
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
{
DECL_CONTEXT (parms) = clone;
- copy_lang_decl (parms);
+ cxx_dup_lang_specific_decl (parms);
}
}
@@ -4043,7 +4130,7 @@ build_clone (fn, name)
}
/* Produce declarations for all appropriate clones of FN. If
- UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+ UPDATE_METHOD_VEC_P is nonzero, the clones are added to the
CLASTYPE_METHOD_VEC as well. */
void
@@ -4105,7 +4192,7 @@ clone_function_decl (fn, update_method_vec_p)
declared. An out-of-class definition can specify additional default
arguments. As it is the clones that are involved in overload
resolution, we must propagate the information from the DECL to its
- clones. */
+ clones. */
void
adjust_clone_args (decl)
@@ -4122,7 +4209,7 @@ adjust_clone_args (decl)
clone_parms = orig_clone_parms;
- /* Skip the 'this' parameter. */
+ /* Skip the 'this' parameter. */
orig_clone_parms = TREE_CHAIN (orig_clone_parms);
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
@@ -4145,7 +4232,7 @@ adjust_clone_args (decl)
if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
{
/* A default parameter has been added. Adjust the
- clone's parameters. */
+ clone's parameters. */
tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
tree type;
@@ -4244,7 +4331,7 @@ type_requires_array_cookie (type)
if (!fns || fns == error_mark_node)
return false;
/* Loop through all of the functions. */
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn;
tree second_parm;
@@ -4274,9 +4361,7 @@ type_requires_array_cookie (type)
level: i.e., independently of the ABI in use. */
static void
-check_bases_and_members (t, empty_p)
- tree t;
- int *empty_p;
+check_bases_and_members (tree t)
{
/* Nonzero if we are not allowed to generate a default constructor
for this case. */
@@ -4295,17 +4380,12 @@ check_bases_and_members (t, empty_p)
cant_have_const_ctor = 0;
no_const_asn_ref = 0;
- /* Assume that the class is nearly empty; we'll clear this flag if
- it turns out not to be nearly empty. */
- CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
- CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
-
- /* Check all the base-classes. */
+ /* Check all the base-classes. */
check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
&no_const_asn_ref);
/* Check all the data member declarations. */
- check_field_decls (t, &access_decls, empty_p,
+ check_field_decls (t, &access_decls,
&cant_have_default_ctor,
&cant_have_const_ctor,
&no_const_asn_ref);
@@ -4356,7 +4436,7 @@ check_bases_and_members (t, empty_p)
/* Figure out whether or not we will need a cookie when dynamically
allocating an array of this type. */
- TYPE_LANG_SPECIFIC (t)->vec_new_uses_cookie
+ TYPE_LANG_SPECIFIC (t)->u.c.vec_new_uses_cookie
= type_requires_array_cookie (t);
}
@@ -4368,10 +4448,8 @@ check_bases_and_members (t, empty_p)
on VIRTUALS_P. */
static tree
-create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p)
+create_vtable_ptr (t, virtuals_p)
tree t;
- int *empty_p;
- int *vfuns_p;
tree *virtuals_p;
{
tree fn;
@@ -4429,7 +4507,7 @@ create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p)
TYPE_VFIELD (t) = field;
/* This class is non-empty. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
if (CLASSTYPE_N_BASECLASSES (t))
/* If there were any baseclasses, they can't possibly be at
@@ -4578,33 +4656,41 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
return NULL_TREE;
}
-/* Set BINFO_OFFSET for all of the virtual bases for T. Update
+/* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
-layout_virtual_bases (t, offsets)
- tree t;
- splay_tree offsets;
+layout_virtual_bases (record_layout_info rli, splay_tree offsets)
{
- tree vbases, dsize;
- unsigned HOST_WIDE_INT eoc;
+ tree vbases;
+ tree t = rli->t;
bool first_vbase = true;
+ tree *next_field;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
+ if (!abi_version_at_least(2))
+ {
+ /* In G++ 3.2, we incorrectly rounded the size before laying out
+ the virtual bases. */
+ finish_record_layout (rli, /*free_p=*/false);
#ifdef STRUCTURE_SIZE_BOUNDARY
- /* Packed structures don't need to have minimum size. */
- if (! TYPE_PACKED (t))
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (t))
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
+ rli->offset = TYPE_SIZE_UNIT (t);
+ rli->bitpos = bitsize_zero_node;
+ rli->record_align = TYPE_ALIGN (t);
+ }
- /* DSIZE is the size of the class without the virtual bases. */
- dsize = TYPE_SIZE (t);
-
- /* Make every class have alignment of at least one. */
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
+ /* Find the last field. The artificial fields created for virtual
+ bases will go after the last extant field to date. */
+ next_field = &TYPE_FIELDS (t);
+ while (*next_field)
+ next_field = &TREE_CHAIN (*next_field);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
@@ -4622,45 +4708,12 @@ layout_virtual_bases (t, offsets)
if (!BINFO_PRIMARY_P (vbase))
{
+ tree basetype = TREE_TYPE (vbase);
+
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
- tree basetype, usize;
- unsigned int desired_align;
-
- basetype = BINFO_TYPE (vbase);
-
- desired_align = CLASSTYPE_ALIGN (basetype);
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
- /* Add padding so that we can put the virtual base class at an
- appropriately aligned offset. */
- dsize = round_up (dsize, desired_align);
- usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
-
- /* We try to squish empty virtual bases in just like
- ordinary empty bases. */
- if (is_empty_class (basetype))
- layout_empty_base (vbase,
- convert (sizetype, usize),
- offsets, t);
- else
- {
- tree offset;
-
- offset = convert (ssizetype, usize);
- offset = size_diffop (offset,
- convert (ssizetype,
- BINFO_OFFSET (vbase)));
-
- /* And compute the offset of the virtual base. */
- propagate_binfo_offsets (vbase, offset, t);
- /* Every virtual baseclass takes a least a UNIT, so that
- we can take it's address and get something different
- for each base. */
- dsize = size_binop (PLUS_EXPR, dsize,
- size_binop (MAX_EXPR, bitsize_unit_node,
- CLASSTYPE_SIZE (basetype)));
- }
+ next_field = build_base_field (rli, vbase,
+ offsets, next_field);
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
@@ -4671,20 +4724,15 @@ layout_virtual_bases (t, offsets)
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
- && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
- round_up (CLASSTYPE_SIZE (t),
- desired_align),
- bitsize_unit_node),
- BINFO_OFFSET (vbase)))
+ && (tree_int_cst_lt
+ (size_binop (CEIL_DIV_EXPR,
+ round_up (CLASSTYPE_SIZE (t),
+ CLASSTYPE_ALIGN (basetype)),
+ bitsize_unit_node),
+ BINFO_OFFSET (vbase))))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
- /* Keep track of the offsets assigned to this virtual base. */
- record_subobject_offsets (BINFO_TYPE (vbase),
- BINFO_OFFSET (vbase),
- offsets,
- /*vbases_p=*/0);
-
first_vbase = false;
}
}
@@ -4695,80 +4743,70 @@ layout_virtual_bases (t, offsets)
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
+}
- /* If we had empty base classes that protruded beyond the end of the
- class, we didn't update DSIZE above; we were hoping to overlay
- multiple such bases at the same location. */
- eoc = end_of_class (t, /*include_virtuals_p=*/1);
- dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
+/* Returns the offset of the byte just past the end of the base class
+ BINFO. */
- /* Now, make sure that the total size of the type is a multiple of
- its alignment. */
- dsize = round_up (dsize, TYPE_ALIGN (t));
- TYPE_SIZE (t) = dsize;
- TYPE_SIZE_UNIT (t) = convert (sizetype,
- size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
- bitsize_unit_node));
+static tree
+end_of_base (tree binfo)
+{
+ tree size;
- /* Check for ambiguous virtual bases. */
- if (extra_warnings)
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
-
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
- warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
+ if (is_empty_class (BINFO_TYPE (binfo)))
+ /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
+ allocate some space for it. It cannot have virtual bases, so
+ TYPE_SIZE_UNIT is fine. */
+ size = TYPE_SIZE_UNIT (BINFO_TYPE (binfo));
+ else
+ size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (binfo));
+
+ return size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), size);
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
-static unsigned HOST_WIDE_INT
+static tree
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
- unsigned HOST_WIDE_INT result = 0;
+ tree result = size_zero_node;
+ tree binfo;
+ tree offset;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree base_binfo;
- tree offset;
- tree size;
- unsigned HOST_WIDE_INT end_of_base;
-
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
if (!include_virtuals_p
- && TREE_VIA_VIRTUAL (base_binfo)
- && !BINFO_PRIMARY_P (base_binfo))
+ && TREE_VIA_VIRTUAL (binfo)
+ && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t))
continue;
- if (is_empty_class (BINFO_TYPE (base_binfo)))
- /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
- allocate some space for it. It cannot have virtual bases,
- so TYPE_SIZE_UNIT is fine. */
- size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
- else
- size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
- offset = size_binop (PLUS_EXPR,
- BINFO_OFFSET (base_binfo),
- size);
- end_of_base = tree_low_cst (offset, /*pos=*/1);
- if (end_of_base > result)
- result = end_of_base;
+ offset = end_of_base (binfo);
+ if (INT_CST_LT_UNSIGNED (result, offset))
+ result = offset;
}
+ /* G++ 3.2 did not check indirect virtual bases. */
+ if (abi_version_at_least (2) && include_virtuals_p)
+ for (binfo = CLASSTYPE_VBASECLASSES (t);
+ binfo;
+ binfo = TREE_CHAIN (binfo))
+ {
+ offset = end_of_base (TREE_VALUE (binfo));
+ if (INT_CST_LT_UNSIGNED (result, offset))
+ result = offset;
+ }
+
return result;
}
-/* Warn about direct bases of T that are inaccessible because they are
+/* Warn about bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
@@ -4779,19 +4817,35 @@ end_of_class (t, include_virtuals_p)
subobjects of U. */
static void
-warn_about_ambiguous_direct_bases (t)
+warn_about_ambiguous_bases (t)
tree t;
{
int i;
+ tree vbases;
+ tree basetype;
+ /* Check direct bases. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
+ basetype, t);
}
+
+ /* Check for ambiguous virtual bases. */
+ if (extra_warnings)
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ basetype = BINFO_TYPE (TREE_VALUE (vbases));
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
+ }
}
/* Compare two INTEGER_CSTs K1 and K2. */
@@ -4804,27 +4858,59 @@ splay_tree_compare_integer_csts (k1, k2)
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
+/* Increase the size indicated in RLI to account for empty classes
+ that are "off the end" of the class. */
+
+static void
+include_empty_classes (record_layout_info rli)
+{
+ tree eoc;
+ tree rli_size;
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ eoc = end_of_class (rli->t,
+ CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+ rli_size = rli_size_unit_so_far (rli);
+ if (TREE_CODE (rli_size) == INTEGER_CST
+ && INT_CST_LT_UNSIGNED (rli_size, eoc))
+ {
+ rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+ rli->bitpos
+ = size_binop (PLUS_EXPR,
+ rli->bitpos,
+ size_binop (MULT_EXPR,
+ convert (bitsizetype,
+ size_binop (MINUS_EXPR,
+ eoc, rli_size)),
+ bitsize_int (BITS_PER_UNIT)));
+ normalize_rli (rli);
+ }
+}
+
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
- pointer. Accumulate declared virtual functions on VIRTUALS_P. */
+ pointer. Accumulate declared virtual functions on VIRTUALS_P. */
static void
-layout_class_type (t, empty_p, vfuns_p, virtuals_p)
- tree t;
- int *empty_p;
- int *vfuns_p;
- tree *virtuals_p;
+layout_class_type (tree t, tree *virtuals_p)
{
tree non_static_data_members;
tree field;
tree vptr;
record_layout_info rli;
- unsigned HOST_WIDE_INT eoc;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
+ /* The location at which the next field should be inserted. */
+ tree *next_field;
+ /* T, as a base class. */
+ tree base_t;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
@@ -4834,23 +4920,26 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
- determine_primary_base (t, vfuns_p);
+ determine_primary_base (t);
/* Create a pointer to our virtual function table. */
- vptr = create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p);
+ vptr = create_vtable_ptr (t, virtuals_p);
/* The vptr is always the first thing in the class. */
if (vptr)
{
- TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+ TREE_CHAIN (vptr) = TYPE_FIELDS (t);
+ TYPE_FIELDS (t) = vptr;
+ next_field = &TREE_CHAIN (vptr);
place_field (rli, vptr);
}
+ else
+ next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
- if (build_base_fields (rli, empty_p, empty_base_offsets, t))
- CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ build_base_fields (rli, empty_base_offsets, next_field);
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
@@ -4902,17 +4991,44 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
field. We have to back up by one to find the largest
type that fits. */
integer_type = integer_types[itk - 1];
- padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
- TYPE_SIZE (integer_type));
+
+ if (abi_version_at_least (2) && TREE_CODE (t) == UNION_TYPE)
+ /* In a union, the padding field must have the full width
+ of the bit-field; all fields start at offset zero. */
+ padding = DECL_SIZE (field);
+ else
+ {
+ if (warn_abi && TREE_CODE (t) == UNION_TYPE)
+ warning ("size assigned to `%T' may not be "
+ "ABI-compliant and may change in a future "
+ "version of GCC",
+ t);
+ padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+ TYPE_SIZE (integer_type));
+ }
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ /* Now that layout has been performed, set the size of the
+ field to the size of its declared type; the rest of the
+ field is effectively invisible. */
+ DECL_SIZE (field) = TYPE_SIZE (type);
}
else
- padding = NULL_TREE;
+ {
+ padding = NULL_TREE;
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ }
- layout_nonempty_base_or_field (rli, field, NULL_TREE,
- empty_base_offsets, t);
+ /* Remember the location of any empty classes in FIELD. */
+ if (abi_version_at_least (2))
+ record_subobject_offsets (TREE_TYPE (field),
+ byte_position(field),
+ empty_base_offsets,
+ /*vbases_p=*/1);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
@@ -4926,6 +5042,17 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC",
field);
+ /* G++ used to use DECL_FIELD_OFFSET as if it were the byte
+ offset of the field. */
+ if (warn_abi
+ && !tree_int_cst_equal (DECL_FIELD_OFFSET (field),
+ byte_position (field))
+ && contains_empty_class_p (TREE_TYPE (field)))
+ cp_warning_at ("`%D' contains empty classes which may cause base "
+ "classes to be placed at different locations in a "
+ "future version of GCC",
+ field);
+
/* If we needed additional padding after this field, add it
now. */
if (padding)
@@ -4941,73 +5068,102 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
- empty_base_offsets, t);
+ empty_base_offsets);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
- /* It might be the case that we grew the class to allocate a
- zero-sized base class. That won't be reflected in RLI, yet,
- because we are willing to overlay multiple bases at the same
- offset. However, now we need to make sure that RLI is big enough
- to reflect the entire class. */
- eoc = end_of_class (t, /*include_virtuals_p=*/0);
- if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
- && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
- {
- rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
- rli->bitpos = bitsize_zero_node;
- }
-
- /* We make all structures have at least one element, so that they
- have non-zero size. The class may be empty even if it has
- basetypes. Therefore, we add the fake field after all the other
- fields; if there are already FIELD_DECLs on the list, their
- offsets will not be disturbed. */
- if (!eoc && *empty_p)
+ if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
{
- tree padding;
-
- padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
- place_field (rli, padding);
+ /* Make sure that we are on a byte boundary so that the size of
+ the class without virtual bases will always be a round number
+ of bytes. */
+ rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+ normalize_rli (rli);
}
- /* Let the back-end lay out the type. Note that at this point we
- have only included non-virtual base-classes; we will lay out the
- virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
- this call are not necessarily correct; they are just the size and
- alignment when no virtual base clases are used. */
- finish_record_layout (rli);
+ /* G++ 3.2 does not allow virtual bases to be overlaid with tail
+ padding. */
+ if (!abi_version_at_least (2))
+ include_empty_classes(rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
- /* Remember the size and alignment of the class before adding
- the virtual bases. */
- if (*empty_p)
- {
- CLASSTYPE_SIZE (t) = bitsize_zero_node;
- CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
- }
- /* If this is a POD, we can't reuse its tail padding. */
- else if (!CLASSTYPE_NON_POD_P (t))
+ /* Create the version of T used for virtual bases. We do not use
+ make_aggr_type for this version; this is an artificial type. For
+ a POD type, we just reuse T. */
+ if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
- CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
+ base_t = make_node (TREE_CODE (t));
+
+ /* Set the size and alignment for the new type. In G++ 3.2, all
+ empty classes were considered to have size zero when used as
+ base classes. */
+ if (!abi_version_at_least (2) && CLASSTYPE_EMPTY_P (t))
+ {
+ TYPE_SIZE (base_t) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (base_t) = size_zero_node;
+ if (warn_abi && !integer_zerop (rli_size_unit_so_far (rli)))
+ warning ("layout of classes derived from empty class `%T' "
+ "may change in a future version of GCC",
+ t);
+ }
+ else
+ {
+ tree eoc;
+
+ /* If the ABI version is not at least two, and the last
+ field was a bit-field, RLI may not be on a byte
+ boundary. In particular, rli_size_unit_so_far might
+ indicate the last complete byte, while rli_size_so_far
+ indicates the total number of bits used. Therefore,
+ rli_size_so_far, rather than rli_size_unit_so_far, is
+ used to compute TYPE_SIZE_UNIT. */
+ eoc = end_of_class (t, /*include_virtuals_p=*/0);
+ TYPE_SIZE_UNIT (base_t)
+ = size_binop (MAX_EXPR,
+ convert (sizetype,
+ size_binop (CEIL_DIV_EXPR,
+ rli_size_so_far (rli),
+ bitsize_int (BITS_PER_UNIT))),
+ eoc);
+ TYPE_SIZE (base_t)
+ = size_binop (MAX_EXPR,
+ rli_size_so_far (rli),
+ size_binop (MULT_EXPR,
+ convert (bitsizetype, eoc),
+ bitsize_int (BITS_PER_UNIT)));
+ }
+ TYPE_ALIGN (base_t) = rli->record_align;
+ TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
+
+ /* Copy the fields from T. */
+ next_field = &TYPE_FIELDS (base_t);
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ *next_field = build_decl (FIELD_DECL,
+ DECL_NAME (field),
+ TREE_TYPE (field));
+ DECL_CONTEXT (*next_field) = base_t;
+ DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
+ DECL_FIELD_BIT_OFFSET (*next_field)
+ = DECL_FIELD_BIT_OFFSET (field);
+ next_field = &TREE_CHAIN (*next_field);
+ }
+
+ /* Record the base version of the type. */
+ CLASSTYPE_AS_BASE (t) = base_t;
+ TYPE_CONTEXT (base_t) = t;
}
else
- {
- CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
- }
-
- CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
- CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
+ CLASSTYPE_AS_BASE (t) = t;
/* Every empty class contains an empty class. */
- if (*empty_p)
+ if (CLASSTYPE_EMPTY_P (t))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
/* Set the TYPE_DECL for this type to contain the right
@@ -5019,54 +5175,63 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
- layout_virtual_bases (t, empty_base_offsets);
+ layout_virtual_bases (rli, empty_base_offsets);
- /* Warn about direct bases that can't be talked about due to
- ambiguity. */
- warn_about_ambiguous_direct_bases (t);
+ /* Make sure that empty classes are reflected in RLI at this
+ point. */
+ include_empty_classes(rli);
+
+ /* Make sure not to create any structures with zero size. */
+ if (integer_zerop (rli_size_unit_so_far (rli)) && CLASSTYPE_EMPTY_P (t))
+ place_field (rli,
+ build_decl (FIELD_DECL, NULL_TREE, char_type_node));
+
+ /* Let the back-end lay out the type. */
+ finish_record_layout (rli, /*free_p=*/true);
+
+ /* Warn about bases that can't be talked about due to ambiguity. */
+ warn_about_ambiguous_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
}
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
- (or C++ class declaration).
+/* Returns the virtual function with which the vtable for TYPE is
+ emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
+
+static tree
+key_method (tree type)
+{
+ tree method;
- For C++, we must handle the building of derived classes.
- Also, C++ allows static class members. The way that this is
- handled is to keep the field name where it is (as the DECL_NAME
- of the field), and place the overloaded decl in the bit position
- of the field. layout_record and layout_union will know about this.
+ if (TYPE_FOR_JAVA (type)
+ || processing_template_decl
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+ || CLASSTYPE_INTERFACE_KNOWN (type))
+ return NULL_TREE;
- More C++ hair: inline functions have text in their
- DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
- meaningful tree structure. After the struct has been laid out, set
- things up so that this can happen.
+ for (method = TYPE_METHODS (type); method != NULL_TREE;
+ method = TREE_CHAIN (method))
+ if (DECL_VINDEX (method) != NULL_TREE
+ && ! DECL_DECLARED_INLINE_P (method)
+ && ! DECL_PURE_VIRTUAL_P (method))
+ return method;
- And still more: virtual functions. In the case of single inheritance,
- when a new virtual function is seen which redefines a virtual function
- from the base class, the new virtual function is placed into
- the virtual function table at exactly the same address that
- it had in the base class. When this is extended to multiple
- inheritance, the same thing happens, except that multiple virtual
- function tables must be maintained. The first virtual function
- table is treated in exactly the same way as in the case of single
- inheritance. Additional virtual function tables have different
- DELTAs, which tell how to adjust `this' to point to the right thing.
+ return NULL_TREE;
+}
- ATTRIBUTES is the set of decl attributes to be applied, if any. */
+/* Perform processing required when the definition of T (a class type)
+ is complete. */
void
finish_struct_1 (t)
tree t;
{
tree x;
- int vfuns;
- /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
+ /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
tree virtuals = NULL_TREE;
int n_fields = 0;
tree vfield;
- int empty = 1;
if (COMPLETE_TYPE_P (t))
{
@@ -5083,17 +5248,32 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
- vfuns = 0;
- CLASSTYPE_RTTI (t) = NULL_TREE;
fixup_inline_methods (t);
+ /* Make assumptions about the class; we'll reset the flags if
+ necessary. */
+ CLASSTYPE_EMPTY_P (t) = 1;
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
+ CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
+
/* Do end-of-class semantic processing: checking the validity of the
bases and members and add implicitly generated methods. */
- check_bases_and_members (t, &empty);
+ check_bases_and_members (t);
+
+ /* Find the key method */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ {
+ CLASSTYPE_KEY_METHOD (t) = key_method (t);
+
+ /* If a polymorphic class has no key method, we may emit the vtable
+ in every translation unit where the class definition appears. */
+ if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
+ keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+ }
/* Layout the class itself. */
- layout_class_type (t, &empty, &vfuns, &virtuals);
+ layout_class_type (t, &virtuals);
/* Make sure that we get our own copy of the vfield FIELD_DECL. */
vfield = TYPE_VFIELD (t);
@@ -5104,7 +5284,7 @@ finish_struct_1 (t)
my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
BINFO_TYPE (primary)),
20010726);
- /* The vtable better be at the start. */
+ /* The vtable better be at the start. */
my_friendly_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)),
20010726);
my_friendly_assert (integer_zerop (BINFO_OFFSET (primary)),
@@ -5117,7 +5297,7 @@ finish_struct_1 (t)
else
my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
- virtuals = modify_all_vtables (t, &vfuns, nreverse (virtuals));
+ virtuals = modify_all_vtables (t, nreverse (virtuals));
/* If we created a new vtbl pointer for this class, add it to the
list. */
@@ -5135,28 +5315,13 @@ finish_struct_1 (t)
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
-
- /* If this type has basetypes with constructors, then those
- constructors might clobber the virtual function table. But
- they don't if the derived class shares the exact vtable of the base
- class. */
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
- /* If we didn't need a new vtable, see if we should copy one from
- the base. */
- else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
-
- /* If this class uses a different vtable than its primary base
- then when we will need to initialize our vptr after the base
- class constructor runs. */
- if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
if (TYPE_CONTAINS_VPTR_P (t))
{
+ int vindex;
+ tree fn;
+
if (TYPE_BINFO_VTABLE (t))
my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
20000116);
@@ -5164,9 +5329,17 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116);
- CLASSTYPE_VSIZE (t) = vfuns;
/* Add entries for virtual functions introduced by this class. */
TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);
+
+ /* Set DECL_VINDEX for all functions declared in this class. */
+ for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
+ fn;
+ fn = TREE_CHAIN (fn),
+ vindex += (TARGET_VTABLE_USES_DESCRIPTORS
+ ? TARGET_VTABLE_USES_DESCRIPTORS : 1))
+ if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
+ DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
}
finish_struct_bits (t);
@@ -5181,8 +5354,7 @@ finish_struct_1 (t)
/* Done with FIELDS...now decide whether to sort these for
faster lookups later.
- The C front-end only does this when n_fields > 15. We use
- a smaller number because most searches fail (succeeding
+ We use a small number because most searches fail (succeeding
ultimately as the search bores through the inheritance
hierarchy), and we want this failure to occur quickly. */
@@ -5202,15 +5374,13 @@ finish_struct_1 (t)
{
tree vfields = CLASSTYPE_VFIELDS (t);
- while (vfields)
- {
- /* Mark the fact that constructor for T
- could affect anybody inheriting from T
- who wants to initialize vtables for VFIELDS's type. */
- if (VF_DERIVED_VALUE (vfields))
- TREE_ADDRESSABLE (vfields) = 1;
- vfields = TREE_CHAIN (vfields);
- }
+ for (vfields = CLASSTYPE_VFIELDS (t);
+ vfields; vfields = TREE_CHAIN (vfields))
+ /* Mark the fact that constructor for T could affect anybody
+ inheriting from T who wants to initialize vtables for
+ VFIELDS's type. */
+ if (VF_BINFO_VALUE (vfields))
+ TREE_ADDRESSABLE (vfields) = 1;
}
/* Make the rtl for any new vtables we have created, and unmark
@@ -5248,10 +5418,10 @@ unreverse_member_declarations (t)
tree prev;
tree x;
- /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in
- reverse order. Put them in declaration order now. */
+ /* The following lists 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));
+ CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
/* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
reverse order, so we can't just use nreverse. */
@@ -5308,12 +5478,8 @@ finish_struct (t, attributes)
else
error ("trying to finish struct, but kicked out due to previous parse errors");
- if (processing_template_decl)
- {
- tree scope = current_scope ();
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- add_stmt (build_min (TAG_DEFN, t));
- }
+ if (processing_template_decl && at_function_scope_p ())
+ add_stmt (build_min (TAG_DEFN, t));
return t;
}
@@ -5370,7 +5536,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return NULL_TREE;
case NOP_EXPR:
@@ -5397,6 +5563,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* fall through... */
case TARGET_EXPR:
case PARM_DECL:
+ case RESULT_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
{
if (nonnull)
@@ -5408,7 +5575,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
if (nonnull)
*nonnull = 1;
- /* if we're in a ctor or dtor, we know our type. */
+ /* if we're in a ctor or dtor, we know our type. */
if (DECL_LANG_SPECIFIC (current_function_decl)
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl)))
@@ -5423,6 +5590,21 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
+
+ /* DECL_VAR_MARKED_P is used to prevent recursion; a
+ variable's initializer may refer to the variable
+ itself. */
+ if (TREE_CODE (instance) == VAR_DECL
+ && DECL_INITIAL (instance)
+ && !DECL_VAR_MARKED_P (instance))
+ {
+ tree type;
+ DECL_VAR_MARKED_P (instance) = 1;
+ type = fixed_type_or_null (DECL_INITIAL (instance),
+ nonnull, cdtorp);
+ DECL_VAR_MARKED_P (instance) = 0;
+ return type;
+ }
}
return NULL_TREE;
@@ -5431,7 +5613,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
}
}
-/* Return non-zero if the dynamic type of INSTANCE is known, and
+/* Return nonzero 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. Return negative if this is a
ctor/dtor. There the dynamic type is known, but this might not be
@@ -5473,7 +5655,6 @@ init_class_processing ()
= (class_stack_node_t) xmalloc (current_class_stack_size
* sizeof (struct class_stack_node));
VARRAY_TREE_INIT (local_classes, 8, "local_classes");
- ggc_add_tree_varray_root (&local_classes, 1);
access_default_node = build_int_2 (0, 0);
access_public_node = build_int_2 (ak_public, 0);
@@ -5601,7 +5782,7 @@ pushclass (type, modify)
unuse_fields (type);
}
- storetags (CLASSTYPE_TAGS (type));
+ cxx_remember_type_decls (CLASSTYPE_NESTED_UDTS (type));
}
}
@@ -5630,8 +5811,6 @@ void
popclass ()
{
poplevel_class ();
- /* Since poplevel_class does the popping of class decls nowadays,
- this really only frees the obstack used for these decls. */
pop_class_decls ();
current_class_depth--;
@@ -5748,7 +5927,7 @@ push_lang_context (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". */
+ So we re-enable debug output after extern "Java". */
DECL_IGNORED_P (TYPE_NAME (java_byte_type_node)) = 0;
DECL_IGNORED_P (TYPE_NAME (java_short_type_node)) = 0;
DECL_IGNORED_P (TYPE_NAME (java_int_type_node)) = 0;
@@ -5780,7 +5959,7 @@ pop_lang_context ()
/* 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. Permit pointers to member function if PTRMEM is non-zero.
+ nonzero. Permit pointers to member function if PTRMEM is nonzero.
If TEMPLATE_ONLY, the name of the overloaded function
was a template-id, and EXPLICIT_TARGS are the explicitly provided
template arguments. */
@@ -6045,7 +6224,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
/* 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);
+ cxx_mark_addressable (fn);
return fn;
}
@@ -6090,6 +6269,9 @@ instantiate_type (lhstype, rhs, flags)
return error_mark_node;
}
+ if (TREE_CODE (rhs) == BASELINK)
+ rhs = BASELINK_FUNCTIONS (rhs);
+
/* We don't overwrite rhs if it is an overloaded function.
Copying it would destroy the tree link. */
if (TREE_CODE (rhs) != OVERLOAD)
@@ -6136,7 +6318,7 @@ instantiate_type (lhstype, rhs, flags)
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, TREE_VALUE (rhs),
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
flags | allow_ptrmem);
/* This can happen if we are forming a pointer-to-member for a
@@ -6169,10 +6351,10 @@ instantiate_type (lhstype, rhs, flags)
/*explicit_targs=*/NULL_TREE);
case TREE_LIST:
- /* Now we should have a baselink. */
+ /* Now we should have a baselink. */
my_friendly_assert (BASELINK_P (rhs), 990412);
- return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
@@ -6377,7 +6559,38 @@ is_empty_class (type)
if (! IS_AGGR_TYPE (type))
return 0;
- return integer_zerop (CLASSTYPE_SIZE (type));
+ /* In G++ 3.2, whether or not a class was empty was determined by
+ looking at its size. */
+ if (abi_version_at_least (2))
+ return CLASSTYPE_EMPTY_P (type);
+ else
+ return integer_zerop (CLASSTYPE_SIZE (type));
+}
+
+/* Returns true if TYPE contains an empty class. */
+
+static bool
+contains_empty_class_p (tree type)
+{
+ if (is_empty_class (type))
+ return true;
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ int i;
+
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
+ return true;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_ARTIFICIAL (field)
+ && is_empty_class (TREE_TYPE (field)))
+ return true;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return contains_empty_class_p (TREE_TYPE (type));
+ return false;
}
/* Find the enclosing class of the given NODE. NODE can be a *_DECL or
@@ -6456,7 +6669,7 @@ maybe_note_name_used_in_class (name, decl)
}
/* Note that NAME was declared (as DECL) in the current class. Check
- to see that the declaration is legal. */
+ to see that the declaration is valid. */
void
note_name_declared_in_class (name, decl)
@@ -6511,7 +6724,7 @@ get_vtbl_decl_for_binfo (binfo)
/* Called from get_primary_binfo via dfs_walk. DATA is a TREE_LIST
who's TREE_PURPOSE is the TYPE of the required primary base and
- who's TREE_VALUE is a list of candidate binfos that we fill in. */
+ who's TREE_VALUE is a list of candidate binfos that we fill in. */
static tree
dfs_get_primary_binfo (binfo, data)
@@ -6618,7 +6831,7 @@ get_primary_binfo (binfo)
return result;
}
-/* If INDENTED_P is zero, indent to INDENT. Return non-zero. */
+/* If INDENTED_P is zero, indent to INDENT. Return nonzero. */
static int
maybe_indent_hierarchy (stream, indent, indented_p)
@@ -6908,6 +7121,7 @@ initialize_array (decl, inits)
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) = 1;
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
@@ -6949,8 +7163,10 @@ build_vtt (t)
/* Now, build the VTT object itself. */
vtt = build_vtable (t, get_vtt_name (t), type);
- pushdecl_top_level (vtt);
initialize_array (vtt, inits);
+ /* Add the VTT to the vtables list. */
+ TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
+ TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
dump_vtt (t, vtt);
}
@@ -6985,7 +7201,7 @@ get_original_base (base_binfo, binfo)
/* When building a secondary VTT, BINFO_VTABLE is set to a TREE_LIST with
PURPOSE the RTTI_BINFO, VALUE the real vtable pointer for this binfo,
and CHAIN the vtable pointer for this binfo after construction is
- complete. VALUE can also be another BINFO, in which case we recurse. */
+ complete. VALUE can also be another BINFO, in which case we recurse. */
static tree
binfo_ctor_vtable (binfo)
@@ -7176,7 +7392,7 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data)
{
/* It's a primary virtual base, and this is not the construction
vtable. Find the base this is primary of in the inheritance graph,
- and use that base's vtable now. */
+ and use that base's vtable now. */
while (BINFO_PRIMARY_BASE_OF (binfo))
binfo = BINFO_PRIMARY_BASE_OF (binfo);
}
@@ -7285,7 +7501,7 @@ build_ctor_vtbl_group (binfo, t)
TREE_TYPE (vtbl) = type;
/* Initialize the construction vtable. */
- pushdecl_top_level (vtbl);
+ CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
initialize_array (vtbl, inits);
dump_vtable (t, binfo, vtbl);
}
@@ -7315,7 +7531,7 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
BINFO_TYPE (orig_binfo)),
20000517);
- /* If it doesn't have a vptr, we don't do anything. */
+ /* If it doesn't have a vptr, we don't do anything. */
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
return;
@@ -7502,8 +7718,9 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vid.last_init = &vid.inits;
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+ vid.generate_vcall_entries = true;
/* The first vbase or vcall offset is at index -3 in the vtable. */
- vid.index = ssize_int (-3);
+ vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
/* Add entries to the vtable for RTTI. */
build_rtti_vtbl_entries (binfo, &vid);
@@ -7514,8 +7731,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
VARRAY_TREE_INIT (vid.fns, 32, "fns");
/* Add the vcall and vbase offset entries. */
build_vcall_and_vbase_vtbl_entries (binfo, &vid);
- /* Clean up. */
- VARRAY_FREE (vid.fns);
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
@@ -7523,6 +7738,25 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vbase = TREE_CHAIN (vbase))
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
+ /* If the target requires padding between data entries, add that now. */
+ if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
+ {
+ tree cur, *prev;
+
+ for (prev = &vid.inits; (cur = *prev); prev = &TREE_CHAIN (cur))
+ {
+ tree add = cur;
+ int i;
+
+ for (i = 1; i < TARGET_VTABLE_DATA_ENTRY_DISTANCE; ++i)
+ add = tree_cons (NULL_TREE,
+ build1 (NOP_EXPR, vtable_entry_type,
+ null_pointer_node),
+ add);
+ *prev = add;
+ }
+ }
+
if (non_fn_entries_p)
*non_fn_entries_p = list_length (vid.inits);
@@ -7534,7 +7768,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree delta;
tree vcall_index;
tree fn;
- tree pfn;
tree init = NULL_TREE;
fn = BV_FN (v);
@@ -7569,14 +7802,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
-
- if (BV_USE_VCALL_INDEX_P (v))
- {
- vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (vcall_index != NULL_TREE, 20000621);
- }
- else
- vcall_index = NULL_TREE;
+ vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
@@ -7585,15 +7811,13 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
So, we replace these functions with __pure_virtual. */
if (DECL_PURE_VIRTUAL_P (fn))
fn = abort_fndecl;
-
+ else if (!integer_zerop (delta) || vcall_index)
+ fn = make_thunk (fn, delta, vcall_index);
/* Take the address of the function, considering it to be of an
appropriate generic type. */
- pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+ init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
/* The address of a function can't change. */
- TREE_CONSTANT (pfn) = 1;
-
- /* Enter it in the vtable. */
- init = build_vtable_entry (delta, vcall_index, pfn);
+ TREE_CONSTANT (init) = 1;
}
/* And add it to the chain of initializers. */
@@ -7740,7 +7964,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
}
/* The next vbase will come at a more negative offset. */
- vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+ vid->index = size_binop (MINUS_EXPR, vid->index,
+ ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and
@@ -7766,31 +7991,37 @@ build_vcall_offset_vtbl_entries (binfo, vid)
tree binfo;
vtbl_init_data *vid;
{
- /* We only need these entries if this base is a virtual base. */
- if (!TREE_VIA_VIRTUAL (binfo))
- return;
-
- /* We need a vcall offset for each of the virtual functions in this
- vtable. For example:
+ /* We only need these entries if this base is a virtual base. We
+ compute the indices -- but do not add to the vtable -- when
+ building the main vtable for a class. */
+ if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
+ {
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
- class A { virtual void f (); };
- class B1 : virtual public A { virtual void f (); };
- class B2 : virtual public A { virtual void f (); };
- class C: public B1, public B2 { virtual void f (); };
+ class A { virtual void f (); };
+ class B1 : virtual public A { virtual void f (); };
+ class B2 : virtual public A { virtual void f (); };
+ class C: public B1, public B2 { virtual void f (); };
- A C object has a primary base of B1, which has a primary base of A. A
- C also has a secondary base of B2, which no longer has a primary base
- of A. So the B2-in-C construction vtable needs a secondary vtable for
- A, which will adjust the A* to a B2* to call f. We have no way of
- knowing what (or even whether) this offset will be when we define B2,
- so we store this "vcall offset" in the A sub-vtable and look it up in
- a "virtual thunk" for B2::f.
+ A C object has a primary base of B1, which has a primary base of A. A
+ C also has a secondary base of B2, which no longer has a primary base
+ of A. So the B2-in-C construction vtable needs a secondary vtable for
+ A, which will adjust the A* to a B2* to call f. We have no way of
+ knowing what (or even whether) this offset will be when we define B2,
+ so we store this "vcall offset" in the A sub-vtable and look it up in
+ a "virtual thunk" for B2::f.
- We need entries for all the functions in our primary vtable and
- in our non-virtual bases' secondary vtables. */
- vid->vbase = binfo;
- /* Now, walk through the non-virtual bases, adding vcall offsets. */
- add_vcall_offset_vtbl_entries_r (binfo, vid);
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases' secondary vtables. */
+ vid->vbase = binfo;
+ /* If we are just computing the vcall indices -- but do not need
+ the actual entries -- not that. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ vid->generate_vcall_entries = false;
+ /* Now, walk through the non-virtual bases, adding vcall offsets. */
+ add_vcall_offset_vtbl_entries_r (binfo, vid);
+ }
}
/* Build vcall offsets, starting with those for BINFO. */
@@ -7836,136 +8067,154 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree binfo;
vtbl_init_data* vid;
{
- tree derived_virtuals;
- tree base_virtuals;
- tree orig_virtuals;
- tree binfo_inits;
- /* If BINFO is a primary base, the most derived class which has BINFO as
- a primary base; otherwise, just BINFO. */
- tree non_primary_binfo;
-
- binfo_inits = NULL_TREE;
-
- /* We might be a primary base class. Go up the inheritance hierarchy
- until we find the most derived class of which we are a primary base:
- it is the BINFO_VIRTUALS there that we need to consider. */
- non_primary_binfo = binfo;
- while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
+ /* Make entries for the rest of the virtuals. */
+ if (abi_version_at_least (2))
{
- tree b;
+ tree orig_fn;
- /* If we have reached a virtual base, then it must be vid->vbase,
- because we ignore other virtual bases in
- add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
- base (possibly multi-level) of vid->binfo, or we wouldn't
- have called build_vcall_and_vbase_vtbl_entries for it. But it
- might be a lost primary, so just skip down to vid->binfo. */
- if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ /* The ABI requires that the methods be processed in declaration
+ order. G++ 3.2 used the order in the vtable. */
+ for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
+ orig_fn;
+ orig_fn = TREE_CHAIN (orig_fn))
+ if (DECL_VINDEX (orig_fn))
+ add_vcall_offset (orig_fn, binfo, vid);
+ }
+ else
+ {
+ tree derived_virtuals;
+ tree base_virtuals;
+ tree orig_virtuals;
+ /* If BINFO is a primary base, the most derived class which has
+ BINFO as a primary base; otherwise, just BINFO. */
+ tree non_primary_binfo;
+
+ /* We might be a primary base class. Go up the inheritance hierarchy
+ until we find the most derived class of which we are a primary base:
+ it is the BINFO_VIRTUALS there that we need to consider. */
+ non_primary_binfo = binfo;
+ while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{
- if (non_primary_binfo != vid->vbase)
- abort ();
- non_primary_binfo = vid->binfo;
- break;
+ tree b;
+
+ /* If we have reached a virtual base, then it must be vid->vbase,
+ because we ignore other virtual bases in
+ add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
+ base (possibly multi-level) of vid->binfo, or we wouldn't
+ have called build_vcall_and_vbase_vtbl_entries for it. But it
+ might be a lost primary, so just skip down to vid->binfo. */
+ if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ {
+ if (non_primary_binfo != vid->vbase)
+ abort ();
+ non_primary_binfo = vid->binfo;
+ break;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ if (get_primary_binfo (b) != non_primary_binfo)
+ break;
+ non_primary_binfo = b;
}
- b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
- if (get_primary_binfo (b) != non_primary_binfo)
- break;
- non_primary_binfo = b;
+ if (vid->ctor_vtbl_p)
+ /* For a ctor vtable we need the equivalent binfo within the hierarchy
+ where rtti_binfo is the most derived type. */
+ non_primary_binfo = get_original_base
+ (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
+
+ for (base_virtuals = BINFO_VIRTUALS (binfo),
+ derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
+ orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+ base_virtuals;
+ base_virtuals = TREE_CHAIN (base_virtuals),
+ derived_virtuals = TREE_CHAIN (derived_virtuals),
+ orig_virtuals = TREE_CHAIN (orig_virtuals))
+ {
+ tree orig_fn;
+
+ /* Find the declaration that originally caused this function to
+ be present in BINFO_TYPE (binfo). */
+ orig_fn = BV_FN (orig_virtuals);
+
+ /* When processing BINFO, we only want to generate vcall slots for
+ function slots introduced in BINFO. So don't try to generate
+ one if the function isn't even defined in BINFO. */
+ if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
+ continue;
+
+ add_vcall_offset (orig_fn, binfo, vid);
+ }
}
+}
- if (vid->ctor_vtbl_p)
- /* For a ctor vtable we need the equivalent binfo within the hierarchy
- where rtti_binfo is the most derived type. */
- non_primary_binfo = get_original_base
- (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
+/* Add a vcall offset entry for ORIG_FN to the vtable. */
- /* Make entries for the rest of the virtuals. */
- for (base_virtuals = BINFO_VIRTUALS (binfo),
- derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
- orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
- base_virtuals;
- base_virtuals = TREE_CHAIN (base_virtuals),
- derived_virtuals = TREE_CHAIN (derived_virtuals),
- orig_virtuals = TREE_CHAIN (orig_virtuals))
+static void
+add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
+{
+ size_t i;
+ tree vcall_offset;
+
+ /* If there is already an entry for a function with the same
+ signature as FN, then we do not need a second vcall offset.
+ Check the list of functions already present in the derived
+ class vtable. */
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
{
- tree orig_fn;
- tree fn;
- tree base;
- tree base_binfo;
- size_t i;
- tree vcall_offset;
+ tree derived_entry;
- /* Find the declaration that originally caused this function to
- be present in BINFO_TYPE (binfo). */
- orig_fn = BV_FN (orig_virtuals);
+ derived_entry = VARRAY_TREE (vid->fns, i);
+ if (same_signature_p (derived_entry, orig_fn)
+ /* We only use one vcall offset for virtual destructors,
+ even though there are two virtual table entries. */
+ || (DECL_DESTRUCTOR_P (derived_entry)
+ && DECL_DESTRUCTOR_P (orig_fn)))
+ return;
+ }
- /* When processing BINFO, we only want to generate vcall slots for
- function slots introduced in BINFO. So don't try to generate
- one if the function isn't even defined in BINFO. */
- if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
- continue;
+ /* If we are building these vcall offsets as part of building
+ the vtable for the most derived class, remember the vcall
+ offset. */
+ if (vid->binfo == TYPE_BINFO (vid->derived))
+ CLASSTYPE_VCALL_INDICES (vid->derived)
+ = tree_cons (orig_fn, vid->index,
+ CLASSTYPE_VCALL_INDICES (vid->derived));
- /* Find the overriding function. */
- fn = BV_FN (derived_virtuals);
+ /* The next vcall offset will be found at a more negative
+ offset. */
+ vid->index = size_binop (MINUS_EXPR, vid->index,
+ ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
+
+ /* Keep track of this function. */
+ VARRAY_PUSH_TREE (vid->fns, orig_fn);
- /* If there is already an entry for a function with the same
- signature as FN, then we do not need a second vcall offset.
- Check the list of functions already present in the derived
- class vtable. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
+ if (vid->generate_vcall_entries)
+ {
+ tree base;
+ tree fn;
+
+ /* Find the overriding function. */
+ fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
+ if (fn == error_mark_node)
+ vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
+ integer_zero_node);
+ else
{
- tree derived_entry;
-
- derived_entry = VARRAY_TREE (vid->fns, i);
- if (same_signature_p (BV_FN (derived_entry), fn)
- /* We only use one vcall offset for virtual destructors,
- even though there are two virtual table entries. */
- || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
- && DECL_DESTRUCTOR_P (fn)))
- {
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals)
- = BV_VCALL_INDEX (derived_entry);
- break;
- }
+ base = TREE_VALUE (fn);
+
+ /* The vbase we're working on is a primary base of
+ vid->binfo. But it might be a lost primary, so its
+ BINFO_OFFSET might be wrong, so we just use the
+ BINFO_OFFSET from vid->binfo. */
+ vcall_offset = size_diffop (BINFO_OFFSET (base),
+ BINFO_OFFSET (vid->binfo));
+ vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
+ vcall_offset));
}
- if (i != VARRAY_ACTIVE_SIZE (vid->fns))
- continue;
-
- /* The FN comes from BASE. So, we must calculate the adjustment from
- vid->vbase to BASE. We can just look for BASE in the complete
- object because we are converting from a virtual base, so if there
- were multiple copies, there would not be a unique final overrider
- and vid->derived would be ill-formed. */
- base = DECL_CONTEXT (fn);
- base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
- /* Compute the vcall offset. */
- /* As mentioned above, the vbase we're working on is a primary base of
- vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
- might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
- vcall_offset = BINFO_OFFSET (vid->binfo);
- vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
- vcall_offset);
- vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
- vcall_offset));
-
+ /* Add the intiailizer to the vtable. */
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init);
-
- /* Keep track of the vtable index where this vcall offset can be
- found. For a construction vtable, we already made this
- annotation when we built the original vtable. */
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals) = vid->index;
-
- /* The next vcall offset will be found at a more negative
- offset. */
- vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
-
- /* Keep track of this function. */
- VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
}
}
@@ -8004,52 +8253,20 @@ build_rtti_vtbl_entries (binfo, vid)
/* The second entry is the address of the typeinfo object. */
if (flag_rtti)
- decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ decl = build_address (get_tinfo_decl (t));
else
decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the
vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, decl);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, offset);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
-
-/* Build an entry in the virtual function table. DELTA is the offset
- for the `this' pointer. VCALL_INDEX is the vtable index containing
- the vcall offset; NULL_TREE if none. ENTRY is the virtual function
- table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
- but it may not actually be a virtual function table pointer. (For
- example, it might be the address of the RTTI object, under the new
- ABI.) */
-
-static tree
-build_vtable_entry (delta, vcall_index, entry)
- tree delta;
- tree vcall_index;
- tree entry;
-{
- tree fn = TREE_OPERAND (entry, 0);
-
- if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
- && fn != abort_fndecl)
- {
- entry = make_thunk (entry, delta, vcall_index);
- entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
- TREE_READONLY (entry) = 1;
- TREE_CONSTANT (entry) = 1;
- }
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
- return entry;
-}
diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in
index c07408d..b8feb03 100644
--- a/contrib/gcc/cp/config-lang.in
+++ b/contrib/gcc/cp/config-lang.in
@@ -33,3 +33,5 @@ compilers="cc1plus\$(exeext)"
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
target_libs="${libstdcxx_version} target-gperf"
+
+gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/parse.y \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/spew.c \$(srcdir)/cp/tree.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"
diff --git a/contrib/gcc/cp/cp-lang.c b/contrib/gcc/cp/cp-lang.c
index 1464ef6..0d8a4e3 100644
--- a/contrib/gcc/cp/cp-lang.c
+++ b/contrib/gcc/cp/cp-lang.c
@@ -28,9 +28,11 @@ Boston, MA 02111-1307, USA. */
#include "langhooks.h"
#include "langhooks-def.h"
-static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
-static tree cp_expr_size PARAMS ((tree));
-static bool cp_var_mod_type_p PARAMS ((tree));
+static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
+static bool ok_to_generate_alias_set_for_type PARAMS ((tree));
+static bool cxx_warn_unused_global_decl PARAMS ((tree));
+static tree cp_expr_size PARAMS ((tree));
+static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "GNU C++"
@@ -43,15 +45,35 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS cxx_init_options
#undef LANG_HOOKS_DECODE_OPTION
-#define LANG_HOOKS_DECODE_OPTION cxx_decode_option
+#define LANG_HOOKS_DECODE_OPTION c_common_decode_option
#undef LANG_HOOKS_POST_OPTIONS
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET cxx_get_alias_set
#undef LANG_HOOKS_EXPAND_CONSTANT
#define LANG_HOOKS_EXPAND_CONSTANT cplus_expand_constant
+#undef LANG_HOOKS_EXPAND_EXPR
+#define LANG_HOOKS_EXPAND_EXPR cxx_expand_expr
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL cxx_dup_lang_specific_decl
+#undef LANG_HOOKS_UNSAVE_EXPR_NOW
+#define LANG_HOOKS_UNSAVE_EXPR_NOW cxx_unsave_expr_now
+#undef LANG_HOOKS_MAYBE_BUILD_CLEANUP
+#define LANG_HOOKS_MAYBE_BUILD_CLEANUP cxx_maybe_build_cleanup
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
+#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES cxx_insert_default_attributes
+#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
+#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
+#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME mangle_decl
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE cxx_mark_addressable
#undef LANG_HOOKS_PRINT_STATISTICS
#define LANG_HOOKS_PRINT_STATISTICS cxx_print_statistics
#undef LANG_HOOKS_PRINT_XNODE
@@ -62,8 +84,28 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#define LANG_HOOKS_PRINT_TYPE cxx_print_type
#undef LANG_HOOKS_PRINT_IDENTIFIER
#define LANG_HOOKS_PRINT_IDENTIFIER cxx_print_identifier
-#undef LANG_HOOKS_SET_YYDEBUG
-#define LANG_HOOKS_SET_YYDEBUG cxx_set_yydebug
+#undef LANG_HOOKS_DECL_PRINTABLE_NAME
+#define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name
+#undef LANG_HOOKS_PRINT_ERROR_FUNCTION
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION cxx_print_error_function
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
+#undef LANG_HOOKS_WRITE_GLOBALS
+#define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
+
+
+#undef LANG_HOOKS_FUNCTION_INIT
+#define LANG_HOOKS_FUNCTION_INIT cxx_push_function_context
+#undef LANG_HOOKS_FUNCTION_FINAL
+#define LANG_HOOKS_FUNCTION_FINAL cxx_pop_function_context
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE cxx_attribute_table
#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES \
@@ -98,23 +140,158 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_EXPR_SIZE
#define LANG_HOOKS_EXPR_SIZE cp_expr_size
+#undef LANG_HOOKS_MAKE_TYPE
+#define LANG_HOOKS_MAKE_TYPE cxx_make_type
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR cxx_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO cxx_type_promotes_to
+
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+/* Tree code classes. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+ 'x',
+#include "c-common.def"
+ 'x',
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Table indexed by tree code giving number of expression
+ operands beyond the fixed part of the node structure.
+ Not used for types or decls. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+ 0,
+#include "c-common.def"
+ 0,
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Names of tree components.
+ Used for printing out the tree and error messages. */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char *const tree_code_name[] = {
+#include "tree.def"
+ "@@dummy",
+#include "c-common.def"
+ "@@dummy",
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Check if a C++ type is safe for aliasing.
+ Return TRUE if T safe for aliasing FALSE otherwise. */
+
+static bool
+ok_to_generate_alias_set_for_type (t)
+ tree t;
+{
+ if (TYPE_PTRMEMFUNC_P (t))
+ return true;
+ if (AGGREGATE_TYPE_P (t))
+ {
+ if ((TREE_CODE (t) == RECORD_TYPE) || (TREE_CODE (t) == UNION_TYPE))
+ {
+ tree fields;
+ /* Backend-created structs are safe. */
+ if (! CLASS_TYPE_P (t))
+ return true;
+ /* PODs are safe. */
+ if (! CLASSTYPE_NON_POD_P(t))
+ return true;
+ /* Classes with virtual baseclasses are not. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (t))
+ return false;
+ /* Recursively check the base classes. */
+ if (TYPE_BINFO (t) != NULL && TYPE_BINFO_BASETYPES (t) != NULL)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); i++)
+ {
+ tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
+ if (!ok_to_generate_alias_set_for_type (BINFO_TYPE (binfo)))
+ return false;
+ }
+ }
+ /* Check all the fields. */
+ for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
+ {
+ if (TREE_CODE (fields) != FIELD_DECL)
+ continue;
+ if (! ok_to_generate_alias_set_for_type (TREE_TYPE (fields)))
+ return false;
+ }
+ return true;
+ }
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ return ok_to_generate_alias_set_for_type (TREE_TYPE (t));
+ else
+ /* This should never happen, we dealt with all the aggregate
+ types that can appear in C++ above. */
+ abort ();
+ }
+ else
+ return true;
+}
+
/* Special routine to get the alias set for C++. */
static HOST_WIDE_INT
cxx_get_alias_set (t)
tree t;
{
- /* It's not yet safe to use alias sets for classes in C++ because
- the TYPE_FIELDs list for a class doesn't mention base classes. */
- if (AGGREGATE_TYPE_P (t))
+ if (/* It's not yet safe to use alias sets for some classes in C++. */
+ !ok_to_generate_alias_set_for_type (t)
+ /* Nor is it safe to use alias sets for pointers-to-member
+ functions, due to the fact that there may be more than one
+ RECORD_TYPE type corresponding to the same pointer-to-member
+ type. */
+ || TYPE_PTRMEMFUNC_P (t))
return 0;
return c_common_get_alias_set (t);
}
+/* Called from check_global_declarations. */
+
+static bool
+cxx_warn_unused_global_decl (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+ return false;
+ if (DECL_IN_SYSTEM_HEADER (decl))
+ return false;
+
+ /* Const variables take the place of #defines in C++. */
+ if (TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl))
+ return false;
+
+ return true;
+}
+
/* Langhook for expr_size: Tell the backend that the value of an expression
of non-POD class type does not include any tail padding; a derived class
might have allocated something there. */
@@ -125,8 +302,16 @@ cp_expr_size (exp)
{
if (CLASS_TYPE_P (TREE_TYPE (exp)))
{
- /* This would be wrong for a type with virtual bases, but they should
- not get here. */
+ /* The backend should not be interested in the size of an expression
+ of a type with both of these set; all copies of such types must go
+ through a constructor or assignment op. */
+ if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
+ && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp))
+ /* But storing a CONSTRUCTOR isn't a copy. */
+ && TREE_CODE (exp) != CONSTRUCTOR)
+ abort ();
+ /* This would be wrong for a type with virtual bases, but they are
+ caught by the abort above. */
return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp));
}
else
diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def
index 3854525..cee19ab 100644
--- a/contrib/gcc/cp/cp-tree.def
+++ b/contrib/gcc/cp/cp-tree.def
@@ -23,11 +23,25 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Reference to the contents of an offset
- (a value whose type is an OFFSET_TYPE).
- Operand 0 is the object within which the offset is taken.
- Operand 1 is the offset. The language independent OFFSET_REF
- just won't work for us. */
+/* An OFFSET_REF is used in two situations:
+
+ 1. An expression of the form `A::m' where `A' is a class and `m' is
+ a non-static data member. In this case, operand 0 will be a
+ TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL
+ (corresponding to `m'.
+
+ The expression is a pointer-to-member if its address is taken,
+ but simply denotes a member of the object if its address isnot
+ taken. In the latter case, resolve_offset_ref is used to
+ convert it to a representation of the member referred to by the
+ OFFSET_REF.
+
+ 2. An expression of the form `x.*p'. In this case, operand 0 will
+ be an expression corresponding to `x' and operand 1 will be an
+ expression with pointer-to-member type.
+
+ OFFSET_REFs are only used during the parsing phase; once semantic
+ analysis has taken place they are eliminated. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
/* A pointer-to-member constant. For a pointer-to-member constant
@@ -75,6 +89,20 @@ DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1)
these to avoid actually creating instances of the empty classes. */
DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0)
+/* A reference to a member function or member functions from a base
+ class. BASELINK_FUNCTIONS gives the FUNCTION_DECL,
+ TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the
+ functions. BASELINK_BINFO gives the base from which the functions
+ come, i.e., the base to which the `this' pointer must be converted
+ before the functions are called. BASELINK_ACCESS_BINFO gives the
+ base used to name the functions.
+
+ A BASELINK is an expression; the TREE_TYPE of the BASELINK gives
+ the type of the expression. This type is either a FUNCTION_TYPE,
+ METHOD_TYPE, or `unknown_type_node' indicating that the function is
+ overloaded. */
+DEFTREECODE (BASELINK, "baselink", 'e', 3)
+
/* Template definition. The following fields have the specified uses,
although there are other macros in cp-tree.h that should be used for
accessing this data.
@@ -186,14 +214,10 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 2)
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. */
+ template may be an IDENTIFIER_NODE. In an uninstantiated template,
+ the template may be a LOOKUP_EXPR. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
-/* 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
the original name, and the parameter is the FUNCTION_DECL. */
DEFTREECODE (OVERLOAD, "overload", 'x', 1)
@@ -220,19 +244,9 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
-/* A SUBOBJECT statement marks the point at which a sub-object is
- fully constructed. After this point, the SUBOBJECT_CLEANUP must be
- run if an exception is thrown before the end of the enclosing
- function. */
-DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
-/* An CTOR_STMT marks the beginning (if CTOR_BEGIN_P holds) or end of
- a constructor (if CTOR_END_P) holds. At the end of a constructor,
- the cleanups associated with any SUBOBJECT_CLEANUPS need no longer
- be run. */
-DEFTREECODE (CTOR_STMT, "ctor_stmt", 'e', 0)
/* CTOR_INITIALIZER is a placeholder in template code for a call to
setup_vtbl_pointer (and appears in all functions, not just ctors). */
-DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
+DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2)
DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2)
@@ -248,7 +262,13 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
-/* And some codes for expressing conversions for overload resolution. */
+/* The following codes are used to represent implicit conversion
+ sequences, in the sense of [over.best.ics]. The conversion
+ sequences are connected through their first operands, with the
+ first conversion to be performed at the end of the chain.
+
+ The innermost conversion (i.e, the one at the end of the chain) is
+ always an IDENTITY_CONV, corresponding to the identity conversion. */
DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index a2c0db1..bfeec9b 100644
--- a/contrib/gcc/cp/cp-tree.h
+++ b/contrib/gcc/cp/cp-tree.h
@@ -20,20 +20,22 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifndef GCC_CP_TREE_H
+#define GCC_CP_TREE_H
+
#include "function.h"
#include "hashtab.h"
#include "splay-tree.h"
#include "varray.h"
-#ifndef GCC_CP_TREE_H
-#define GCC_CP_TREE_H
-
#ifndef __GNUC__
#error "You should be using 'make bootstrap' -- see installation instructions"
#endif
#include "c-common.h"
+struct diagnostic_context;
+
/* Usage of TREE_LANG_FLAG_?:
0: BINFO_MARKED (BINFO nodes).
IDENTIFIER_MARKED (IDENTIFIER_NODEs)
@@ -41,12 +43,9 @@ Boston, MA 02111-1307, USA. */
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_INDIRECT_USING (in NAMESPACE_DECL).
- LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
- CTOR_BEGIN_P (in CTOR_STMT)
- BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
PARMLIST_ELLIPSIS_P (in PARMLIST)
1: IDENTIFIER_VIRTUAL_P.
@@ -55,14 +54,12 @@ Boston, MA 02111-1307, USA. */
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
- INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
- BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
+ DECL_INITIALIZED_P (in VAR_DECL)
2: IDENTIFIER_OPNAME_P.
- TYPE_POLYMORHPIC_P (in _TYPE)
+ TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
- BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
@@ -96,11 +93,11 @@ Boston, MA 02111-1307, USA. */
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
- DECL_C_BITFIELD (in FIELD_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
- 4: DECL_C_BIT_FIELD
+ 4: DECL_C_BIT_FIELD (in a FIELD_DECL)
+ DECL_VAR_MARKED_P (in a VAR_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
@@ -121,16 +118,18 @@ Boston, MA 02111-1307, USA. */
For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS
BINFO_VIRTUALS
- For a binfo, this is a TREE_LIST. The BV_DELTA of each node
- gives the amount by which to adjust the `this' pointer when
- calling the function. If the method is an overriden version of a
- base class method, then it is assumed that, prior to adjustment,
- the this pointer points to an object of the base class.
+ For a binfo, this is a TREE_LIST. There is an entry for each
+ virtual function declared either in BINFO or its direct and
+ indirect primary bases.
+
+ The BV_DELTA of each node gives the amount by which to adjust the
+ `this' pointer when calling the function. If the method is an
+ overriden version of a base class method, then it is assumed
+ that, prior to adjustment, the this pointer points to an object
+ of the base class.
The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
- index of the vcall offset for this entry. If
- BV_USE_VCALL_INDEX_P then the corresponding vtable entry should
- use a virtual thunk, as opposed to an ordinary thunk.
+ index of the vcall offset for this entry.
The BV_FN is the declaration for the virtual function itself.
@@ -153,7 +152,7 @@ Boston, MA 02111-1307, USA. */
the virtual function this one overrides, and whose TREE_CHAIN is
the old DECL_VINDEX. */
-/* Language-specific tree checkers. */
+/* Language-specific tree checkers. */
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
@@ -212,31 +211,70 @@ Boston, MA 02111-1307, USA. */
#endif
+/* Returns TRUE if generated code should match ABI version N or
+ greater is in use. */
+
+#define abi_version_at_least(N) \
+ (flag_abi_version == 0 || flag_abi_version >= (N))
+
-/* ABI control. */
+/* Datatype used to temporarily save C++ bindings (for implicit
+ instantiations purposes and like). Implemented in decl.c. */
+typedef struct cxx_saved_binding cxx_saved_binding;
-/* Nonzero to use __cxa_atexit, rather than atexit, to register
- destructors for local statics and global objects. */
+/* Datatype that represents binding established by a declaration between
+ a name and a C++ entity. */
+typedef struct cxx_binding cxx_binding;
-extern int flag_use_cxa_atexit;
+/* (GC-)allocate a cxx_binding object. */
+#define cxx_binding_make() (ggc_alloc (sizeof (cxx_binding)))
-/* Nonzero means generate 'rtti' that give run-time type information. */
+/* Zero out a cxx_binding pointed to by B. */
+#define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding))
-extern int flag_rtti;
+struct cxx_binding GTY(())
+{
+ /* Link to chain together various bindings for this name. */
+ cxx_binding *previous;
+ /* The non-type entity this name is bound to. */
+ tree value;
+ /* The type entity this name is bound to. */
+ tree type;
+ union tree_binding_u {
+ tree GTY ((tag ("0"))) scope;
+ struct cp_binding_level * GTY ((tag ("1"))) level;
+ } GTY ((desc ("%0.has_level"))) scope;
+ unsigned has_level : 1;
+ unsigned value_is_inherited : 1;
+ unsigned is_local : 1;
+};
-/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
+/* The type of dictionary used to map names to types declared at
+ a given scope. */
+typedef struct binding_table_s *binding_table;
+typedef struct binding_entry_s *binding_entry;
-extern int flag_huge_objects;
+/* The type of a routine repeatedly called by binding_table_foreach. */
+typedef void (*bt_foreach_proc) (binding_entry, void *);
+struct binding_entry_s GTY(())
+{
+ binding_entry chain;
+ tree name;
+ tree type;
+};
+
+extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
+extern binding_entry binding_table_find (binding_table, tree);
+extern void cxx_remember_type_decls (binding_table);
/* Language-dependent contents of an identifier. */
-struct lang_identifier
+struct lang_identifier GTY(())
{
- struct c_common_identifier ignore;
- tree namespace_bindings;
- tree bindings;
+ struct c_common_identifier c_common;
+ cxx_binding *namespace_bindings;
+ cxx_binding *bindings;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -254,20 +292,21 @@ extern const short rid_to_yy[RID_MAX];
#define LANG_IDENTIFIER_CAST(NODE) \
((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE))
-struct lang_id2
+struct lang_id2 GTY(())
{
- tree label_value, implicit_decl;
+ tree label_value;
+ tree implicit_decl;
tree error_locus;
};
-typedef struct
+typedef struct flagged_type_tree_s GTY(())
{
tree t;
int new_type_flag;
tree lookups;
} flagged_type_tree;
-typedef struct
+typedef struct template_parm_index_s GTY(())
{
struct tree_common common;
HOST_WIDE_INT index;
@@ -276,41 +315,40 @@ typedef struct
tree decl;
} template_parm_index;
-typedef struct ptrmem_cst
+struct ptrmem_cst GTY(())
{
struct tree_common common;
/* This isn't used, but the middle-end expects all constants to have
this field. */
rtx rtl;
tree member;
-}* ptrmem_cst_t;
+};
+typedef struct ptrmem_cst * 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)
+#define LOCAL_BINDING_P(NODE) ((NODE)->is_local)
/* 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)
+#define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited)
/* 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*)CPLUS_BINDING_CHECK (NODE))->scope.scope)
+#define BINDING_SCOPE(NODE) ((NODE)->scope.scope)
/* Nonzero if NODE has BINDING_LEVEL, rather than BINDING_SCOPE. */
-#define BINDING_HAS_LEVEL_P(NODE) TREE_LANG_FLAG_2 (NODE)
+#define BINDING_HAS_LEVEL_P(NODE) ((NODE)->has_level)
/* This is the declaration bound to the name. Possible values:
variable, overloaded function, namespace, template, enumerator. */
-#define BINDING_VALUE(NODE) \
- (((struct tree_binding*)CPLUS_BINDING_CHECK (NODE))->value)
+#define BINDING_VALUE(NODE) ((NODE)->value)
/* If name is bound to a type, this is the type (struct, union, enum). */
-#define BINDING_TYPE(NODE) TREE_TYPE (NODE)
+#define BINDING_TYPE(NODE) ((NODE)->type)
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
namespace_binding ((NODE), global_namespace)
@@ -333,71 +371,71 @@ typedef struct ptrmem_cst
#define same_type_ignoring_top_level_qualifiers_p(TYPE1, TYPE2) \
same_type_p (TYPE_MAIN_VARIANT (TYPE1), TYPE_MAIN_VARIANT (TYPE2))
-/* Non-zero if we are presently building a statement tree, rather
+/* Nonzero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */
#define building_stmt_tree() (last_tree != NULL_TREE)
-/* Returns non-zero iff NODE is a declaration for the global function
+/* Returns nonzero iff NODE is a declaration for the global function
`main'. */
#define DECL_MAIN_P(NODE) \
(DECL_EXTERN_C_FUNCTION_P (NODE) \
&& DECL_NAME (NODE) != NULL_TREE \
&& MAIN_NAME_P (DECL_NAME (NODE)))
-
-struct tree_binding
-{
- struct tree_common common;
- union {
- tree scope;
- struct binding_level *level;
- } scope;
- tree value;
-};
-
-/* The overloaded FUNCTION_DECL. */
+/* The overloaded FUNCTION_DECL. */
#define OVL_FUNCTION(NODE) \
(((struct tree_overload*)OVERLOAD_CHECK (NODE))->function)
#define OVL_CHAIN(NODE) TREE_CHAIN (NODE)
-/* Polymorphic access to FUNCTION and CHAIN. */
+/* Polymorphic access to FUNCTION and CHAIN. */
#define OVL_CURRENT(NODE) \
((TREE_CODE (NODE) == OVERLOAD) ? OVL_FUNCTION (NODE) : (NODE))
#define OVL_NEXT(NODE) \
((TREE_CODE (NODE) == OVERLOAD) ? TREE_CHAIN (NODE) : NULL_TREE)
/* If set, this was imported in a using declaration.
This is not to confuse with being used somewhere, which
- is not important for this node. */
+ is not important for this node. */
#define OVL_USED(NODE) TREE_USED (NODE)
-struct tree_overload
+struct tree_overload GTY(())
{
struct tree_common common;
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. */
+/* Returns true iff NODE is a BASELINK. */
#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*)WRAPPER_CHECK (NODE))->u.ptr)
-#define WRAPPER_INT(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->u.i)
-
-struct tree_wrapper
+ (TREE_CODE (NODE) == BASELINK)
+/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */
+#define BASELINK_BINFO(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 0))
+/* The functions referred to by the BASELINK; either a FUNCTION_DECL,
+ a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */
+#define BASELINK_FUNCTIONS(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 1))
+/* The BINFO in which the search for the functions indicated by this baselink
+ began. This base is used to determine the accessibility of functions
+ selected by overload resolution. */
+#define BASELINK_ACCESS_BINFO(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 2))
+/* For a type-conversion operator, the BASELINK_OPTYPE indicates the type
+ to which the conversion should occur. This value is important if
+ the BASELINK_FUNCTIONS include a template conversion operator --
+ the BASELINK_OPTYPE can be used to determine what type the user
+ requested. */
+#define BASELINK_OPTYPE(NODE) \
+ (TREE_CHAIN (BASELINK_CHECK (NODE)))
+
+#define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)
+
+struct tree_wrapper GTY(())
{
struct tree_common common;
- union {
- void *ptr;
- int i;
- } u;
+ struct z_candidate *z_c;
};
#define SRCLOC_FILE(NODE) (((struct tree_srcloc*)SRCLOC_CHECK (NODE))->filename)
#define SRCLOC_LINE(NODE) (((struct tree_srcloc*)SRCLOC_CHECK (NODE))->linenum)
-struct tree_srcloc
+struct tree_srcloc GTY(())
{
struct tree_common common;
const char *filename;
@@ -411,8 +449,8 @@ struct tree_srcloc
#define IDENTIFIER_TEMPLATE(NODE) \
(LANG_IDENTIFIER_CAST (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
+/* The IDENTIFIER_BINDING is the innermost cxx_binding for the
+ identifier. It's PREVIOUS 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,
@@ -424,9 +462,7 @@ struct tree_srcloc
/* 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)
+ (IDENTIFIER_BINDING (NODE) ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) : 0)
/* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
class, and IDENTIFIER_CLASS_VALUE is the value binding. This is
@@ -439,7 +475,7 @@ struct tree_srcloc
/* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must
- be found through lookup. */
+ be found through lookup. */
#define IDENTIFIER_TYPE_VALUE(NODE) identifier_type_value (NODE)
#define REAL_IDENTIFIER_TYPE_VALUE(NODE) TREE_TYPE (NODE)
#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = (TYPE))
@@ -449,10 +485,10 @@ struct tree_srcloc
(LANG_IDENTIFIER_CAST (NODE)->x \
? LANG_IDENTIFIER_CAST (NODE)->x->NAME : 0)
-#define SET_LANG_ID(NODE, VALUE, NAME) \
- (LANG_IDENTIFIER_CAST (NODE)->x == 0 \
- ? LANG_IDENTIFIER_CAST (NODE)->x \
- = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
+#define SET_LANG_ID(NODE, VALUE, NAME) \
+ (LANG_IDENTIFIER_CAST (NODE)->x == 0 \
+ ? LANG_IDENTIFIER_CAST (NODE)->x \
+ = (struct lang_id2 *)ggc_alloc_cleared (sizeof (struct lang_id2)) : 0, \
LANG_IDENTIFIER_CAST (NODE)->x->NAME = (VALUE))
#define IDENTIFIER_LABEL_VALUE(NODE) \
@@ -494,11 +530,35 @@ struct tree_srcloc
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
(TREE_COMPLEXITY (EXP) = (int)(CODE))
-
-/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
- next exception handler. */
-extern tree exception_throw_decl;
+enum cp_tree_node_structure_enum {
+ TS_CP_COMMON,
+ TS_CP_GENERIC,
+ TS_CP_IDENTIFIER,
+ TS_CP_TPI,
+ TS_CP_PTRMEM,
+ TS_CP_OVERLOAD,
+ TS_CP_WRAPPER,
+ TS_CP_SRCLOC,
+ LAST_TS_CP_ENUM
+};
+
+/* The resulting tree type. */
+union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+ struct tree_common GTY ((tag ("TS_CP_COMMON"))) common;
+ union tree_node GTY ((tag ("TS_CP_GENERIC"),
+ desc ("tree_node_structure (&%h)"))) generic;
+ struct template_parm_index_s GTY ((tag ("TS_CP_TPI"))) tpi;
+ struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem;
+ struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
+ struct tree_wrapper GTY ((tag ("TS_CP_WRAPPER"))) wrapper;
+ struct tree_srcloc GTY ((tag ("TS_CP_SRCLOC"))) srcloc;
+ struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
+};
+
+
enum cp_tree_index
{
CPTI_JAVA_BYTE_TYPE,
@@ -582,10 +642,12 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
+ CPTI_KEYED_CLASSES,
+
CPTI_MAX
};
-extern tree cp_global_trees[CPTI_MAX];
+extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define java_byte_type_node cp_global_trees[CPTI_JAVA_BYTE_TYPE]
#define java_short_type_node cp_global_trees[CPTI_JAVA_SHORT_TYPE]
@@ -687,7 +749,7 @@ extern tree cp_global_trees[CPTI_MAX];
/* The node for `__null'. */
#define null_node cp_global_trees[CPTI_NULL]
-/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
+/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
#define jclass_node cp_global_trees[CPTI_JCLASS]
/* The declaration for `std::terminate'. */
@@ -712,11 +774,16 @@ extern tree cp_global_trees[CPTI_MAX];
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
+/* A TREE_LIST of the dynamic classes whose vtables may have to be
+ emitted in this translation unit. */
+
+#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
+
/* Global state. */
-struct saved_scope
+struct saved_scope GTY(())
{
- tree old_bindings;
+ cxx_saved_binding *old_bindings;
tree old_namespace;
tree decl_ns_list;
tree class_name;
@@ -739,8 +806,8 @@ struct saved_scope
struct stmt_tree_s x_stmt_tree;
- struct binding_level *class_bindings;
- struct binding_level *bindings;
+ struct cp_binding_level *class_bindings;
+ struct cp_binding_level *bindings;
struct saved_scope *prev;
};
@@ -749,7 +816,7 @@ struct saved_scope
#define current_namespace scope_chain->old_namespace
-/* The stack for namespaces of current declarations. */
+/* The stack for namespaces of current declarations. */
#define decl_namespace_list scope_chain->decl_ns_list
@@ -797,15 +864,15 @@ struct saved_scope
#define type_lookups scope_chain->lookups
-extern struct saved_scope *scope_chain;
+extern GTY(()) struct saved_scope *scope_chain;
struct unparsed_text;
/* Global state pertinent to the current function. */
-struct cp_language_function
+struct language_function GTY(())
{
- struct language_function base;
+ struct c_language_function base;
tree x_dtor_label;
tree x_current_class_ptr;
@@ -815,17 +882,19 @@ struct cp_language_function
tree x_vtt_parm;
tree x_return_value;
- tree *x_vcalls_possible_p;
-
int returns_value;
int returns_null;
int returns_abnormally;
int in_function_try_handler;
+ int in_base_initializer;
int x_expanding_p;
+ /* True if this function can throw an exception. */
+ bool can_throw : 1;
+
struct named_label_use_list *x_named_label_uses;
struct named_label_list *x_named_labels;
- struct binding_level *bindings;
+ struct cp_binding_level *bindings;
varray_type x_local_names;
const char *cannot_inline;
@@ -834,8 +903,7 @@ struct cp_language_function
/* The current C++-specific per-function global variables. */
-#define cp_function_chain \
- ((struct cp_language_function *) (cfun->language))
+#define cp_function_chain (cfun->language)
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
@@ -866,12 +934,6 @@ struct cp_language_function
#define current_vtt_parm cp_function_chain->x_vtt_parm
-/* In destructors, this is a pointer to a condition in an
- if-statement. If the pointed-to value is boolean_true_node, then
- there may be virtual function calls in this destructor. */
-
-#define current_vcalls_possible_p cp_function_chain->x_vcalls_possible_p
-
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -888,17 +950,20 @@ struct cp_language_function
#define current_function_returns_abnormally \
cp_function_chain->returns_abnormally
-/* Non-zero if we should generate RTL for functions that we process.
+/* Nonzero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */
#define expanding_p cp_function_chain->x_expanding_p
-/* Non-zero if we are in the semantic analysis phase for the current
+/* Nonzero if we are in the semantic analysis phase for the current
function. */
#define doing_semantic_analysis_p() (!expanding_p)
+/* Non-zero if we are processing a base initializer. Zero elsewhere. */
+#define in_base_initializer cp_function_chain->in_base_initializer
+
#define in_function_try_handler cp_function_chain->in_function_try_handler
/* Expression always returned from function, or error_mark_node
@@ -907,112 +972,18 @@ struct cp_language_function
#define current_function_return_value \
(cp_function_chain->x_return_value)
-extern tree global_namespace;
+extern GTY(()) tree global_namespace;
#define ansi_opname(CODE) \
(operator_name_info[(int) (CODE)].identifier)
#define ansi_assopname(CODE) \
(assignment_operator_name_info[(int) (CODE)].identifier)
-/* Nonzero means `$' can be in an identifier. */
-
-extern int dollars_in_ident;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-extern int flag_no_asm;
-
-/* Nonzero means don't recognize any extended keywords. */
-
-extern int flag_no_gnu_keywords;
-
-/* Nonzero means recognize the named operators from C++98. */
-
-extern int flag_operator_names;
-
-/* For environments where you can use GNU binutils (as, ld in particular). */
+/* True if NODE is an erroneous expression. */
-extern int flag_gnu_binutils;
-
-/* Nonzero means warn about things that will change when compiling
- with an ABI-compliant compiler. */
-
-extern int warn_abi;
-
-/* Nonzero means warn about implicit declarations. */
-
-extern int warn_implicit;
-
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-extern int warn_ctor_dtor_privacy;
-
-/* Nonzero means warn about deprecated conversion from string constant to
- `char *'. */
-
-extern int warn_write_strings;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-extern int warn_redundant_decls;
-
-/* Warn if initializer is not completely bracketed. */
-
-extern int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values. */
-
-extern int warn_sign_compare;
-
-/* Warn about testing equality of floating point numbers. */
-
-extern int warn_float_equal;
-
-/* Warn about a subscript that has type char. */
-
-extern int warn_char_subscripts;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-extern int warn_cast_qual;
-
-/* Nonzero means warn about non virtual destructors in classes that have
- virtual functions. */
-
-extern int warn_nonvdtor;
-
-/* Non-zero means warn when we convert a pointer to member function
- into a pointer to (void or function). */
-
-extern int warn_pmf2ptr;
-
-/* Nonzero means warn about violation of some Effective C++ style rules. */
-
-extern int warn_ecpp;
-
-/* Nonzero means warn where overload resolution chooses a promotion from
- unsigned to signed over a conversion to an unsigned of the same size. */
-
-extern int warn_sign_promo;
-
-/* Non-zero means warn when an old-style cast is used. */
-
-extern int warn_old_style_cast;
-
-/* Non-zero means warn when the compiler will reorder code. */
-
-extern int warn_reorder;
-
-/* Non-zero means warn about deprecated features. */
-
-extern int warn_deprecated;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-extern int flag_signed_bitfields;
+#define error_operand_p(NODE) \
+ ((NODE) == error_mark_node \
+ || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
/* INTERFACE_ONLY nonzero means that we are in an "interface"
section of the compiler. INTERFACE_UNKNOWN nonzero means
@@ -1020,52 +991,6 @@ extern int flag_signed_bitfields;
is zero and INTERFACE_ONLY is zero, it means that we are responsible
for exporting definitions that others might need. */
extern int interface_only, interface_unknown;
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-extern int flag_elide_constructors;
-
-/* Nonzero means enable obscure standard features and disable GNU
- extensions that might cause standard-compliant code to be
- miscompiled. */
-
-extern int flag_ansi;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-extern int flag_default_inline;
-
-/* Nonzero means generate separate instantiation control files and juggle
- them at link time. */
-extern int flag_use_repository;
-
-/* Nonzero if we want to issue diagnostics that the standard says are not
- required. */
-extern int flag_optional_diags;
-
-/* 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 means to implement standard semantics for exception
- specifications, calling unexpected if an exception is thrown that
- doesn't match the specification. Zero means to treat them as
- assertions and optimize accordingly, but not check them. */
-extern int flag_enforce_eh_specs;
-
-/* Nonzero if we want to obey access control semantics. */
-
-extern int flag_access_control;
-
-/* Nonzero if we want to check the return value of new and avoid calling
- constructors if it is a null pointer. */
-
-extern int flag_check_new;
-
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -1130,7 +1055,7 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* In a *_TYPE, nonzero means a built-in type. */
#define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6 (NODE)
-/* True if this a "Java" type, defined in 'extern "Java"'. */
+/* True if this a "Java" type, defined in 'extern "Java"'. */
#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3 (NODE)
/* Nonzero if this type is const-qualified. */
@@ -1173,19 +1098,36 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* Nonzero iff TYPE is derived from PARENT. Ignores accessibility and
ambiguity issues. */
#define DERIVED_FROM_P(PARENT, TYPE) \
- lookup_base ((TYPE), PARENT, ba_any, NULL)
+ (lookup_base ((TYPE), PARENT, ba_any, NULL) != NULL_TREE)
/* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
accessibility. */
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_ignore | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_ignore | ba_quiet, NULL) != NULL_TREE)
/* Nonzero iff TYPE is accessible in the current scope and uniquely
derived from PARENT. */
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_check | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_check | ba_quiet, NULL) != NULL_TREE)
/* Nonzero iff TYPE is publicly & uniquely derived from PARENT. */
#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL) \
+ != NULL_TREE)
+/* This is a few header flags for 'struct lang_type'. Actually,
+ all but the first are used only for lang_type_class; they
+ are put in this structure to save space. */
+struct lang_type_header GTY(())
+{
+ unsigned is_lang_type_class : 1;
+
+ unsigned has_type_conversion : 1;
+ unsigned has_init_ref : 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;
+};
+
/* 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
@@ -1199,19 +1141,12 @@ enum languages { lang_c, lang_cplusplus, lang_java };
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 lang_type_class GTY(())
{
+ struct lang_type_header h;
+
unsigned char align;
- unsigned has_type_conversion : 1;
- unsigned has_init_ref : 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_aggr : 1;
-
unsigned has_mutable : 1;
unsigned com_interface : 1;
unsigned non_pod_class : 1;
@@ -1227,7 +1162,6 @@ struct lang_type
unsigned has_arrow_overloaded : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
- unsigned needs_virtual_reinit : 1;
unsigned marks: 6;
unsigned vec_new_uses_cookie : 1;
@@ -1250,7 +1184,9 @@ struct lang_type
unsigned is_partial_instantiation : 1;
unsigned java_interface : 1;
+ unsigned anon_aggr : 1;
unsigned non_zero_init : 1;
+ unsigned empty_p : 1;
unsigned contains_empty_class_p : 1;
/* When adding a flag here, consider whether or not it ought to
@@ -1260,31 +1196,69 @@ struct lang_type
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 6;
-
- int vsize;
+ unsigned dummy : 5;
tree primary_base;
tree vfields;
+ tree vcall_indices;
+ tree vtables;
tree typeinfo_var;
tree vbases;
- tree tags;
- tree size;
- tree size_unit;
+ binding_table nested_udts;
+ tree as_base;
tree pure_virtuals;
tree friend_classes;
- tree rtti;
tree methods;
+ tree key_method;
+ tree decl_list;
tree template_info;
tree befriending_classes;
};
+struct lang_type_ptrmem GTY(())
+{
+ struct lang_type_header h;
+ tree record;
+};
+
+struct lang_type GTY(())
+{
+ union lang_type_u
+ {
+ struct lang_type_header GTY((tag ("2"))) h;
+ struct lang_type_class GTY((tag ("1"))) c;
+ struct lang_type_ptrmem GTY((tag ("0"))) ptrmem;
+ } GTY((desc ("%h.h.is_lang_type_class"))) u;
+};
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+#define LANG_TYPE_CLASS_CHECK(NODE) \
+({ struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE); \
+ if (! lt->u.h.is_lang_type_class) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.c; })
+
+#define LANG_TYPE_PTRMEM_CHECK(NODE) \
+({ struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE); \
+ if (lt->u.h.is_lang_type_class) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.ptrmem; })
+
+#else
+
+#define LANG_TYPE_CLASS_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.c)
+#define LANG_TYPE_PTRMEM_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.ptrmem)
+
+#endif /* ENABLE_TREE_CHECKING */
+
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
2=explicit template specialization
3=explicit template instantiation */
-#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC (NODE)->use_template)
+#define CLASSTYPE_USE_TEMPLATE(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
/* Fields used for storing information before the class is defined.
After the class is defined, these fields hold other information. */
@@ -1293,79 +1267,93 @@ struct lang_type
#define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE)
/* Nonzero for _CLASSTYPE means that operator delete is defined. */
-#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC (NODE)->gets_delete)
+#define TYPE_GETS_DELETE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->gets_delete)
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
/* Nonzero if `new NODE[x]' should cause the allocation of extra
storage to indicate how many array elements are in use. */
#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
(CLASS_TYPE_P (NODE) \
- && TYPE_LANG_SPECIFIC (NODE)->vec_new_uses_cookie)
+ && LANG_TYPE_CLASS_CHECK (NODE)->vec_new_uses_cookie)
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
#define TYPE_HAS_CONVERSION(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_type_conversion)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion)
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
-#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_assign_ref)
+#define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref)
#define TYPE_HAS_CONST_ASSIGN_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_const_assign_ref)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_const_assign_ref)
/* Nonzero means that this _CLASSTYPE node has an X(X&) constructor. */
-#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_init_ref)
+#define TYPE_HAS_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->h.has_init_ref)
#define TYPE_HAS_CONST_INIT_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_const_init_ref)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_const_init_ref)
/* Nonzero if this class defines an overloaded operator new. (An
operator new [] doesn't count.) */
#define TYPE_HAS_NEW_OPERATOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_new)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_new)
/* Nonzero if this class defines an overloaded operator new[]. */
#define TYPE_HAS_ARRAY_NEW_OPERATOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_array_new)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_array_new)
/* Nonzero means that this type is being defined. I.e., the left brace
starting the definition of this type has been seen. */
-#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->being_defined)
+#define TYPE_BEING_DEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->being_defined)
/* Nonzero means that this type has been redefined. In this case, if
convenient, don't reprocess any methods that appear in its redefinition. */
-#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->redefined)
-
-/* The is the basetype that contains NODE's rtti. */
-#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC (NODE)->rtti)
+#define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_call_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
/* Nonzero means that this _CLASSTYPE node overloads operator[]. */
#define TYPE_OVERLOADS_ARRAY_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_array_ref_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_array_ref_overloaded)
/* Nonzero means that this _CLASSTYPE node overloads operator->. */
#define TYPE_OVERLOADS_ARROW(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_arrow_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_arrow_overloaded)
/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
multiple inheritance. If this is 0 for the root of a type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_MULTIPLE_INHERITANCE(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->uses_multiple_inheritance)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.uses_multiple_inheritance)
/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
virtual base classes. If this is 0 for the root of a type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3 (NODE))
+/* The member function with which the vtable will be emitted:
+ the first noninline non-pure-virtual member function. NULL_TREE
+ if there is no key function or if this is a class template */
+#define CLASSTYPE_KEY_METHOD(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->key_method)
+
/* 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.
- Any conversion operators are next, 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)
+ All template conversion operators to innermost template dependent
+ types are overloaded on the next slot, if they exist. Note, the
+ names for these functions will not all be the same. The
+ non-template conversion operators & templated conversions to
+ non-innermost template types are next, followed by ordinary member
+ functions. There may be empty entries at the end of the vector.
+ The conversion operators are unsorted. The ordinary member
+ functions are sorted, once the class is complete. */
+#define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods)
+
+/* For class templates, this is a TREE_LIST of all member data,
+ functions, types, and friends in the order of declaration.
+ The TREE_PURPOSE of each TREE_LIST is NULL_TREE for a friend,
+ and the RECORD_TYPE for the class template otherwise. */
+#define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list)
/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
#define CLASSTYPE_CONSTRUCTOR_SLOT 0
@@ -1391,19 +1379,19 @@ struct lang_type
/* Get the value of the Nth mark bit. */
#define CLASSTYPE_MARKED_N(NODE, N) \
- (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->marks \
+ (((CLASS_TYPE_P (NODE) ? LANG_TYPE_CLASS_CHECK (NODE)->marks \
: ((unsigned) TYPE_ALIAS_SET (NODE))) & (1 << (N))) != 0)
/* Set the Nth mark bit. */
#define SET_CLASSTYPE_MARKED_N(NODE, N) \
(CLASS_TYPE_P (NODE) \
- ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks |= (1 << (N))) \
+ ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks |= (1 << (N))) \
: (void) (TYPE_ALIAS_SET (NODE) |= (1 << (N))))
/* Clear the Nth mark bit. */
#define CLEAR_CLASSTYPE_MARKED_N(NODE, N) \
(CLASS_TYPE_P (NODE) \
- ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks &= ~(1 << (N))) \
+ ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks &= ~(1 << (N))) \
: (void) (TYPE_ALIAS_SET (NODE) &= ~(1 << (N))))
/* Get the value of the mark bits. */
@@ -1428,11 +1416,12 @@ struct lang_type
#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
- of the type; the TREE_VALUE is the type itself. This list includes
+/* A binding_table of the nested tag-types (class, struct, union, or enum)
+ found within this class. The ENTRY->name of each node is the name
+ of the type; the ENTRY->type is the type itself. This table includes
nested member class templates. */
-#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC (NODE)->tags)
+#define CLASSTYPE_NESTED_UDTS(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->nested_udts)
/* Nonzero if NODE has a primary base class, i.e., a base class with
which it shares the virtual function table pointer. */
@@ -1443,11 +1432,7 @@ struct lang_type
the base class which contains the virtual function table pointer
for this class. */
#define CLASSTYPE_PRIMARY_BINFO(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->primary_base)
-
-/* The number of virtual functions present in this class' virtual
- function table. */
-#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->vsize)
+ (LANG_TYPE_CLASS_CHECK (NODE)->primary_base)
/* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in a post-order depth-first left-to-right
@@ -1457,7 +1442,7 @@ struct lang_type
list are all "real"; they are the same BINFOs that will be
encountered when using dfs_unmarked_real_bases_queue_p and related
functions. */
-#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC (NODE)->vbases)
+#define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases)
/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
binfo_for_vbase. C is the most derived class for the hierarchy
@@ -1471,95 +1456,98 @@ struct lang_type
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
+/* The type corresponding to NODE when NODE is used as a base class,
+ i.e., NODE without virtual base classes. */
+
+#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
+
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
-#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->size)
-#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC (NODE)->size_unit)
-#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->align)
-#define CLASSTYPE_USER_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->user_align)
+#define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE))
/* The alignment of NODE, without its virtual bases, in bytes. */
#define CLASSTYPE_ALIGN_UNIT(NODE) \
(CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
/* True if this a Java interface type, declared with
- '__attribute__ ((java_interface))'. */
-#define TYPE_JAVA_INTERFACE(NODE) (TYPE_LANG_SPECIFIC (NODE)->java_interface)
+ '__attribute__ ((java_interface))'. */
+#define TYPE_JAVA_INTERFACE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->java_interface)
/* 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. */
-#define CLASSTYPE_PURE_VIRTUALS(NODE) (TYPE_LANG_SPECIFIC (NODE)->pure_virtuals)
+#define CLASSTYPE_PURE_VIRTUALS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals)
/* Nonzero means that this aggr type has been `closed' by a semicolon. */
-#define CLASSTYPE_GOT_SEMICOLON(NODE) (TYPE_LANG_SPECIFIC (NODE)->got_semicolon)
-
-/* Nonzero means that the main virtual function table pointer needs to be
- set because base constructors have placed the wrong value there.
- If this is zero, it means that they placed the right value there,
- and there is no need to change it. */
-#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->needs_virtual_reinit)
+#define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_default_ctor)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
/* Nonzero means that this type contains a mutable member */
-#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_mutable)
+#define CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_mutable)
#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
/* Nonzero means that this class type is a non-POD class. */
-#define CLASSTYPE_NON_POD_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_pod_class)
+#define CLASSTYPE_NON_POD_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
/* Nonzero means that this class contains pod types whose default
initialization is not a zero initialization (namely, pointers to
data members). */
-#define CLASSTYPE_NON_ZERO_INIT_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_zero_init)
+#define CLASSTYPE_NON_ZERO_INIT_P(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_zero_init)
+
+/* Nonzero if this class is "empty" in the sense of the C++ ABI. */
+#define CLASSTYPE_EMPTY_P(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->empty_p)
/* Nonzero if this class is "nearly empty", i.e., contains only a
virtual function table pointer. */
#define CLASSTYPE_NEARLY_EMPTY_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->nearly_empty_p)
+ (LANG_TYPE_CLASS_CHECK (NODE)->nearly_empty_p)
/* Nonzero if this class contains an empty subobject. */
#define CLASSTYPE_CONTAINS_EMPTY_CLASS_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->contains_empty_class_p)
+ (LANG_TYPE_CLASS_CHECK (NODE)->contains_empty_class_p)
/* 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)
+ (LANG_TYPE_CLASS_CHECK (NODE)->friend_classes)
/* A list of the classes which grant friendship to this class. */
#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
+ (LANG_TYPE_CLASS_CHECK (NODE)->befriending_classes)
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->declared_class)
+ (LANG_TYPE_CLASS_CHECK (NODE)->declared_class)
/* Nonzero if this class has const members
which have no specified initialization. */
#define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) \
(TYPE_LANG_SPECIFIC (NODE) \
- ? TYPE_LANG_SPECIFIC (NODE)->const_needs_init : 0)
+ ? LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init : 0)
#define SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE)->const_needs_init = (VALUE))
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init = (VALUE))
/* Nonzero if this class has ref members
which have no specified initialization. */
#define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE) \
(TYPE_LANG_SPECIFIC (NODE) \
- ? TYPE_LANG_SPECIFIC (NODE)->ref_needs_init : 0)
+ ? LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init : 0)
#define SET_CLASSTYPE_REF_FIELDS_NEED_INIT(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE)->ref_needs_init = (VALUE))
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init = (VALUE))
/* Nonzero if this class is included from a header file which employs
`#pragma interface', and it is not included in its implementation file. */
#define CLASSTYPE_INTERFACE_ONLY(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_only)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_only)
/* True if we have already determined whether or not vtables, VTTs,
typeinfo, and other similar per-class data should be emitted in
@@ -1567,21 +1555,21 @@ struct lang_type
these items should be emitted; it only indicates that we know one
way or the other. */
#define CLASSTYPE_INTERFACE_KNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown == 0)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown == 0)
/* The opposite of CLASSTYPE_INTERFANCE_KNOWN. */
#define CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown)
#define SET_CLASSTYPE_INTERFACE_UNKNOWN_X(NODE,X) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = !!(X))
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = !!(X))
#define SET_CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 1)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 1)
#define SET_CLASSTYPE_INTERFACE_KNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 0)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 0)
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->debug_requested)
+ (LANG_TYPE_CLASS_CHECK (NODE)->debug_requested)
/* Additional macros for inheritance information. */
@@ -1687,45 +1675,60 @@ struct lang_type
/* Used by various search routines. */
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
+/* A TREE_LIST of the vcall indices associated with the class NODE.
+ The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual
+ function. The TREE_VALUE is the index into the virtual table where
+ the vcall offset for that function is stored, when NODE is a
+ virtual base. */
+#define CLASSTYPE_VCALL_INDICES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices)
+
+/* The various vtables for the class NODE. The primary vtable will be
+ first, followed by the construction vtables and VTT, if any. */
+#define CLASSTYPE_VTABLES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vtables)
+
/* The std::type_info variable representing this class, or NULL if no
such variable has been created. This field is only set for the
TYPE_MAIN_VARIANT of the class. */
#define CLASSTYPE_TYPEINFO_VAR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->typeinfo_var)
+ (LANG_TYPE_CLASS_CHECK (NODE)->typeinfo_var)
/* Accessor macros for the vfield slots in structures. */
-/* The virtual function pointer fields that this type contains. For a
- vfield defined just for this class, or from a primary base, the
- TREE_PURPOSE is NULL. Otherwise, the TREE_PURPOSE is the BINFO for
- the class containing the vfield. The TREE_VALUE is the class where
- the vfield was first defined. */
-#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC (NODE)->vfields)
-
-/* Get the assoc info that caused this vfield to exist. */
+/* List of virtual table fields that this type contains (both the primary
+ and secondaries). The TREE_VALUE is the class type where the vtable
+ field was introduced. For a vtable field inherited from the primary
+ base, or introduced by this class, the TREE_PURPOSE is NULL. For
+ other vtable fields (those from non-primary bases), the
+ TREE_PURPOSE is the BINFO of the base through which the vtable was
+ inherited. */
+#define CLASSTYPE_VFIELDS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vfields)
+
+/* Get the BINFO that introduced this vtable into the hierarchy (will
+ be NULL for those created at this level, or from a primary
+ hierarchy). */
#define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
-/* Get that same information as a _TYPE. */
+/* Get the TYPE that introduced this vtable into the hierarchy (always
+ non-NULL). */
#define VF_BASETYPE_VALUE(NODE) TREE_VALUE (NODE)
-/* Get the value of the top-most type dominating the non-`normal' vfields. */
-#define VF_DERIVED_VALUE(NODE) \
- (VF_BINFO_VALUE (NODE) ? BINFO_TYPE (VF_BINFO_VALUE (NODE)) : NULL_TREE)
+/* Accessor macros for the BINFO_VIRTUALS list. */
/* The number of bytes by which to adjust the `this' pointer when
- calling this virtual function. */
+ calling this virtual function. Subtract this value from the this
+ pointer. Always non-NULL, might be constant zero though. */
#define BV_DELTA(NODE) (TREE_PURPOSE (NODE))
/* If non-NULL, the vtable index at which to find the vcall offset
- when calling this virtual function. */
+ when calling this virtual function. Add the value at that vtable
+ index to the this pointer. */
#define BV_VCALL_INDEX(NODE) (TREE_TYPE (NODE))
/* The function to call. */
#define BV_FN(NODE) (TREE_VALUE (NODE))
-/* Nonzero if we should use a virtual thunk for this entry. */
-#define BV_USE_VCALL_INDEX_P(NODE) \
- (TREE_LANG_FLAG_0 (NODE))
/* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */
@@ -1760,7 +1763,7 @@ struct lang_type
|| TREE_CODE (NODE) == FIELD_DECL \
|| TREE_CODE (NODE) == USING_DECL))
-struct lang_decl_flags
+struct lang_decl_flags GTY(())
{
struct c_lang_decl base;
@@ -1781,66 +1784,93 @@ struct lang_decl_flags
unsigned not_really_extern : 1;
unsigned needs_final_overrider : 1;
unsigned initialized_in_class : 1;
- unsigned pending_inline_p : 1;
+ unsigned assignment_operator_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
- unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
- /* Four unused bits. */
+ unsigned template_conv_p : 1;
+ unsigned u1sel : 1;
+ unsigned u2sel : 1;
+ unsigned can_be_full : 1;
+ unsigned unused : 1; /* One unused bit. */
- union {
+ union lang_decl_u {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
is DECL_TEMPLATE_INFO. */
- tree template_info;
+ tree GTY ((tag ("0"))) template_info;
/* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
- struct binding_level *level;
- } u;
+ struct cp_binding_level * GTY ((tag ("1"))) level;
+ } GTY ((desc ("%1.u1sel"))) u;
- union {
+ union lang_decl_u2 {
/* This is DECL_ACCESS. */
- tree access;
+ tree GTY ((tag ("0"))) access;
/* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */
int discriminator;
- /* In a namespace-scope FUNCTION_DECL, this is
- GLOBAL_INIT_PRIORITY. */
- int init_priority;
-
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
THUNK_VCALL_OFFSET. */
- tree vcall_offset;
- } u2;
+ tree GTY((tag ("2"))) vcall_offset;
+ } GTY ((desc ("%1.u2sel"))) u2;
};
-struct lang_decl
+struct lang_decl GTY(())
{
struct lang_decl_flags decl_flags;
- tree befriending_classes;
+ union lang_decl_u4
+ {
+ struct full_lang_decl
+ {
+ tree befriending_classes;
+
+ /* For a non-virtual FUNCTION_DECL, this is
+ DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which
+ DECL_THUNK_P does not hold, this is DECL_THUNKS. */
+ tree context;
+
+ /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
+ tree cloned_function;
+
+ /* In a FUNCTION_DECL for which THUNK_P holds, this is
+ THUNK_DELTA. */
+ HOST_WIDE_INT delta;
+
+ /* In an overloaded operator, this is the value of
+ DECL_OVERLOADED_OPERATOR_P. */
+ enum tree_code operator_code;
+
+ unsigned u3sel : 1;
+ unsigned pending_inline_p : 1;
+
+ union lang_decl_u3
+ {
+ tree GTY ((tag ("0"))) sorted_fields;
+ struct unparsed_text * GTY ((tag ("2"))) pending_inline_info;
+ struct language_function * GTY ((tag ("1")))
+ saved_language_function;
+ } GTY ((desc ("%1.u3sel + %1.pending_inline_p"))) u;
+ } GTY ((tag ("1"))) f;
+ } GTY ((desc ("%1.decl_flags.can_be_full"))) u;
+};
- /* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT. For a
- non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT. */
- tree context;
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
- /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
- tree cloned_function;
+#define LANG_DECL_U2_CHECK(NODE, TF) \
+({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (lt->decl_flags.u2sel != TF) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->decl_flags.u2; })
- union
- {
- tree sorted_fields;
- struct unparsed_text *pending_inline_info;
- struct cp_language_function *saved_language_function;
- } u;
-
- union {
- /* In an overloaded operator, this is the value of
- DECL_OVERLOADED_OPERATOR_P. */
- enum tree_code operator_code;
- } u2;
-};
+#else
+
+#define LANG_DECL_U2_CHECK(NODE, TF) \
+ (&DECL_LANG_SPECIFIC (NODE)->decl_flags.u2)
+
+#endif /* ENABLE_TREE_CHECKING */
#define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK (NODE)->identifier.id.str)
@@ -1857,7 +1887,7 @@ struct lang_decl
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \
|| (flag_syntax_only && TREE_USED (DECL)))
-/* Non-zero iff DECL is memory-based. The DECL_RTL of
+/* Nonzero iff DECL is memory-based. The DECL_RTL of
certain const variables might be a CONST_INT, or a REG
in some cases. We cannot use `memory_operand' as a test
here because on most RISC machines, a variable's address
@@ -1949,7 +1979,7 @@ struct lang_decl
/* If DECL_CLONED_FUNCTION_P holds, this is the function that was
cloned. */
#define DECL_CLONED_FUNCTION(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->cloned_function)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
/* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */
#define DECL_DISCRIMINATOR_P(NODE) \
@@ -1957,27 +1987,37 @@ struct lang_decl
&& DECL_FUNCTION_SCOPE_P (NODE))
/* Discriminator for name mangling. */
-#define DECL_DISCRIMINATOR(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.discriminator)
+#define DECL_DISCRIMINATOR(NODE) (LANG_DECL_U2_CHECK (NODE, 1)->discriminator)
-/* Non-zero if the VTT parm has been added to NODE. */
+/* Nonzero if the VTT parm has been added to NODE. */
#define DECL_HAS_VTT_PARM_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.has_vtt_parm_p)
-/* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
+/* Nonzero if NODE is a FUNCTION_DECL for which a VTT parameter is
required. */
#define DECL_NEEDS_VTT_PARM_P(NODE) \
(TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (NODE)) \
&& (DECL_BASE_CONSTRUCTOR_P (NODE) \
|| DECL_BASE_DESTRUCTOR_P (NODE)))
-/* Non-zero if NODE is a user-defined conversion operator. */
+/* Nonzero if NODE is a user-defined conversion operator. */
#define DECL_CONV_FN_P(NODE) \
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
+/* If FN is a conversion operator, the type to which it converts.
+ Otherwise, NULL_TREE. */
+#define DECL_CONV_FN_TYPE(FN) \
+ (DECL_CONV_FN_P (FN) ? TREE_TYPE (DECL_NAME (FN)) : NULL_TREE)
+
+/* Nonzero if NODE, which is a TEMPLATE_DECL, is a template
+ conversion operator to a type dependent on the innermost template
+ args. */
+#define DECL_TEMPLATE_CONV_FN_P(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->decl_flags.template_conv_p)
+
/* Set the overloaded operator code for NODE to CODE. */
#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
- (DECL_LANG_SPECIFIC (NODE)->u2.operator_code = (CODE))
+ (DECL_LANG_SPECIFIC (NODE)->u.f.operator_code = (CODE))
/* If NODE is an overloaded operator, then this returns the TREE_CODE
associcated with the overloaded operator.
@@ -1988,9 +2028,9 @@ struct lang_decl
to test whether or not NODE is an overloaded operator. */
#define DECL_OVERLOADED_OPERATOR_P(NODE) \
(IDENTIFIER_OPNAME_P (DECL_NAME (NODE)) \
- ? DECL_LANG_SPECIFIC (NODE)->u2.operator_code : ERROR_MARK)
+ ? DECL_LANG_SPECIFIC (NODE)->u.f.operator_code : ERROR_MARK)
-/* Non-zero if NODE is an assignment operator. */
+/* Nonzero if NODE is an assignment operator. */
#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.assignment_operator_p)
@@ -2011,8 +2051,14 @@ struct lang_decl
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
+/* Nonzero for a VAR_DECL means that the variable's initialization has
+ been processed. */
+#define DECL_INITIALIZED_P(NODE) \
+ (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
+
/* Nonzero if the DECL was initialized in the class definition itself,
- rather than outside the class. */
+ rather than outside the class. This is used for both static member
+ VAR_DECLS, and FUNTION_DECLS that are defined in the class. */
#define DECL_INITIALIZED_IN_CLASS_P(DECL) \
(DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class)
@@ -2023,7 +2069,7 @@ struct lang_decl
/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */
#define DECL_BEFRIENDING_CLASSES(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->befriending_classes)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
/* Nonzero for FUNCTION_DECL means that this decl is a static
member function. */
@@ -2079,6 +2125,11 @@ struct lang_decl
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider)
+/* The thunks associated with NODE, a FUNCTION_DECL that is not itself
+ a thunk. */
+#define DECL_THUNKS(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->u.f.context)
+
/* Nonzero if NODE is a thunk, rather than an ordinary function. */
#define DECL_THUNK_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL \
@@ -2097,8 +2148,9 @@ struct lang_decl
(DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE))
/* Set DECL_THUNK_P for node. */
-#define SET_DECL_THUNK_P(NODE) \
- (DECL_LANG_FLAG_7 (NODE) = 1)
+#define SET_DECL_THUNK_P(NODE) \
+ (DECL_LANG_FLAG_7 (NODE) = 1, \
+ DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1)
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
@@ -2106,7 +2158,7 @@ struct lang_decl
(TREE_LANG_FLAG_0 (NODE))
/* The _TYPE context in which this _DECL appears. This field holds the
- class where a virtual function instance is actually defined. */
+ class where a virtual function instance is actually defined. */
#define DECL_CLASS_CONTEXT(NODE) \
(DECL_CLASS_SCOPE_P (NODE) ? DECL_CONTEXT (NODE) : NULL_TREE)
@@ -2118,23 +2170,18 @@ struct lang_decl
the DECL_FRIEND_CONTEXT for `f' will be `S'. */
#define DECL_FRIEND_CONTEXT(NODE) \
((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \
- ? DECL_LANG_SPECIFIC (NODE)->context \
+ ? DECL_LANG_SPECIFIC (NODE)->u.f.context \
: NULL_TREE)
/* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT. */
#define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
- (DECL_LANG_SPECIFIC (NODE)->context = (CONTEXT))
+ (DECL_LANG_SPECIFIC (NODE)->u.f.context = (CONTEXT))
-/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
+/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
#define CP_DECL_CONTEXT(NODE) \
(DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
-/* 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_LANG_SPECIFIC (NODE)->context)
-
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
(!DECL_TEMPLATE_PARM_P (NODE) \
@@ -2155,11 +2202,11 @@ struct lang_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. */
+ that is the common ancestor. */
#define DECL_NAMESPACE_USING(NODE) DECL_VINDEX (NAMESPACE_DECL_CHECK (NODE))
/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users
- of a namespace, to record the transitive closure of using namespace. */
+ of a namespace, to record the transitive closure of using namespace. */
#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NAMESPACE_DECL_CHECK (NODE))
/* In a NAMESPACE_DECL, points to the original namespace if this is
@@ -2169,7 +2216,7 @@ struct lang_decl
#define ORIGINAL_NAMESPACE(NODE) \
(DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
-/* Non-zero if NODE is the std namespace. */
+/* Nonzero if NODE is the std namespace. */
#define DECL_NAMESPACE_STD_P(NODE) \
(TREE_CODE (NODE) == NAMESPACE_DECL \
&& CP_DECL_CONTEXT (NODE) == global_namespace \
@@ -2192,17 +2239,17 @@ struct lang_decl
the class definition. We have saved away the text of the function,
but have not yet processed it. */
#define DECL_PENDING_INLINE_P(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.pending_inline_p)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.pending_inline_p)
/* If DECL_PENDING_INLINE_P holds, this is the saved text of the
function. */
#define DECL_PENDING_INLINE_INFO(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->u.pending_inline_info)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.u.pending_inline_info)
-/* For a TYPE_DECL: if this function has many fields, we'll sort them
- and put them into a TREE_VEC. */
+/* For a TYPE_DECL: if this structure has many fields, we'll sort them
+ and put them into a TREE_VEC. */
#define DECL_SORTED_FIELDS(NODE) \
- (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.sorted_fields)
+ (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.f.u.sorted_fields)
/* True if on the deferred_fns (see decl2.c) list. */
#define DECL_DEFERRED_FN(DECL) \
@@ -2214,9 +2261,15 @@ struct lang_decl
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info)
+/* For a VAR_DECL, indicates that the variable has been processed.
+ This flag is set and unset throughout the code; it is always
+ used for a temporary purpose. */
+#define DECL_VAR_MARKED_P(NODE) \
+ (DECL_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)))
+
/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) \
- (TYPE_LANG_SPECIFIC (RECORD_OR_UNION_TYPE_CHECK (NODE))->template_info)
+ (LANG_TYPE_CLASS_CHECK (RECORD_OR_UNION_TYPE_CHECK (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
@@ -2226,7 +2279,7 @@ struct lang_decl
/* Template information for a template template parameter. */
#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \
- (TYPE_LANG_SPECIFIC (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
+ (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
->template_info)
/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
@@ -2262,7 +2315,7 @@ struct lang_decl
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,
+/* Nonzero 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 \
@@ -2279,7 +2332,7 @@ struct lang_decl
#define TMPL_ARGS_DEPTH(NODE) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
-/* The LEVELth level of the template ARGS. The outermost level of of
+/* The LEVELth level of the template ARGS. The outermost level of
args is level 1, not level 0. */
#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
@@ -2364,8 +2417,9 @@ struct lang_decl
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
/* In a FUNCTION_DECL, the saved language-specific per-function data. */
-#define DECL_SAVED_FUNCTION_DATA(NODE) \
- (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->u.saved_language_function)
+#define DECL_SAVED_FUNCTION_DATA(NODE) \
+ (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
+ ->u.f.u.saved_language_function)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
@@ -2423,8 +2477,6 @@ struct lang_decl
(TYPE_POLYMORPHIC_P (NODE) \
|| TYPE_USES_VIRTUAL_BASECLASSES (NODE))
-extern int flag_new_for_scope;
-
/* This flag is true of a local VAR_DECL if it was declared in a for
statement, but we are no longer in the scope of the for. */
#define DECL_DEAD_FOR_LOCAL(NODE) DECL_LANG_FLAG_7 (VAR_DECL_CHECK (NODE))
@@ -2446,7 +2498,7 @@ 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)
-/* Returns non-zero if DECL has external linkage, as specified by the
+/* Returns nonzero if DECL has external linkage, as specified by the
language standard. (This predicate may hold even when the
corresponding entity is not actually given external linkage in the
object file; see decl_linkage for details.) */
@@ -2467,6 +2519,10 @@ extern int flag_new_for_scope;
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| TREE_CODE (TYPE) == INTEGER_TYPE)
+/* Returns true if TYPE is an integral or enumeration name. */
+#define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \
+ (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == ENUMERAL_TYPE)
+
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
@@ -2474,8 +2530,29 @@ extern int flag_new_for_scope;
#define ARITHMETIC_TYPE_P(TYPE) \
(CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE)
-/* Nonzero for _TYPE means that the _TYPE defines
- at least one constructor. */
+/* [basic.types]
+
+ Arithmetic types, enumeration types, pointer types, and
+ pointer-to-member types, are collectively called scalar types. */
+#define SCALAR_TYPE_P(TYPE) \
+ (ARITHMETIC_TYPE_P (TYPE) \
+ || TREE_CODE (TYPE) == ENUMERAL_TYPE \
+ || TYPE_PTR_P (TYPE) \
+ || TYPE_PTRMEM_P (TYPE) \
+ || TYPE_PTRMEMFUNC_P (TYPE))
+
+/* [dcl.init.aggr]
+
+ An aggregate is an array or a class with no user-declared
+ constructors, no private or protected non-static data members, no
+ base classes, and no virtual functions. */
+#define CP_AGGREGATE_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ || (CLASS_TYPE_P (TYPE) \
+ && !CLASSTYPE_NON_AGGREGATE (TYPE)))
+
+/* Nonzero for a class type means that the class type has a
+ user-declared constructor. */
#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
/* When appearing in an INDIRECT_REF, it means that the tree structure
@@ -2504,15 +2581,15 @@ extern int flag_new_for_scope;
/* Nonzero means that an object of this type can not be initialized using
an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->non_aggregate)
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
#define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if there is a user-defined X::op=(x&) for this class. */
-#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_real_assign_ref)
-#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_assign_ref)
-#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_abstract_assign_ref)
-#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_init_ref)
+#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_real_assign_ref)
+#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
+#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_abstract_assign_ref)
+#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
@@ -2571,7 +2648,7 @@ extern int flag_new_for_scope;
&& TYPE_PTRMEMFUNC_FLAG (NODE))
#define TYPE_PTRMEMFUNC_FLAG(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->ptrmemfunc_flag)
+ (LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag)
/* Indicates when overload resolution may resolve to a pointer to
member function. [expr.unary.op]/3 */
@@ -2590,9 +2667,17 @@ extern int flag_new_for_scope;
/* These are use to manipulate the canonical RECORD_TYPE from the
hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */
#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) \
- ((tree)TYPE_LANG_SPECIFIC (NODE))
-#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE) = ((struct lang_type *)(void*)(VALUE)))
+ (TYPE_LANG_SPECIFIC (NODE) ? LANG_TYPE_PTRMEM_CHECK (NODE)->record : NULL)
+#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) \
+ do { \
+ if (TYPE_LANG_SPECIFIC (NODE) == NULL) \
+ { \
+ TYPE_LANG_SPECIFIC (NODE) = \
+ ggc_alloc_cleared (sizeof (struct lang_type_ptrmem)); \
+ TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0; \
+ } \
+ TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.record = (VALUE); \
+ } while (0)
/* Returns the pfn field from a TYPE_PTRMEMFUNC_P. */
#define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
@@ -2637,9 +2722,9 @@ extern int flag_new_for_scope;
flag for this because "A union for which objects or pointers are
declared is not an anonymous union" [class.union]. */
#define ANON_AGGR_TYPE_P(NODE) \
- (CLASS_TYPE_P (NODE) && TYPE_LANG_SPECIFIC (NODE)->anon_aggr)
+ (CLASS_TYPE_P (NODE) && LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr)
#define SET_ANON_AGGR_TYPE_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->anon_aggr = 1)
+ (LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr = 1)
/* Nonzero if TYPE is an anonymous union type. */
#define ANON_UNION_TYPE_P(NODE) \
@@ -2649,7 +2734,7 @@ extern int flag_new_for_scope;
/* Define fields and accessors for nodes representing declared names. */
-#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->was_anonymous)
+#define TYPE_WAS_ANONYMOUS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->was_anonymous)
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
@@ -2674,7 +2759,7 @@ extern int flag_new_for_scope;
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.u2.access)
+#define DECL_ACCESS(NODE) (LANG_DECL_U2_CHECK (NODE, 0)->access)
/* Nonzero if the FUNCTION_DECL is a global constructor. */
#define DECL_GLOBAL_CTOR_P(NODE) \
@@ -2684,13 +2769,6 @@ extern int flag_new_for_scope;
#define DECL_GLOBAL_DTOR_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.global_dtor_p)
-/* If DECL_GLOBAL_CTOR_P or DECL_GLOBAL_DTOR_P holds, this macro
- returns the initialization priority for the function. Constructors
- with lower numbers should be run first. Destructors should be run
- in the reverse order of constructors. */
-#define GLOBAL_INIT_PRIORITY(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.init_priority)
-
/* Accessor macros for C++ template decl nodes. */
/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
@@ -2819,7 +2897,7 @@ extern int flag_new_for_scope;
#define DECL_PRIMARY_TEMPLATE(NODE) \
(TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)))
-/* Returns non-zero if NODE is a primary template. */
+/* Returns nonzero if NODE is a primary template. */
#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
@@ -2858,7 +2936,7 @@ 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
+/* Nonzero 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) {}; };
@@ -2868,21 +2946,18 @@ extern int flag_new_for_scope;
#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,
+/* Nonzero 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)->is_partial_instantiation)
+ (LANG_TYPE_CLASS_CHECK (TYPE)->is_partial_instantiation)
-/* Non-zero iff we are currently processing a declaration for an
+/* Nonzero 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. */
@@ -2930,14 +3005,15 @@ extern int flag_new_for_scope;
/* An integer indicating how many bytes should be subtracted from the
`this' pointer when this function is called. */
-#define THUNK_DELTA(DECL) (DECL_CHECK (DECL)->decl.u1.i)
+#define THUNK_DELTA(DECL) \
+ (DECL_LANG_SPECIFIC (DECL)->u.f.delta)
/* A tree indicating how many bytes should be subtracted from the
vtable for the `this' pointer to find the vcall offset. (The vptr
is always located at offset zero from the f `this' pointer.) If
NULL, then there is no vcall offset. */
#define THUNK_VCALL_OFFSET(DECL) \
- (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
+ (LANG_DECL_U2_CHECK (DECL, 0)->vcall_offset)
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
@@ -2954,15 +3030,6 @@ extern int flag_new_for_scope;
#define HANDLER_PARMS(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 0)
#define HANDLER_BODY(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 1)
#define HANDLER_TYPE(NODE) TREE_TYPE (HANDLER_CHECK (NODE))
-#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (SUBOBJECT_CHECK (NODE), 0)
-
-/* Nonzero if this CTOR_STMT is for the beginning of a constructor. */
-#define CTOR_BEGIN_P(NODE) \
- (TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE)))
-
-/* Nonzero if this CTOR_STMT is for the end of a constructor. */
-#define CTOR_END_P(NODE) \
- (!CTOR_BEGIN_P (NODE))
/* The parameters for a call-declarator. */
#define CALL_DECLARATOR_PARMS(NODE) \
@@ -3075,23 +3142,25 @@ typedef enum tsubst_flags_t {
tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
tf_keep_type_decl = 1 << 4, /* retain typedef type decls
(make_typename_type use) */
- tf_ptrmem_ok = 1 << 5 /* pointers to member ok (internal
+ tf_ptrmem_ok = 1 << 5, /* pointers to member ok (internal
instantiate_type use) */
+ tf_parsing = 1 << 6 /* called from parser
+ (make_typename_type use) */
} tsubst_flags_t;
-/* The kind of checking we can do looking in a class hierarchy. */
+/* The kind of checking we can do looking in a class hierarchy. */
typedef enum base_access {
ba_any = 0, /* Do not check access, allow an ambiguous base,
prefer a non-virtual base */
ba_ignore = 1, /* Do not check access */
ba_check = 2, /* Check access */
ba_not_special = 3, /* Do not consider special privilege
- current_class_type might give. */
+ current_class_type might give. */
ba_quiet = 4, /* Do not issue error messages (bit mask). */
} base_access;
/* The kind of base we can find, looking in a class hierarchy.
- Values <0 indicate we failed. */
+ Values <0 indicate we failed. */
typedef enum base_kind {
bk_inaccessible = -3, /* The base is inaccessible */
bk_ambig = -2, /* The base is ambiguous */
@@ -3100,33 +3169,17 @@ typedef enum base_kind {
bk_proper_base = 1, /* It is a proper base */
bk_via_virtual = 2 /* It is a proper base, but via a virtual
path. This might not be the canonical
- binfo. */
+ binfo. */
} base_kind;
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-extern int flag_ms_extensions;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-extern int warn_overloaded_virtual;
-
-/* Nonzero means warn about use of multicharacter literals. */
-extern int warn_multichar;
-
/* Set by add_implicitly_declared_members() to keep those members from
being flagged as deprecated or reported as using deprecated
types. */
extern int adding_implicit_members;
-/* 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 decl{2}.c */
/* A node that is a list (length 1) of error_mark_nodes. */
-extern tree error_mark_list;
+extern GTY(()) tree error_mark_list;
/* Node for "pointer to (virtual) function".
This may be distinct from ptr_type_node so gdb can distinguish them. */
@@ -3134,9 +3187,10 @@ extern tree error_mark_list;
/* For building calls to `delete'. */
-extern tree integer_two_node, integer_three_node;
+extern GTY(()) tree integer_two_node;
+extern GTY(()) tree integer_three_node;
-extern tree anonymous_namespace_name;
+extern GTY(()) tree anonymous_namespace_name;
/* The number of function bodies which we are currently processing.
(Zero if we are at namespace scope, one inside the body of a
@@ -3167,13 +3221,9 @@ typedef enum unification_kind_t {
extern int current_class_depth;
-/* 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;
-
/* An array of all local classes present in this translation unit, in
declaration order. */
-extern varray_type local_classes;
+extern GTY(()) varray_type local_classes;
/* Here's where we control how name mangling takes place. */
@@ -3261,7 +3311,6 @@ extern varray_type local_classes;
#endif /* NO_DOLLAR_IN_LABEL */
#define THIS_NAME "this"
-#define FILE_FUNCTION_PREFIX_LEN 9
#define CTOR_NAME "__ct"
#define DTOR_NAME "__dt"
@@ -3294,7 +3343,7 @@ extern varray_type local_classes;
&& IDENTIFIER_POINTER (ID_NODE)[1] == '_')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
-/* Returns non-zero iff NODE is a declaration for the global function
+/* Returns nonzero iff NODE is a declaration for the global function
`main'. */
#define DECL_MAIN_P(NODE) \
(DECL_EXTERN_C_FUNCTION_P (NODE) \
@@ -3302,39 +3351,20 @@ extern varray_type local_classes;
&& MAIN_NAME_P (DECL_NAME (NODE)))
-/* Things for handling inline functions. */
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-extern int flag_implement_inlines;
-
-/* Nonzero means templates obey #pragma interface and implementation. */
-
-extern int flag_external_templates;
-
-/* Nonzero means templates are emitted where they are instantiated. */
-
-extern int flag_alt_external_templates;
-
-/* Nonzero means implicit template instantiations are emitted. */
-
-extern int flag_implicit_templates;
-
-/* Nonzero if we want to emit defined symbols with common-like linkage as
- weak symbols where possible, in order to conform to C++ semantics.
- Otherwise, emit them as local symbols. */
-
-extern int flag_weak;
-
/* Nonzero if we're done parsing and into end-of-file activities. */
extern int at_eof;
+/* A list of namespace-scope 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 in the
+ TREE_PURPOSE slot. */
+extern GTY(()) tree static_aggregates;
+
/* Functions called along with real static constructors and destructors. */
-extern tree static_ctors;
-extern tree static_dtors;
+extern GTY(()) tree static_ctors;
+extern GTY(()) tree static_dtors;
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
@@ -3444,7 +3474,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
type is derived from the pointed to
by the first. */
#define COMPARE_RELAXED 2 /* Like COMPARE_DERIVED, but in
- reverse. Also treat enmeration
+ reverse. Also treat enumeration
types as the same as integer types
of the same width. */
#define COMPARE_REDECLARATION 4 /* The comparsion is being done when
@@ -3547,6 +3577,8 @@ typedef struct operator_name_info_t
const char *name;
/* The mangled name of the operator. */
const char *mangled_name;
+ /* The arity of the operator. */
+ int arity;
} operator_name_info_t;
/* A mapping from tree codes to operator name information. */
@@ -3567,8 +3599,11 @@ extern tree build_method_call PARAMS ((tree, tree, tree, tree, int));
extern int null_ptr_cst_p PARAMS ((tree));
extern int sufficient_parms_p PARAMS ((tree));
extern tree type_decays_to PARAMS ((tree));
+extern tree resolve_scoped_fn_name PARAMS ((tree, tree));
extern tree build_user_type_conversion PARAMS ((tree, tree, int));
extern tree build_new_function_call PARAMS ((tree, tree));
+extern tree build_new_method_call (tree, tree, tree, tree, int);
+extern tree build_special_member_call (tree, tree, tree, tree, int);
extern tree build_new_op PARAMS ((enum tree_code, int, tree, tree, tree));
extern tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree));
extern int can_convert PARAMS ((tree, tree));
@@ -3578,15 +3613,20 @@ extern int enforce_access PARAMS ((tree, tree));
extern tree convert_default_arg PARAMS ((tree, tree, tree, int));
extern tree convert_arg_to_ellipsis PARAMS ((tree));
extern tree build_x_va_arg PARAMS ((tree, tree));
-extern tree convert_type_from_ellipsis PARAMS ((tree));
+extern tree cxx_type_promotes_to PARAMS ((tree));
+extern tree type_passed_as PARAMS ((tree));
+extern tree convert_for_arg_passing PARAMS ((tree, tree));
+extern tree cp_convert_parm_for_inlining PARAMS ((tree, tree, tree));
extern int is_properly_derived_from PARAMS ((tree, tree));
-extern tree initialize_reference PARAMS ((tree, tree));
+extern tree initialize_reference PARAMS ((tree, tree, tree));
+extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals PARAMS ((tree));
extern tree perform_implicit_conversion PARAMS ((tree, tree));
+extern tree perform_direct_initialization_if_possible (tree, tree);
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
-extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
+extern tree convert_to_base (tree, tree, bool);
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
@@ -3613,10 +3653,12 @@ extern void cxx_print_xnode PARAMS ((FILE *, tree, int));
extern void cxx_print_decl PARAMS ((FILE *, tree, int));
extern void cxx_print_type PARAMS ((FILE *, tree, int));
extern void cxx_print_identifier PARAMS ((FILE *, tree, int));
-extern void cxx_set_yydebug PARAMS ((int));
+extern void cxx_print_error_function PARAMS ((struct diagnostic_context *,
+ const char *));
extern void build_self_reference PARAMS ((void));
extern int same_signature_p PARAMS ((tree, tree));
extern void warn_hidden PARAMS ((tree));
+extern void maybe_add_class_template_decl_list PARAMS ((tree, tree, int));
extern tree get_enclosing_class PARAMS ((tree));
int is_base_of_enclosing_class PARAMS ((tree, tree));
extern void unreverse_member_declarations PARAMS ((tree));
@@ -3625,6 +3667,7 @@ extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_in_class PARAMS ((tree, tree));
extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
extern tree in_charge_arg_for_name PARAMS ((tree));
+extern tree build_cxx_call PARAMS ((tree, tree, tree));
extern tree get_vtt_name PARAMS ((tree));
extern tree get_primary_binfo PARAMS ((tree));
@@ -3632,11 +3675,12 @@ extern tree get_primary_binfo PARAMS ((tree));
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
extern tree convert_from_reference PARAMS ((tree));
extern tree convert_lvalue PARAMS ((tree, tree));
+extern tree force_rvalue PARAMS ((tree));
extern tree ocp_convert PARAMS ((tree, tree, int, int));
extern tree cp_convert PARAMS ((tree, tree));
extern tree convert_to_void PARAMS ((tree, const char */*implicit context*/));
extern tree convert_force PARAMS ((tree, tree, int));
-extern tree build_type_conversion PARAMS ((tree, tree, int));
+extern tree build_type_conversion PARAMS ((tree, tree));
extern tree build_expr_type_conversion PARAMS ((int, tree, int));
extern tree type_promotes_to PARAMS ((tree));
extern tree perform_qualification_conversions PARAMS ((tree, tree));
@@ -3644,12 +3688,25 @@ extern void clone_function_decl PARAMS ((tree, int));
extern void adjust_clone_args PARAMS ((tree));
/* decl.c */
-/* resume_binding_level */
+extern int global_bindings_p PARAMS ((void));
+extern int kept_level_p PARAMS ((void));
+extern tree getdecls PARAMS ((void));
+extern void pushlevel PARAMS ((int));
+extern tree poplevel PARAMS ((int,int, int));
+extern void insert_block PARAMS ((tree));
+extern void set_block PARAMS ((tree));
+extern tree pushdecl PARAMS ((tree));
extern void cxx_init_decl_processing PARAMS ((void));
+enum cp_tree_node_structure_enum cp_tree_node_structure
+ PARAMS ((union lang_tree_node *));
+extern void cxx_insert_default_attributes PARAMS ((tree));
+extern bool cxx_mark_addressable PARAMS ((tree));
+extern void cxx_push_function_context PARAMS ((struct function *));
+extern void cxx_pop_function_context PARAMS ((struct function *));
+extern void cxx_mark_function_context PARAMS ((struct function *));
extern int toplevel_bindings_p PARAMS ((void));
extern int namespace_bindings_p PARAMS ((void));
extern void keep_next_level PARAMS ((int));
-extern int kept_level_p PARAMS ((void));
extern int template_parm_scope_p PARAMS ((void));
extern void set_class_shadows PARAMS ((tree));
extern void maybe_push_cleanup_level PARAMS ((tree));
@@ -3658,13 +3715,13 @@ extern void finish_scope PARAMS ((void));
extern void note_level_for_for PARAMS ((void));
extern void note_level_for_try PARAMS ((void));
extern void note_level_for_catch PARAMS ((void));
-extern void resume_level PARAMS ((struct binding_level *));
+extern void resume_level PARAMS ((struct cp_binding_level *));
extern void delete_block PARAMS ((tree));
extern void add_block_current_level PARAMS ((tree));
extern void pushlevel_class PARAMS ((void));
extern void poplevel_class PARAMS ((void));
extern void print_binding_stack PARAMS ((void));
-extern void print_binding_level PARAMS ((struct binding_level *));
+extern void print_binding_level PARAMS ((struct cp_binding_level *));
extern void push_namespace PARAMS ((tree));
extern void pop_namespace PARAMS ((void));
extern void push_nested_namespace PARAMS ((tree));
@@ -3683,23 +3740,24 @@ extern void clear_anon_tags PARAMS ((void));
extern int decls_match PARAMS ((tree, tree));
extern int duplicate_decls PARAMS ((tree, tree));
extern tree pushdecl_top_level PARAMS ((tree));
-extern void pushdecl_class_level PARAMS ((tree));
+extern tree pushdecl_top_level_and_finish (tree, tree);
+extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level PARAMS ((tree));
extern tree push_using_decl PARAMS ((tree, tree));
extern tree push_using_directive PARAMS ((tree));
-extern void push_class_level_binding PARAMS ((tree, tree));
+extern bool push_class_level_binding (tree, tree);
extern tree implicitly_declare PARAMS ((tree));
extern tree declare_local_label PARAMS ((tree));
extern tree define_label PARAMS ((const char *, int, tree));
extern void check_goto PARAMS ((tree));
extern void define_case_label PARAMS ((void));
-extern tree binding_for_name PARAMS ((tree, tree));
+extern cxx_binding *binding_for_name (tree, tree);
extern tree namespace_binding PARAMS ((tree, tree));
extern void set_namespace_binding PARAMS ((tree, tree, tree));
extern tree lookup_namespace_name PARAMS ((tree, tree));
extern tree build_typename_type PARAMS ((tree, tree, tree, tree));
extern tree make_typename_type PARAMS ((tree, tree, tsubst_flags_t));
-extern tree make_unbound_class_template PARAMS ((tree, tree, int));
+extern tree make_unbound_class_template PARAMS ((tree, tree, tsubst_flags_t));
extern tree lookup_name_nonclass PARAMS ((tree));
extern tree lookup_function_nonclass PARAMS ((tree, tree));
extern tree lookup_name PARAMS ((tree, int));
@@ -3709,9 +3767,11 @@ extern tree lookup_name_namespace_only PARAMS ((tree));
extern void begin_only_namespace_names PARAMS ((void));
extern void end_only_namespace_names PARAMS ((void));
extern tree namespace_ancestor PARAMS ((tree, tree));
+extern bool is_ancestor (tree, tree);
extern tree unqualified_namespace_lookup PARAMS ((tree, int, tree *));
-extern int lookup_using_namespace PARAMS ((tree, tree, tree, tree, int, tree *));
-extern int qualified_lookup_using_namespace PARAMS ((tree, tree, tree, int));
+extern tree check_for_out_of_scope_variable (tree);
+extern bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int, tree *);
+extern bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int);
extern tree build_library_fn PARAMS ((tree, tree));
extern tree build_library_fn_ptr PARAMS ((const char *, tree));
extern tree build_cp_library_fn_ptr PARAMS ((const char *, tree));
@@ -3727,20 +3787,19 @@ extern void start_decl_1 PARAMS ((tree));
extern void cp_finish_decl PARAMS ((tree, tree, tree, int));
extern void finish_decl PARAMS ((tree, tree, tree));
extern void maybe_inject_for_scope_var PARAMS ((tree));
-extern void initialize_local_var PARAMS ((tree, tree, int));
-extern void expand_static_init PARAMS ((tree, tree));
extern tree start_handler_parms PARAMS ((tree, tree));
extern int complete_array_type PARAMS ((tree, tree, int));
extern tree build_ptrmemfunc_type PARAMS ((tree));
+extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PARAMS ((tree));
extern int copy_fn_p PARAMS ((tree));
extern void grok_special_member_properties PARAMS ((tree));
extern int grok_ctor_properties PARAMS ((tree, tree));
extern void grok_op_properties PARAMS ((tree, int));
-extern tree xref_tag PARAMS ((tree, tree, int));
+extern tree xref_tag (enum tag_types, tree, tree, bool);
extern tree xref_tag_from_type PARAMS ((tree, tree, int));
-extern void xref_basetypes PARAMS ((tree, tree, tree, tree));
+extern void xref_basetypes PARAMS ((tree, tree));
extern tree start_enum PARAMS ((tree));
extern void finish_enum PARAMS ((tree));
extern void build_enumerator PARAMS ((tree, tree, tree));
@@ -3753,7 +3812,7 @@ extern tree finish_method PARAMS ((tree));
extern void maybe_register_incomplete_var PARAMS ((tree));
extern void complete_vars PARAMS ((tree));
extern void finish_stmt PARAMS ((void));
-extern void print_other_binding_stack PARAMS ((struct binding_level *));
+extern void print_other_binding_stack PARAMS ((struct cp_binding_level *));
extern void revert_static_member_fn PARAMS ((tree));
extern void fixup_anonymous_aggr PARAMS ((tree));
extern int check_static_variable_definition PARAMS ((tree, tree));
@@ -3772,6 +3831,9 @@ typedef int (*walk_globals_fn) PARAMS ((tree *, void *));
extern int walk_globals PARAMS ((walk_globals_pred,
walk_globals_fn,
void *));
+extern int walk_vtables PARAMS ((walk_globals_pred,
+ walk_globals_fn,
+ void *));
typedef int (*walk_namespaces_fn) PARAMS ((tree, void *));
extern int walk_namespaces PARAMS ((walk_namespaces_fn,
void *));
@@ -3785,12 +3847,12 @@ extern int nonstatic_local_decl_p PARAMS ((tree));
extern tree declare_global_var PARAMS ((tree, tree));
extern void register_dtor_fn PARAMS ((tree));
extern tmpl_spec_kind current_tmpl_spec_kind PARAMS ((int));
+extern cxx_binding *cxx_scope_find_binding_for_name (tree, tree);
extern tree cp_fname_init PARAMS ((const char *));
+extern bool have_extern_spec;
/* in decl2.c */
-extern void init_decl2 PARAMS ((void));
extern int check_java_method PARAMS ((tree));
-extern int cxx_decode_option PARAMS ((int, char **));
extern int grok_method_quals PARAMS ((tree, tree, tree));
extern void warn_if_unknown_interface PARAMS ((tree));
extern void grok_x_components PARAMS ((tree));
@@ -3804,10 +3866,11 @@ extern void check_member_template PARAMS ((tree));
extern tree grokfield PARAMS ((tree, tree, tree, tree, tree));
extern tree grokbitfield PARAMS ((tree, tree, tree));
extern tree groktypefield PARAMS ((tree, tree));
-extern tree grokoptypename PARAMS ((tree, tree));
+extern tree grokoptypename PARAMS ((tree, tree, tree));
extern void cplus_decl_attributes PARAMS ((tree *, tree, int));
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
+extern bool constructor_name_p (tree, tree);
extern void defer_fn PARAMS ((tree));
extern void finish_anon_union PARAMS ((tree));
extern tree finish_table PARAMS ((tree, tree, tree, int));
@@ -3824,6 +3887,8 @@ extern void finish_file PARAMS ((void));
extern tree reparse_absdcl_as_expr PARAMS ((tree, tree));
extern tree reparse_absdcl_as_casts PARAMS ((tree, tree));
extern tree build_expr_from_tree PARAMS ((tree));
+extern tree build_offset_ref_call_from_tree (tree, tree);
+extern tree build_call_from_tree (tree, tree, bool);
extern tree reparse_decl_as_expr PARAMS ((tree, tree));
extern tree finish_decl_parsing PARAMS ((tree));
extern void set_decl_namespace PARAMS ((tree, tree, int));
@@ -3839,17 +3904,16 @@ extern tree do_class_using_decl PARAMS ((tree));
extern void do_using_directive PARAMS ((tree));
extern void check_default_args PARAMS ((tree));
extern void mark_used PARAMS ((tree));
-extern tree handle_class_head PARAMS ((tree, tree, tree, int, int *));
+extern tree handle_class_head (enum tag_types, tree, tree, tree, int, int *);
+extern tree handle_class_head_apparent_template (tree, int *);
extern tree lookup_arg_dependent PARAMS ((tree, tree, tree));
extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int));
+extern tree cp_build_parm_decl PARAMS ((tree, tree));
extern tree build_artificial_parm PARAMS ((tree, tree));
extern tree get_guard PARAMS ((tree));
extern tree get_guard_cond PARAMS ((tree));
extern tree set_guard PARAMS ((tree));
-/* in parse.y */
-extern void cp_parse_init PARAMS ((void));
-
extern void cp_error_at PARAMS ((const char *msgid, ...));
extern void cp_warning_at PARAMS ((const char *msgid, ...));
extern void cp_pedwarn_at PARAMS ((const char *msgid, ...));
@@ -3889,8 +3953,9 @@ extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */
-extern void init_cplus_expand PARAMS ((void));
-extern int extract_init PARAMS ((tree, tree));
+extern rtx cxx_expand_expr PARAMS ((tree, rtx,
+ enum machine_mode,
+ int));
extern tree cplus_expand_constant PARAMS ((tree));
/* friend.c */
@@ -3900,22 +3965,22 @@ extern void add_friend PARAMS ((tree, tree));
extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */
-extern void init_init_processing PARAMS ((void));
-extern void emit_base_init PARAMS ((tree, tree));
-extern tree expand_member_init PARAMS ((tree, tree, tree));
+extern tree expand_member_init (tree);
+extern void emit_mem_initializers (tree);
extern tree build_aggr_init PARAMS ((tree, tree, int));
+extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree));
-extern tree build_forced_zero_init PARAMS ((tree));
+extern tree build_zero_init (tree, tree, bool);
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
-extern tree build_vec_init PARAMS ((tree, tree, int));
+extern tree build_vec_init PARAMS ((tree, tree, tree, int));
extern tree build_x_delete PARAMS ((tree, int, tree));
extern tree build_delete PARAMS ((tree, tree, special_function_kind, int, int));
-extern void perform_base_cleanups PARAMS ((void));
+extern void push_base_cleanups PARAMS ((void));
extern tree build_vbase_delete PARAMS ((tree, tree));
extern tree build_vec_delete PARAMS ((tree, tree, special_function_kind, int));
extern tree create_temporary_var PARAMS ((tree));
@@ -3927,6 +3992,7 @@ extern tree build_java_class_ref PARAMS ((tree));
/* in input.c */
/* in lex.c */
+extern void cxx_dup_lang_specific_decl PARAMS ((tree));
extern tree make_pointer_declarator PARAMS ((tree, tree));
extern tree make_reference_declarator PARAMS ((tree, tree));
extern tree make_call_declarator PARAMS ((tree, tree, tree, tree));
@@ -3943,19 +4009,17 @@ extern void note_got_semicolon PARAMS ((tree));
extern void note_list_got_semicolon PARAMS ((tree));
extern void do_pending_lang_change PARAMS ((void));
extern void see_typename PARAMS ((void));
+extern void unqualified_name_lookup_error PARAMS ((tree));
extern tree do_identifier PARAMS ((tree, int, tree));
-extern tree do_scoped_id PARAMS ((tree, int));
+extern tree do_scoped_id PARAMS ((tree, tree));
extern tree identifier_typedecl_value PARAMS ((tree));
extern tree build_lang_decl PARAMS ((enum tree_code, tree, tree));
extern void retrofit_lang_decl PARAMS ((tree));
extern tree copy_decl PARAMS ((tree));
extern tree copy_type PARAMS ((tree));
-extern tree cp_make_lang_type PARAMS ((enum tree_code));
+extern tree cxx_make_type PARAMS ((enum tree_code));
extern tree make_aggr_type PARAMS ((enum tree_code));
-extern void compiler_error PARAMS ((const char *, ...))
- ATTRIBUTE_PRINTF_1;
extern void yyerror PARAMS ((const char *));
-extern void clear_inline_text_obstack PARAMS ((void));
extern void yyhook PARAMS ((int));
extern int cp_type_qual_from_rid PARAMS ((tree));
extern const char *cxx_init PARAMS ((const char *));
@@ -3979,7 +4043,6 @@ extern int calls_setjmp_p PARAMS ((tree));
extern int maybe_clone_body PARAMS ((tree));
/* in pt.c */
-extern void init_pt PARAMS ((void));
extern void check_template_shadow PARAMS ((tree));
extern tree get_innermost_template_args PARAMS ((tree, int));
extern tree tsubst PARAMS ((tree, tree, tsubst_flags_t, tree));
@@ -4012,7 +4075,7 @@ extern tree tinst_for_decl PARAMS ((void));
extern void mark_decl_instantiated PARAMS ((tree, int));
extern int more_specialized PARAMS ((tree, tree, int, int));
extern void mark_class_instantiated PARAMS ((tree, int));
-extern void do_decl_instantiation PARAMS ((tree, tree, tree));
+extern void do_decl_instantiation (tree, tree);
extern void do_type_instantiation PARAMS ((tree, tree, tsubst_flags_t));
extern tree instantiate_decl PARAMS ((tree, int));
extern tree get_bindings PARAMS ((tree, tree, tree));
@@ -4020,7 +4083,6 @@ extern int push_tinst_level PARAMS ((tree));
extern void pop_tinst_level PARAMS ((void));
extern int more_specialized_class PARAMS ((tree, tree));
extern int is_member_template PARAMS ((tree));
-extern int template_parms_equal PARAMS ((tree, tree));
extern int comp_template_parms PARAMS ((tree, tree));
extern int template_class_depth PARAMS ((tree));
extern int is_specialization_of PARAMS ((tree, tree));
@@ -4032,7 +4094,7 @@ extern void print_candidates PARAMS ((tree));
extern int instantiate_pending_templates PARAMS ((void));
extern tree tsubst_default_argument PARAMS ((tree, tree, tree));
extern tree most_general_template PARAMS ((tree));
-extern tree get_mostly_instantiated_function_type PARAMS ((tree, tree *, tree *));
+extern tree get_mostly_instantiated_function_type PARAMS ((tree));
extern int problematic_instantiation_changed PARAMS ((void));
extern void record_last_problematic_instantiation PARAMS ((void));
extern tree current_instantiation PARAMS ((void));
@@ -4061,6 +4123,7 @@ extern tree get_vbase PARAMS ((tree, tree));
extern tree get_dynamic_cast_base_type PARAMS ((tree, tree));
extern void type_access_control PARAMS ((tree, tree));
extern int accessible_p PARAMS ((tree, tree));
+extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field PARAMS ((tree, tree, int, int));
extern tree lookup_nested_field PARAMS ((tree, int));
extern int lookup_fnfields_1 PARAMS ((tree, tree));
@@ -4079,6 +4142,7 @@ extern void init_search_processing PARAMS ((void));
extern void reinit_search_statistics PARAMS ((void));
extern tree current_scope PARAMS ((void));
extern int at_function_scope_p PARAMS ((void));
+extern bool at_class_scope_p (void);
extern tree context_for_name_lookup PARAMS ((tree));
extern tree lookup_conversions PARAMS ((tree));
extern tree binfo_for_vtable PARAMS ((tree));
@@ -4105,7 +4169,9 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
extern tree find_vbase_instance PARAMS ((tree, tree));
extern tree binfo_for_vbase PARAMS ((tree, tree));
extern tree binfo_via_virtual PARAMS ((tree, tree));
-
+extern tree build_baselink (tree, tree, tree, tree);
+extern tree adjust_result_of_qualified_name_lookup
+ (tree, tree, tree);
/* in semantics.c */
extern void init_cp_semantics PARAMS ((void));
extern tree finish_expr_stmt PARAMS ((tree));
@@ -4157,19 +4223,19 @@ extern void finish_subobject PARAMS ((tree));
extern tree finish_parenthesized_expr PARAMS ((tree));
extern tree begin_stmt_expr PARAMS ((void));
extern tree finish_stmt_expr PARAMS ((tree));
-extern tree finish_call_expr PARAMS ((tree, tree, int));
+extern tree finish_call_expr (tree, tree, bool);
extern tree finish_increment_expr PARAMS ((tree, enum tree_code));
extern tree finish_this_expr PARAMS ((void));
extern tree finish_object_call_expr PARAMS ((tree, tree, tree));
extern tree finish_qualified_object_call_expr PARAMS ((tree, tree, tree));
extern tree finish_pseudo_destructor_call_expr PARAMS ((tree, tree, tree));
-extern tree finish_qualified_call_expr PARAMS ((tree, tree));
extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((tree));
+extern tree finish_fname (tree);
extern void save_type_access_control PARAMS ((tree));
extern void reset_type_access_control PARAMS ((void));
extern void decl_type_access_control PARAMS ((tree));
-extern int begin_function_definition PARAMS ((tree, tree));
+extern int begin_function_definition (tree, tree, tree);
extern tree begin_constructor_declarator PARAMS ((tree, tree));
extern tree finish_declarator PARAMS ((tree, tree, tree, tree, int));
extern void finish_translation_unit PARAMS ((void));
@@ -4180,7 +4246,6 @@ extern tree begin_class_definition PARAMS ((tree));
extern tree finish_class_definition PARAMS ((tree, tree, int, int));
extern void finish_default_args PARAMS ((void));
extern void begin_inline_definitions PARAMS ((void));
-extern void finish_inline_definitions PARAMS ((void));
extern tree finish_member_class_template PARAMS ((tree));
extern void finish_template_decl PARAMS ((tree));
extern tree finish_template_type PARAMS ((tree, tree, int));
@@ -4192,21 +4257,22 @@ extern tree finish_typeof PARAMS ((tree));
extern tree finish_sizeof PARAMS ((tree));
extern tree finish_alignof PARAMS ((tree));
extern void finish_decl_cleanup PARAMS ((tree, tree));
+extern void finish_eh_cleanup PARAMS ((tree));
extern void finish_named_return_value PARAMS ((tree, tree));
extern void expand_body PARAMS ((tree));
extern tree nullify_returns_r PARAMS ((tree *, int *, void *));
extern void do_pushlevel PARAMS ((void));
extern tree do_poplevel PARAMS ((void));
+extern void begin_mem_initializers (void);
extern void finish_mem_initializers PARAMS ((tree));
extern void setup_vtbl_ptr PARAMS ((tree, tree));
extern void clear_out_block PARAMS ((void));
extern tree begin_global_stmt_expr PARAMS ((void));
extern tree finish_global_stmt_expr PARAMS ((tree));
-
+extern tree check_template_template_default_arg (tree);
/* in spew.c */
extern void init_spew PARAMS ((void));
-extern void mark_pending_inlines PARAMS ((PTR));
extern int peekyylex PARAMS ((void));
extern tree arbitrate_lookup PARAMS ((tree, tree, tree));
extern tree frob_opname PARAMS ((tree));
@@ -4219,6 +4285,11 @@ extern void replace_defarg PARAMS ((tree, tree));
extern void end_input PARAMS ((void));
/* in tree.c */
+extern void lang_check_failed PARAMS ((const char *, int,
+ const char *));
+extern tree stabilize_expr PARAMS ((tree, tree *));
+extern tree cxx_unsave_expr_now PARAMS ((tree));
+extern tree cxx_maybe_build_cleanup PARAMS ((tree));
extern void init_tree PARAMS ((void));
extern int pod_type_p PARAMS ((tree));
extern int zero_init_p PARAMS ((tree));
@@ -4226,7 +4297,11 @@ extern tree canonical_type_variant PARAMS ((tree));
extern void unshare_base_binfos PARAMS ((tree));
extern int member_p PARAMS ((tree));
extern cp_lvalue_kind real_lvalue_p PARAMS ((tree));
-extern tree build_min PARAMS ((enum tree_code, tree, ...));
+extern cp_lvalue_kind real_non_cast_lvalue_p (tree);
+extern int non_cast_lvalue_p PARAMS ((tree));
+extern int non_cast_lvalue_or_else PARAMS ((tree, const char *));
+extern tree build_min PARAMS ((enum tree_code, tree,
+ ...));
extern tree build_min_nt PARAMS ((enum tree_code, ...));
extern tree build_cplus_new PARAMS ((tree, tree));
extern tree get_target_expr PARAMS ((tree));
@@ -4241,6 +4316,7 @@ extern tree make_binfo PARAMS ((tree, tree, tree, tree));
extern tree reverse_path PARAMS ((tree));
extern int count_functions PARAMS ((tree));
extern int is_overloaded_fn PARAMS ((tree));
+extern tree get_overloaded_fn PARAMS ((tree));
extern tree get_first_fn PARAMS ((tree));
extern int bound_pmf_p PARAMS ((tree));
extern tree ovl_cons PARAMS ((tree, tree));
@@ -4248,7 +4324,7 @@ extern tree build_overload PARAMS ((tree, tree));
extern tree function_arg_chain PARAMS ((tree));
extern int promotes_to_aggr_type PARAMS ((tree, enum tree_code));
extern int is_aggr_type_2 PARAMS ((tree, tree));
-extern const char *lang_printable_name PARAMS ((tree, int));
+extern const char *cxx_printable_name PARAMS ((tree, int));
extern tree build_exception_variant PARAMS ((tree, tree));
extern tree bind_template_template_parm PARAMS ((tree, tree));
extern tree array_type_nelts_total PARAMS ((tree));
@@ -4259,8 +4335,7 @@ extern tree vec_binfo_member PARAMS ((tree, tree));
extern tree decl_namespace_context PARAMS ((tree));
extern tree lvalue_type PARAMS ((tree));
extern tree error_type PARAMS ((tree));
-extern tree build_ptr_wrapper PARAMS ((void *));
-extern tree build_int_wrapper PARAMS ((int));
+extern tree build_zc_wrapper PARAMS ((struct z_candidate *));
extern tree build_srcloc_here PARAMS ((void));
extern int varargs_function_p PARAMS ((tree));
extern int really_overloaded_fn PARAMS ((tree));
@@ -4270,13 +4345,14 @@ extern void debug_binfo PARAMS ((tree));
extern tree build_dummy_object PARAMS ((tree));
extern tree maybe_dummy_object PARAMS ((tree, tree *));
extern int is_dummy_object PARAMS ((tree));
-extern const struct attribute_spec cp_attribute_table[];
+extern const struct attribute_spec cxx_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, tsubst_flags_t));
#define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
extern tree build_shared_int_cst PARAMS ((int));
extern special_function_kind special_function_p PARAMS ((tree));
+extern bool name_p (tree);
extern int count_trees PARAMS ((tree));
extern int char_type_p PARAMS ((tree));
extern void verify_stmt_tree PARAMS ((tree));
@@ -4300,7 +4376,8 @@ extern tree condition_conversion PARAMS ((tree));
extern tree target_type PARAMS ((tree));
extern tree require_complete_type PARAMS ((tree));
extern tree complete_type PARAMS ((tree));
-extern tree complete_type_or_else PARAMS ((tree, tree));
+extern tree complete_type_or_diagnostic PARAMS ((tree, tree, int));
+#define complete_type_or_else(T,V) (complete_type_or_diagnostic ((T), (V), 0))
extern int type_unknown_p PARAMS ((tree));
extern tree commonparms PARAMS ((tree, tree));
extern tree original_type PARAMS ((tree));
@@ -4311,17 +4388,15 @@ extern int compparms PARAMS ((tree, tree));
extern int comp_cv_qualification PARAMS ((tree, tree));
extern int comp_cv_qual_signature PARAMS ((tree, tree));
extern tree expr_sizeof PARAMS ((tree));
-extern tree c_sizeof_nowarn PARAMS ((tree));
+extern tree cxx_sizeof_or_alignof_type PARAMS ((tree, enum tree_code, int));
+#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion PARAMS ((tree));
extern tree decay_conversion PARAMS ((tree));
-extern tree build_object_ref PARAMS ((tree, tree, tree));
-extern tree build_component_ref_1 PARAMS ((tree, tree, int));
-extern tree build_component_ref PARAMS ((tree, tree, tree, int));
-extern tree build_x_component_ref PARAMS ((tree, tree, tree, int));
+extern tree build_class_member_access_expr (tree, tree, tree, bool);
+extern tree finish_class_member_access_expr (tree, tree);
extern tree build_x_indirect_ref PARAMS ((tree, const char *));
extern tree build_indirect_ref PARAMS ((tree, const char *));
extern tree build_array_ref PARAMS ((tree, tree));
-extern tree build_x_function_call PARAMS ((tree, tree, tree));
extern tree get_member_function_from_ptrfunc PARAMS ((tree *, tree));
extern tree build_function_call_real PARAMS ((tree, tree, int, int));
extern tree build_function_call_maybe PARAMS ((tree, tree));
@@ -4357,20 +4432,27 @@ extern tree merge_types PARAMS ((tree, tree));
extern tree check_return_expr PARAMS ((tree));
#define cp_build_binary_op(code, arg1, arg2) \
build_binary_op(code, arg1, arg2, 1)
+#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
+#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
+extern tree build_ptrmemfunc_access_expr (tree, tree);
+extern tree build_address (tree);
+extern tree build_nop (tree, tree);
/* in typeck2.c */
+extern void require_complete_eh_spec_types PARAMS ((tree, tree));
+extern void cxx_incomplete_type_diagnostic PARAMS ((tree, tree, int));
+#undef cxx_incomplete_type_error
+extern void cxx_incomplete_type_error PARAMS ((tree, tree));
+#define cxx_incomplete_type_error(V,T) \
+ (cxx_incomplete_type_diagnostic ((V), (T), 0))
extern tree error_not_base_type PARAMS ((tree, tree));
extern tree binfo_or_else PARAMS ((tree, tree));
extern void readonly_error PARAMS ((tree, const char *, int));
extern int abstract_virtuals_error PARAMS ((tree, tree));
-#define my_friendly_assert(EXP, N) (void) \
- (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
-
-extern tree force_store_init_value PARAMS ((tree, tree));
extern tree store_init_value PARAMS ((tree, tree));
extern tree digest_init PARAMS ((tree, tree, tree *));
-extern tree build_scoped_ref PARAMS ((tree, tree));
+extern tree build_scoped_ref PARAMS ((tree, tree, tree *));
extern tree build_x_arrow PARAMS ((tree));
extern tree build_m_component_ref PARAMS ((tree, tree));
extern tree build_functional_cast PARAMS ((tree, tree));
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 1603a2a..75a6a3a 100644
--- a/contrib/gcc/cp/cvt.c
+++ b/contrib/gcc/cp/cvt.c
@@ -52,7 +52,7 @@ static void warn_ref_binding PARAMS ((tree, tree, tree));
narrowing is always done with a NOP_EXPR:
In convert.c, convert_to_integer.
In c-typeck.c, build_binary_op_nodefault (boolean ops),
- and truthvalue_conversion.
+ and c_common_truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR.
In fold-const.c: fold.
In tree.c: get_narrower and get_unwidened.
@@ -90,7 +90,7 @@ cp_convert_to_pointer (type, expr, force)
return error_mark_node;
}
- rval = build_type_conversion (type, expr, 1);
+ rval = build_type_conversion (type, expr);
if (rval)
{
if (rval == error_mark_node)
@@ -130,6 +130,9 @@ cp_convert_to_pointer (type, expr, force)
intype = TREE_TYPE (expr);
}
+ if (expr == error_mark_node)
+ return error_mark_node;
+
form = TREE_CODE (intype);
if (POINTER_TYPE_P (intype))
@@ -145,31 +148,33 @@ cp_convert_to_pointer (type, expr, force)
{
enum tree_code code = PLUS_EXPR;
tree binfo;
-
- /* Try derived to base conversion. */
- binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
- ba_check, NULL);
- if (!binfo)
+ tree intype_class;
+ tree type_class;
+ bool same_p;
+
+ intype_class = TREE_TYPE (intype);
+ type_class = TREE_TYPE (type);
+
+ same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
+ TYPE_MAIN_VARIANT (type_class));
+ binfo = NULL_TREE;
+ /* Try derived to base conversion. */
+ if (!same_p)
+ binfo = lookup_base (intype_class, type_class, ba_check, NULL);
+ if (!same_p && !binfo)
{
- /* Try base to derived conversion. */
- binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_check, NULL);
+ /* Try base to derived conversion. */
+ binfo = lookup_base (type_class, intype_class, ba_check, NULL);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
return error_mark_node;
- if (binfo)
+ if (binfo || same_p)
{
- expr = build_base_path (code, expr, binfo, 0);
- /* Add any qualifier conversions. */
- if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
- TREE_TYPE (type)))
- {
- expr = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (expr) =
- TREE_CONSTANT (TREE_OPERAND (expr, 0));
- }
- return expr;
+ if (binfo)
+ expr = build_base_path (code, expr, binfo, 0);
+ /* Add any qualifier conversions. */
+ return build_nop (type, expr);
}
}
@@ -222,9 +227,7 @@ cp_convert_to_pointer (type, expr, force)
return error_mark_node;
}
- rval = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
- return rval;
+ return build_nop (type, expr);
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
@@ -253,12 +256,18 @@ cp_convert_to_pointer (type, expr, force)
force_fit_type (expr, 0);
return expr;
}
+ else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+ && INTEGRAL_CODE_P (form))
+ {
+ error ("invalid conversion from '%T' to '%T'", intype, type);
+ return error_mark_node;
+ }
if (INTEGRAL_CODE_P (form))
{
if (TYPE_PRECISION (intype) == POINTER_SIZE)
return build1 (CONVERT_EXPR, type, expr);
- expr = cp_convert (type_for_size (POINTER_SIZE, 0), expr);
+ expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr);
/* Modes may be different but sizes should be the same. */
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
!= GET_MODE_SIZE (TYPE_MODE (type)))
@@ -313,19 +322,14 @@ convert_to_pointer_force (type, expr)
if (binfo)
{
expr = build_base_path (code, expr, binfo, 0);
- if (expr == error_mark_node)
- return error_mark_node;
- /* Add any qualifier conversions. */
+ if (expr == error_mark_node)
+ return error_mark_node;
+ /* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type)))
- {
- expr = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (expr) =
- TREE_CONSTANT (TREE_OPERAND (expr, 0));
- }
+ expr = build_nop (type, expr);
return expr;
}
-
}
}
@@ -348,7 +352,6 @@ build_up_reference (type, arg, flags, decl)
tree rval;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
- tree stmt_expr = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
@@ -358,25 +361,7 @@ build_up_reference (type, arg, flags, decl)
here because it needs to live as long as DECL. */
tree targ = arg;
- arg = build_decl (VAR_DECL, NULL_TREE, argtype);
- DECL_ARTIFICIAL (arg) = 1;
- TREE_USED (arg) = 1;
- TREE_STATIC (arg) = TREE_STATIC (decl);
-
- if (TREE_STATIC (decl))
- {
- /* Namespace-scope or local static; give it a mangled name. */
- tree name = mangle_ref_init_variable (decl);
- DECL_NAME (arg) = name;
- SET_DECL_ASSEMBLER_NAME (arg, name);
- arg = pushdecl_top_level (arg);
- }
- else
- {
- /* Automatic; make sure we handle the cleanup properly. */
- maybe_push_cleanup_level (argtype);
- arg = pushdecl (arg);
- }
+ arg = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (arg));
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
@@ -409,16 +394,7 @@ build_up_reference (type, arg, flags, decl)
else
rval
= convert_to_pointer_force (build_pointer_type (target_type), rval);
- rval = build1 (NOP_EXPR, type, rval);
- TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
-
- /* If we created and initialized a new temporary variable, add the
- representation of that initialization to the RVAL. */
- if (stmt_expr)
- rval = build (COMPOUND_EXPR, TREE_TYPE (rval), stmt_expr, rval);
-
- /* And return the result. */
- return rval;
+ return build_nop (type, rval);
}
/* Subroutine of convert_to_reference. REFTYPE is the target reference type.
@@ -500,7 +476,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 (reftype, expr, 1);
+ = build_type_conversion (reftype, expr);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -609,6 +585,21 @@ convert_lvalue (totype, expr)
NULL_TREE);
return convert_from_reference (expr);
}
+
+/* Really perform an lvalue-to-rvalue conversion, including copying an
+ argument of class type into a temporary. */
+
+tree
+force_rvalue (tree expr)
+{
+ if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+ expr = ocp_convert (TREE_TYPE (expr), expr,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
+ else
+ expr = decay_conversion (expr);
+
+ return expr;
+}
/* C++ conversions, preference to static cast conversions. */
@@ -697,7 +688,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (intype))
{
tree rval;
- rval = build_type_conversion (type, e, 1);
+ rval = build_type_conversion (type, e);
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
@@ -733,7 +724,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
tree rval;
- rval = build_type_conversion (type, e, 1);
+ rval = build_type_conversion (type, e);
if (rval)
return rval;
else
@@ -776,22 +767,14 @@ ocp_convert (type, expr, convtype, flags)
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
else
- ctor = build_method_call (NULL_TREE,
- complete_ctor_identifier,
- build_tree_list (NULL_TREE, ctor),
- TYPE_BINFO (type), flags);
+ ctor = build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ build_tree_list (NULL_TREE, ctor),
+ TYPE_BINFO (type), flags);
if (ctor)
return build_cplus_new (type, ctor);
}
- /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
- then it won't be hashed and hence compare as not equal,
- even when it is. */
- if (code == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type)
- && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type)))
- return e;
-
if (flags & LOOKUP_COMPLAIN)
error ("conversion from `%T' to non-scalar type `%T' requested",
TREE_TYPE (expr), type);
@@ -864,7 +847,7 @@ convert_to_void (expr, implicit)
case NON_LVALUE_EXPR:
case NOP_EXPR:
- /* These have already decayed to rvalue. */
+ /* These have already decayed to rvalue. */
break;
case CALL_EXPR: /* we have a special meaning for volatile void fn() */
@@ -1021,26 +1004,18 @@ convert_force (type, expr, convtype)
allowed (references private members, etc).
If no conversion exists, NULL_TREE is returned.
- If (FOR_SURE & 1) is non-zero, then we allow this type conversion
- to take place immediately. Otherwise, we build a SAVE_EXPR
- which can be evaluated if the results are ever needed.
-
- Changes to this functions should be mirrored in user_harshness.
-
FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */
tree
-build_type_conversion (xtype, expr, for_sure)
+build_type_conversion (xtype, expr)
tree xtype, expr;
- int for_sure;
{
/* C++: check to see if we can convert this aggregate type
into the required type. */
- return build_user_type_conversion
- (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
+ return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
}
/* Convert the given EXPR to one of a group of types suitable for use in an
@@ -1186,10 +1161,10 @@ type_promotes_to (type)
{
int precision = MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node));
- tree totype = type_for_size (precision, 0);
+ tree totype = c_common_type_for_size (precision, 0);
if (TREE_UNSIGNED (type)
&& ! int_fits_type_p (TYPE_MAX_VALUE (type), totype))
- type = type_for_size (precision, 1);
+ type = c_common_type_for_size (precision, 1);
else
type = totype;
}
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 5c891a5..be31ac2 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -41,34 +41,34 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "../hash.h"
+#include "hashtab.h"
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
#include "c-pragma.h"
#include "diagnostic.h"
-
-extern const struct attribute_spec *lang_attribute_table;
+#include "debug.h"
+#include "timevar.h"
+#include "input.h"
static tree grokparms PARAMS ((tree));
static const char *redeclaration_error_message PARAMS ((tree, tree));
-static void push_binding_level PARAMS ((struct binding_level *, int,
+static void push_binding_level PARAMS ((struct cp_binding_level *, int,
int));
static void pop_binding_level PARAMS ((void));
static void suspend_binding_level PARAMS ((void));
-static void resume_binding_level PARAMS ((struct binding_level *));
-static struct binding_level *make_binding_level PARAMS ((void));
+static void resume_binding_level PARAMS ((struct cp_binding_level *));
+static struct cp_binding_level *make_binding_level PARAMS ((void));
static void declare_namespace_level PARAMS ((void));
static int decl_jump_unsafe PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
static int ambi_op_p PARAMS ((enum tree_code));
static int unary_op_p PARAMS ((enum tree_code));
-static tree store_bindings PARAMS ((tree, tree));
+static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
static tree lookup_tag_reverse PARAMS ((tree, tree));
-static tree obscure_complex_init PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
@@ -79,60 +79,54 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree follow_tag_typedef PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
- struct binding_level *, int));
+ struct cp_binding_level *, int));
static void set_identifier_type_value_with_scope
- PARAMS ((tree, tree, struct binding_level *));
+ PARAMS ((tree, tree, struct cp_binding_level *));
static void record_unknown_type PARAMS ((tree, const char *));
static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
- enum built_in_class, const char *));
+ enum built_in_class, const char *,
+ tree));
static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
int));
-static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct binding_level*));
+static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct cp_binding_level*));
static void check_for_uninitialized_const_var PARAMS ((tree));
-static unsigned long typename_hash PARAMS ((hash_table_key));
-static bool typename_compare PARAMS ((hash_table_key, hash_table_key));
-static void push_binding PARAMS ((tree, tree, struct binding_level*));
+static hashval_t typename_hash PARAMS ((const void *));
+static int typename_compare PARAMS ((const void *, const void *));
+static void push_binding PARAMS ((tree, tree, struct cp_binding_level*));
static int add_binding PARAMS ((tree, tree));
static void pop_binding PARAMS ((tree, tree));
static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
-static tree find_binding PARAMS ((tree, tree));
-static tree select_decl PARAMS ((tree, int));
+static cxx_binding *find_binding (tree, tree, cxx_binding *);
+static tree select_decl (cxx_binding *, int);
static int lookup_flags PARAMS ((int, int));
static tree qualify_lookup PARAMS ((tree, int));
static tree record_builtin_java_type PARAMS ((const char *, int));
static const char *tag_name PARAMS ((enum tag_types code));
static void find_class_binding_level PARAMS ((void));
-static struct binding_level *innermost_nonclass_level PARAMS ((void));
+static struct cp_binding_level *innermost_nonclass_level PARAMS ((void));
static void warn_about_implicit_typename_lookup PARAMS ((tree, tree));
static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
static int walk_globals_r PARAMS ((tree, void *));
-static void add_decl_to_level PARAMS ((tree, struct binding_level *));
+static int walk_vtables_r PARAMS ((tree, void*));
+static void add_decl_to_level PARAMS ((tree, struct cp_binding_level *));
static tree make_label_decl PARAMS ((tree, int));
static void use_label PARAMS ((tree));
-static void check_previous_goto_1 PARAMS ((tree, struct binding_level *, tree,
+static void check_previous_goto_1 PARAMS ((tree, struct cp_binding_level *, tree,
const char *, int));
static void check_previous_goto PARAMS ((struct named_label_use_list *));
-static void check_switch_goto PARAMS ((struct binding_level *));
+static void check_switch_goto PARAMS ((struct cp_binding_level *));
static void check_previous_gotos PARAMS ((tree));
static void pop_label PARAMS ((tree, tree));
static void pop_labels PARAMS ((tree));
static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
static void layout_var_decl PARAMS ((tree));
static void maybe_commonize_var PARAMS ((tree));
-static tree check_initializer PARAMS ((tree, tree));
+static tree check_initializer (tree, tree, int);
static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
-static void push_cp_function_context PARAMS ((struct function *));
-static void pop_cp_function_context PARAMS ((struct function *));
-static void mark_binding_level PARAMS ((void *));
-static void mark_named_label_lists PARAMS ((void *, void *));
-static void mark_cp_function_context PARAMS ((struct function *));
-static void mark_saved_scope PARAMS ((void *));
-static void mark_lang_function PARAMS ((struct cp_language_function *));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
-static void destroy_local_var PARAMS ((tree));
static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
static void begin_destructor_body PARAMS ((void));
@@ -150,10 +144,10 @@ static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static void store_parm_decls PARAMS ((tree));
static int cp_missing_noreturn_ok_p PARAMS ((tree));
-
-#if defined (DEBUG_CP_BINDING_LEVELS)
-static void indent PARAMS ((void));
-#endif
+static void initialize_local_var (tree, tree);
+static void expand_static_init (tree, tree);
+static tree next_initializable_field (tree);
+static tree reshape_init (tree, tree *);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
@@ -208,17 +202,17 @@ tree cp_global_trees[CPTI_MAX];
/* Indicates that there is a type value in some namespace, although
that is not necessarily in scope at the moment. */
-static tree global_type_node;
+static GTY(()) tree global_type_node;
-/* Expect only namespace names now. */
+/* Expect only namespace names now. */
static int only_namespace_names;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
-struct named_label_use_list
+struct named_label_use_list GTY(())
{
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
const char *filename_o_goto;
@@ -249,9 +243,9 @@ tree last_function_parms;
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
-struct named_label_list
+struct named_label_list GTY(())
{
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
tree label_decl;
@@ -262,36 +256,7 @@ struct named_label_list
};
#define named_labels cp_function_chain->x_named_labels
-
-/* Nonzero means use the ISO C94 dialect of C. */
-
-int flag_isoc94;
-
-/* Nonzero means use the ISO C99 dialect of C. */
-
-int flag_isoc99;
-
-/* Nonzero means we are a hosted implementation for code shared with C. */
-
-int flag_hosted = 1;
-
-/* Nonzero means add default format_arg attributes for functions not
- in ISO C. */
-
-int flag_noniso_default_format_attributes = 1;
-
-/* Nonzero if we want to conserve space in the .o files. We do this
- by putting uninitialized data and runtime initialized data into
- .common instead of .data at the expense of not flagging multiple
- definitions. */
-extern int flag_conserve_space;
-/* C and C++ flags are in decl2.c. */
-
-/* A expression of value 0 with the same precision as a sizetype
- node, but signed. */
-tree signed_size_zero_node;
-
/* The name of the anonymous namespace, throughout this translation
unit. */
tree anonymous_namespace_name;
@@ -317,7 +282,254 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
being flagged as deprecated or reported as using deprecated
types. */
int adding_implicit_members = 0;
+
+/* True if a declaration with an `extern' linkage specifier is being
+ processed. */
+bool have_extern_spec;
+
+/* Compute the chain index of a binding_entry given the HASH value of its
+ name and the total COUNT of chains. COUNT is assumed to be a power
+ of 2. */
+#define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
+
+/* A free list of "binding_entry"s awaiting for re-use. */
+static GTY((deletable(""))) binding_entry free_binding_entry;
+
+/* Create a binding_entry object for (NAME, TYPE). */
+static inline binding_entry
+binding_entry_make (tree name, tree type)
+{
+ binding_entry entry;
+
+ if (free_binding_entry)
+ {
+ entry = free_binding_entry;
+ free_binding_entry = entry->chain;
+ }
+ else
+ entry = ggc_alloc (sizeof (struct binding_entry_s));
+
+ entry->name = name;
+ entry->type = type;
+
+ return entry;
+}
+
+/* Put ENTRY back on the free list. */
+static inline void
+binding_entry_free (binding_entry entry)
+{
+ entry->chain = free_binding_entry;
+ free_binding_entry = entry;
+}
+
+/* The datatype used to implement the mapping from names to types at
+ a given scope. */
+struct binding_table_s GTY(())
+{
+ /* Array of chains of "binding_entry"s */
+ binding_entry * GTY((length ("%h.chain_count"))) chain;
+
+ /* The number of chains in this table. This is the length of the
+ the member "chaiin" considered as an array. */
+ size_t chain_count;
+
+ /* Number of "binding_entry"s in this table. */
+ size_t entry_count;
+};
+
+/* These macros indicate the initial chains count for binding_table. */
+#define SCOPE_DEFAULT_HT_SIZE (1 << 3)
+#define CLASS_SCOPE_HT_SIZE (1 << 3)
+#define NAMESPACE_ORDINARY_HT_SIZE (1 << 5)
+#define NAMESPACE_STD_HT_SIZE (1 << 8)
+#define GLOBAL_SCOPE_HT_SIZE (1 << 8)
+
+/* Construct TABLE with an initial CHAIN_COUNT. */
+static inline void
+binding_table_construct (binding_table table, size_t chain_count)
+{
+ table->chain_count = chain_count;
+ table->entry_count = 0;
+ table->chain = ggc_alloc_cleared
+ (table->chain_count * sizeof (binding_entry));
+}
+
+/* Free TABLE by making its entries ready for reuse. */
+static inline void
+binding_table_free (binding_table table)
+{
+ size_t i;
+ if (table == NULL)
+ return;
+
+ for (i = 0; i < table->chain_count; ++i)
+ {
+ while (table->chain[i] != NULL)
+ {
+ binding_entry entry = table->chain[i];
+ table->chain[i] = entry->chain;
+ binding_entry_free (entry);
+ }
+ }
+ table->entry_count = 0;
+}
+
+/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
+static inline binding_table
+binding_table_new (size_t chain_count)
+{
+ binding_table table = ggc_alloc (sizeof (struct binding_table_s));
+ binding_table_construct (table, chain_count);
+ return table;
+}
+
+/* Expand TABLE to twice its current chain_count. */
+static void
+binding_table_expand (binding_table table)
+{
+ const size_t old_chain_count = table->chain_count;
+ const size_t old_entry_count = table->entry_count;
+ const size_t new_chain_count = 2 * old_chain_count;
+ binding_entry *old_chains = table->chain;
+ size_t i;
+
+ binding_table_construct (table, new_chain_count);
+ for (i = 0; i < old_chain_count; ++i)
+ {
+ binding_entry entry = old_chains[i];
+ for (; entry != NULL; entry = old_chains[i])
+ {
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
+ const size_t j = ENTRY_INDEX (hash, new_chain_count);
+
+ old_chains[i] = entry->chain;
+ entry->chain = table->chain[j];
+ table->chain[j] = entry;
+ }
+ }
+ table->entry_count = old_entry_count;
+}
+
+/* Insert a binding for NAME to TYPe into TABLE. */
+static inline void
+binding_table_insert (binding_table table, tree name, tree type)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ const size_t i = ENTRY_INDEX (hash, table->chain_count);
+ binding_entry entry = binding_entry_make (name, type);
+
+ entry->chain = table->chain[i];
+ table->chain[i] = entry;
+ ++table->entry_count;
+
+ if (3 * table->chain_count < 5 * table->entry_count)
+ binding_table_expand (table);
+}
+
+/* Return the binding_entry, if any, that maps NAME. */
+binding_entry
+binding_table_find (binding_table table, tree name)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+
+ while (entry != NULL && entry->name != name)
+ entry = entry->chain;
+
+ return entry;
+}
+
+/* Return the binding_entry, if any, that maps name to an anonymous type. */
+static inline tree
+binding_table_find_anon_type (binding_table table, tree name)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+
+ while (entry != NULL && TYPE_IDENTIFIER (entry->type) != name)
+ entry = entry->chain;
+
+ return entry ? entry->type : NULL;
+}
+
+/* Return the binding_entry, if any, that has TYPE as target. If NAME
+ is non-null, then set the domain and rehash that entry. */
+static inline binding_entry
+binding_table_reverse_maybe_remap (binding_table table, tree type, tree name)
+{
+ const size_t chain_count = table->chain_count;
+ binding_entry entry = NULL;
+ binding_entry *p;
+ size_t i;
+
+ for (i = 0; i < chain_count && entry == NULL; ++i)
+ {
+ p = &table->chain[i];
+ while (*p != NULL && entry == NULL)
+ if ((*p)->type == type)
+ entry = *p;
+ else
+ p = &(*p)->chain;
+ }
+
+ if (entry != NULL && name != NULL && entry->name != name)
+ {
+ /* Remove the bucket from the previous chain. */
+ *p = (*p)->chain;
+
+ /* Remap the name type to type. */
+ i = ENTRY_INDEX (IDENTIFIER_HASH_VALUE (name), chain_count);
+ entry->chain = table->chain[i];
+ entry->name = name;
+ table->chain[i] = entry;
+ }
+
+ return entry;
+}
+
+/* Remove from TABLE all entries that map to anonymous enums or
+ class-types. */
+static void
+binding_table_remove_anonymous_types (binding_table table)
+{
+ const size_t chain_count = table->chain_count;
+ size_t i;
+
+ for (i = 0; i < chain_count; ++i)
+ {
+ binding_entry *p = &table->chain[i];
+
+ while (*p != NULL)
+ if (ANON_AGGRNAME_P ((*p)->name))
+ {
+ binding_entry e = *p;
+ *p = (*p)->chain;
+ --table->entry_count;
+ binding_entry_free (e);
+ }
+ else
+ p = &(*p)->chain;
+ }
+}
+
+/* Apply PROC -- with DATA -- to all entries in TABLE. */
+void
+binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
+{
+ const size_t chain_count = table->chain_count;
+ size_t i;
+
+ for (i = 0; i < chain_count; ++i)
+ {
+ binding_entry entry = table->chain[i];
+ for (; entry != NULL; entry = entry->chain)
+ proc (entry, data);
+ }
+}
+
+
/* For each binding contour we allocate a binding_level structure
which records the names defined in that contour.
Contours include:
@@ -342,7 +554,7 @@ int adding_implicit_members = 0;
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-struct binding_level
+struct cp_binding_level GTY(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order
@@ -350,21 +562,26 @@ struct binding_level
are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
- /* A list of structure, union and enum definitions, for looking up
- tag names.
- It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- or ENUMERAL_TYPE node.
+ /* Count of elements in names chain. */
+ size_t names_size;
+
+ /* A chain of NAMESPACE_DECL nodes. */
+ tree namespaces;
+
+ /* An array of static functions and variables (for namespaces only) */
+ varray_type static_decls;
- C++: the TREE_VALUE nodes can be simple types for
- component_bindings. */
- tree tags;
+ /* A chain of VTABLE_DECL nodes. */
+ tree vtables;
- /* A list of USING_DECL nodes. */
+ /* A dictionary for looking up enums or class-types names. */
+ binding_table type_decls;
+
+ /* A list of USING_DECL nodes. */
tree usings;
/* A list of used namespaces. PURPOSE is the namespace,
- VALUE the common ancestor with this binding_level's namespace. */
+ VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
/* If this binding level is the binding level for a class, then
@@ -392,7 +609,7 @@ struct binding_level
tree this_class;
/* The binding level which this one is contained in (inherits from). */
- struct binding_level *level_chain;
+ struct cp_binding_level *level_chain;
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ISO-conforming code, but might
@@ -443,13 +660,15 @@ struct binding_level
/* Three bits left for this word. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
/* Binding depth at which this level began. */
unsigned binding_depth;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
};
-#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
+#define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
+
+/* True if SCOPE designates the global scope binding contour. */
+#define global_scope_p(SCOPE) \
+ ((SCOPE) == NAMESPACE_LEVEL (global_namespace))
/* The binding level currently in effect. */
@@ -464,13 +683,7 @@ struct binding_level
/* A chain of binding_level structures awaiting reuse. */
-static struct binding_level *free_binding_level;
-
-/* The outermost binding level, for names of file scope.
- This is created when the compiler is started and exists
- through the entire run. */
-
-static struct binding_level *global_binding_level;
+static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
@@ -480,46 +693,52 @@ static int keep_next_level_flag;
UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
time the VAR_DECL was declared, the type was incomplete. */
-static tree incomplete_vars;
+static GTY(()) tree incomplete_vars;
+
+#ifndef ENABLE_SCOPE_CHECKING
+# define ENABLE_SCOPE_CHECKING 0
+#else
+# define ENABLE_SCOPE_CHECKING 1
+#endif
-#if defined(DEBUG_CP_BINDING_LEVELS)
-static int binding_depth = 0;
+static unsigned binding_depth = 0;
static int is_class_level = 0;
static void
-indent ()
+indent (unsigned depth)
{
- register unsigned i;
+ unsigned i;
- for (i = 0; i < binding_depth*2; i++)
+ for (i = 0; i < depth * 2; i++)
putc (' ', stderr);
}
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-static tree pushdecl_with_scope PARAMS ((tree, struct binding_level *));
+static tree pushdecl_with_scope PARAMS ((tree, struct cp_binding_level *));
static void
push_binding_level (newlevel, tag_transparent, keep)
- struct binding_level *newlevel;
+ struct cp_binding_level *newlevel;
int tag_transparent, keep;
{
/* Add this level to the front of the chain (stack) of levels that
are active. */
- memset ((char*) newlevel, 0, sizeof (struct binding_level));
+ memset ((char*) newlevel, 0, sizeof (struct cp_binding_level));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
newlevel->keep = keep;
-#if defined(DEBUG_CP_BINDING_LEVELS)
- newlevel->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "push %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", newlevel, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ newlevel->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("push %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) newlevel, lineno);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
/* Find the innermost enclosing class scope, and reset
@@ -528,7 +747,7 @@ push_binding_level (newlevel, tag_transparent, keep)
static void
find_class_binding_level ()
{
- struct binding_level *level = current_binding_level;
+ struct cp_binding_level *level = current_binding_level;
while (level && level->parm_flag != 2)
level = level->level_chain;
@@ -541,34 +760,34 @@ find_class_binding_level ()
static void
pop_binding_level ()
{
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ /* Cannot pop a level, if there are none left to pop. */
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Pop the current level, and free the structure for reuse. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot pop a level, if there are none left to pop. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim ("pop %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) current_binding_level, lineno);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Pop the current level, and free the structure for reuse. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "pop %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
{
- register struct binding_level *level = current_binding_level;
+ register struct cp_binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
-#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */
- if (level->binding_depth != binding_depth)
- abort ();
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (level->parm_flag != 2)
+ binding_table_free (level->type_decls);
+ else
+ level->type_decls = NULL;
+ my_friendly_assert (!ENABLE_SCOPE_CHECKING
+ || level->binding_depth == binding_depth, 20030529);
free_binding_level = level;
find_class_binding_level ();
}
@@ -580,58 +799,56 @@ suspend_binding_level ()
if (class_binding_level)
current_binding_level = class_binding_level;
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Suspend the current level. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot suspend a level, if there are none left to suspend. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim("suspend %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) current_binding_level, lineno);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Suspend the current level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "suspend %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
current_binding_level = current_binding_level->level_chain;
find_class_binding_level ();
}
static void
resume_binding_level (b)
- struct binding_level *b;
+ struct cp_binding_level *b;
{
/* Resuming binding levels is meant only for namespaces,
- and those cannot nest into classes. */
+ and those cannot nest into classes. */
my_friendly_assert(!class_binding_level, 386);
/* Also, resuming a non-directly nested namespace is a no-no. */
my_friendly_assert(b->level_chain == current_binding_level, 386);
current_binding_level = b;
-#if defined(DEBUG_CP_BINDING_LEVELS)
- b->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "resume %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", b, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ b->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("resume %s level %p line %d\n",
+ (is_class_level) ? "class" : "block", (void *) b, lineno);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
-/* Create a new `struct binding_level'. */
+/* Create a new `struct cp_binding_level'. */
static
-struct binding_level *
+struct cp_binding_level *
make_binding_level ()
{
/* NOSTRICT */
- return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ return (struct cp_binding_level *) ggc_alloc (sizeof (struct cp_binding_level));
}
/* Nonzero if we are currently in the global binding level. */
@@ -639,15 +856,15 @@ make_binding_level ()
int
global_bindings_p ()
{
- return current_binding_level == global_binding_level;
+ return global_scope_p (current_binding_level);
}
/* Return the innermost binding level that is not for a class scope. */
-static struct binding_level *
+static struct cp_binding_level *
innermost_nonclass_level ()
{
- struct binding_level *b;
+ struct cp_binding_level *b;
b = current_binding_level;
while (b->parm_flag == 2)
@@ -665,7 +882,7 @@ innermost_nonclass_level ()
int
toplevel_bindings_p ()
{
- struct binding_level *b = innermost_nonclass_level ();
+ struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p || b->template_parms_p;
}
@@ -677,12 +894,12 @@ toplevel_bindings_p ()
int
namespace_bindings_p ()
{
- struct binding_level *b = innermost_nonclass_level ();
+ struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p;
}
-/* If KEEP is non-zero, make a BLOCK node for the next binding level,
+/* If KEEP is nonzero, make a BLOCK node for the next binding level,
unconditionally. Otherwise, use the normal logic to decide whether
or not to create a BLOCK. */
@@ -701,7 +918,7 @@ kept_level_p ()
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
|| current_binding_level->names != NULL_TREE
- || (current_binding_level->tags != NULL_TREE
+ || (current_binding_level->type_decls != NULL
&& !current_binding_level->tag_transparent));
}
@@ -711,7 +928,7 @@ declare_namespace_level ()
current_binding_level->namespace_p = 1;
}
-/* Returns non-zero if this scope was created to store template
+/* Returns nonzero if this scope was created to store template
parameters. */
int
@@ -731,7 +948,7 @@ current_tmpl_spec_kind (n_class_scopes)
int n_template_parm_scopes = 0;
int seen_specialization_p = 0;
int innermost_specialization_p = 0;
- struct binding_level *b;
+ struct cp_binding_level *b;
/* Scan through the template parameter scopes. */
for (b = current_binding_level; b->template_parms_p; b = b->level_chain)
@@ -742,7 +959,7 @@ current_tmpl_spec_kind (n_class_scopes)
template <class T> template <> ...
- which is always illegal since [temp.expl.spec] forbids the
+ which is always invalid since [temp.expl.spec] forbids the
specialization of a class member template if the enclosing
class templates are not explicitly specialized as well. */
if (b->template_spec_p)
@@ -779,7 +996,7 @@ current_tmpl_spec_kind (n_class_scopes)
template <class T> void R<T>::S<T>::f(int);
- This is illegal; there needs to be one set of template
+ This is invalid; there needs to be one set of template
parameters for each class. */
return tsk_insufficient_parms;
else if (n_template_parm_scopes == n_class_scopes)
@@ -824,17 +1041,13 @@ void
pushlevel (tag_transparent)
int tag_transparent;
{
- struct binding_level *newlevel;
+ struct cp_binding_level *newlevel;
if (cfun && !doing_semantic_analysis_p ())
return;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_CP_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
@@ -919,14 +1132,12 @@ note_level_for_catch ()
}
/* 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)
+ this is the `struct cp_binding_level' for the block. */
+#define BINDING_LEVEL(NODE) ((NODE)->scope.level)
-/* A free list of CPLUS_BINDING nodes, connected by their
- TREE_CHAINs. */
+/* A free list of "cxx_binding"s, connected by their PREVIOUS. */
-static tree free_bindings;
+static GTY((deletable (""))) cxx_binding *free_bindings;
/* Make DECL the innermost binding for ID. The LEVEL is the binding
level at which this declaration is being bound. */
@@ -935,17 +1146,17 @@ static void
push_binding (id, decl, level)
tree id;
tree decl;
- struct binding_level* level;
+ struct cp_binding_level* level;
{
- tree binding;
+ cxx_binding *binding;
if (free_bindings)
{
binding = free_bindings;
- free_bindings = TREE_CHAIN (binding);
+ free_bindings = binding->previous;
}
else
- binding = make_node (CPLUS_BINDING);
+ binding = cxx_binding_make ();
/* Now, fill in the binding information. */
BINDING_VALUE (binding) = decl;
@@ -956,7 +1167,7 @@ push_binding (id, decl, level)
BINDING_HAS_LEVEL_P (binding) = 1;
/* And put it on the front of the list of bindings for ID. */
- TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ binding->previous = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
@@ -965,15 +1176,16 @@ push_binding (id, decl, level)
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. */
+ valid here. Returns nonzero if the new binding was successful. */
static int
add_binding (id, decl)
tree id;
tree decl;
{
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
int ok = 1;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
@@ -1013,11 +1225,18 @@ add_binding (id, decl)
type to which it already refers. */
ok = 0;
/* There can be two block-scope declarations of the same variable,
- so long as they are `extern' declarations. */
+ so long as they are `extern' declarations. However, there cannot
+ be two declarations of the same static data member:
+
+ [class.mem]
+
+ A member shall not be declared twice in the
+ member-specification. */
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
&& DECL_EXTERNAL (decl)
- && DECL_EXTERNAL (BINDING_VALUE (binding)))
+ && DECL_EXTERNAL (BINDING_VALUE (binding))
+ && !DECL_CLASS_SCOPE_P (decl))
{
duplicate_decls (decl, BINDING_VALUE (binding));
ok = 0;
@@ -1030,7 +1249,7 @@ add_binding (id, decl)
ok = 0;
}
- return ok;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
/* Add DECL to the list of things declared in B. */
@@ -1038,12 +1257,34 @@ add_binding (id, decl)
static void
add_decl_to_level (decl, b)
tree decl;
- struct binding_level *b;
+ struct cp_binding_level *b;
{
- /* We build up the list in reverse order, and reverse it later if
- necessary. */
- TREE_CHAIN (decl) = b->names;
- b->names = decl;
+ if (TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl))
+ {
+ TREE_CHAIN (decl) = b->namespaces;
+ b->namespaces = decl;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
+ {
+ TREE_CHAIN (decl) = b->vtables;
+ b->vtables = decl;
+ }
+ else
+ {
+ /* We build up the list in reverse order, and reverse it later if
+ necessary. */
+ TREE_CHAIN (decl) = b->names;
+ b->names = decl;
+ b->names_size++;
+
+ /* If appropriate, add decl to separate list of statics */
+ if (b->namespace_p)
+ if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
+ VARRAY_PUSH_TREE (b->static_decls, decl);
+ }
}
/* Bind DECL to ID in the current_binding_level, assumed to be a local
@@ -1057,7 +1298,7 @@ push_local_binding (id, decl, flags)
tree decl;
int flags;
{
- struct binding_level *b;
+ struct cp_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. */
@@ -1098,11 +1339,12 @@ push_class_binding (id, decl)
tree decl;
{
int result = 1;
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
tree context;
+ timevar_push (TV_NAME_LOOKUP);
/* 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
+ this is an invalid redeclaration of a name already used for some
other purpose. */
note_name_declared_in_class (id, decl);
@@ -1152,7 +1394,7 @@ push_class_binding (id, decl)
in this class. */
INHERITED_VALUE_BINDING_P (binding) = 1;
- return result;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
/* Remove the binding for DECL which should be the innermost binding
@@ -1163,7 +1405,7 @@ pop_binding (id, decl)
tree id;
tree decl;
{
- tree binding;
+ cxx_binding *binding;
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
@@ -1175,7 +1417,7 @@ pop_binding (id, decl)
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
- my_friendly_assert (binding != NULL_TREE, 0);
+ my_friendly_assert (binding != NULL, 0);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that binding. */
@@ -1190,10 +1432,10 @@ pop_binding (id, decl)
{
/* We're completely done with the innermost binding for this
identifier. Unhook it from the list of bindings. */
- IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+ IDENTIFIER_BINDING (id) = binding->previous;
/* Add it to the free list. */
- TREE_CHAIN (binding) = free_bindings;
+ binding->previous = free_bindings;
free_bindings = binding;
/* Clear the BINDING_LEVEL so the garbage collector doesn't walk
@@ -1276,21 +1518,21 @@ poplevel (keep, reverse, functionbody)
tree decls;
int tmp = functionbody;
int real_functionbody;
- tree tags;
tree subblocks;
tree block = NULL_TREE;
tree decl;
int leaving_for_scope;
+ timevar_push (TV_NAME_LOOKUP);
+
if (cfun && !doing_semantic_analysis_p ())
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
my_friendly_assert (current_binding_level->parm_flag != 2,
19990916);
real_functionbody = (current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody);
- tags = functionbody >= 0 ? current_binding_level->tags : 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
my_friendly_assert (!current_binding_level->class_shadowed,
@@ -1308,7 +1550,7 @@ poplevel (keep, reverse, functionbody)
under constraints of next binding contour. */
if (cfun && !functionbody)
{
- struct binding_level *level_chain;
+ struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
@@ -1410,8 +1652,8 @@ poplevel (keep, reverse, functionbody)
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
tree ns_binding;
if (!outer_binding)
@@ -1466,7 +1708,7 @@ poplevel (keep, reverse, functionbody)
current_binding_level->level_chain->
dead_vars_from_for);
- /* Although we don't pop the CPLUS_BINDING, we do clear
+ /* Although we don't pop the cxx_binding, we do clear
its BINDING_LEVEL since the level is going away now. */
BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
= 0;
@@ -1574,7 +1816,7 @@ poplevel (keep, reverse, functionbody)
block = poplevel (keep, reverse, functionbody);
}
- return block;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
/* Delete the node BLOCK from the current binding level.
@@ -1631,14 +1873,10 @@ set_block (block)
void
pushlevel_class ()
{
- register struct binding_level *newlevel;
+ register struct cp_binding_level *newlevel;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_CP_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
@@ -1646,9 +1884,8 @@ pushlevel_class ()
else
newlevel = make_binding_level ();
-#if defined(DEBUG_CP_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
push_binding_level (newlevel, 0, 0);
@@ -1662,9 +1899,11 @@ pushlevel_class ()
void
poplevel_class ()
{
- register struct binding_level *level = class_binding_level;
+ register struct cp_binding_level *level = class_binding_level;
tree shadowed;
+ timevar_push (TV_NAME_LOOKUP);
+
my_friendly_assert (level != 0, 354);
/* If we're leaving a toplevel class, don't bother to do the setting
@@ -1674,7 +1913,7 @@ poplevel_class ()
next time we're entering a class scope, it is the same class. */
if (current_class_depth != 1)
{
- struct binding_level* b;
+ struct cp_binding_level* b;
/* Clear out our IDENTIFIER_CLASS_VALUEs. */
for (shadowed = level->class_shadowed;
@@ -1693,15 +1932,15 @@ poplevel_class ()
shadowed;
shadowed = TREE_CHAIN (shadowed))
{
- tree t;
+ cxx_binding *binding;
- t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
- while (t && BINDING_LEVEL (t) != b)
- t = TREE_CHAIN (t);
+ binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (binding && BINDING_LEVEL (binding) != b)
+ binding = binding->previous;
- if (t)
+ if (binding)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
- = BINDING_VALUE (t);
+ = BINDING_VALUE (binding);
}
}
else
@@ -1724,11 +1963,12 @@ poplevel_class ()
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
pop_binding_level ();
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
@@ -1748,7 +1988,7 @@ clear_identifier_class_values ()
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
}
-/* Returns non-zero if T is a virtual function table. */
+/* Returns nonzero if T is a virtual function table. */
int
vtable_decl_p (t, data)
@@ -1758,7 +1998,7 @@ vtable_decl_p (t, data)
return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
}
-/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+/* Returns nonzero if T is a TYPE_DECL for a type with virtual
functions. */
int
@@ -1780,6 +2020,50 @@ cp_namespace_decls (ns)
return NAMESPACE_LEVEL (ns)->names;
}
+struct walk_globals_data {
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+};
+
+/* Walk the vtable declarations in NAMESPACE. Whenever one is found
+ for which P returns nonzero, call F with its address. If any call
+ to F returns a nonzero value, return a nonzero value. */
+
+static int
+walk_vtables_r (namespace, data)
+ tree namespace;
+ void *data;
+{
+ struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+ walk_globals_fn f = wgd->f;
+ void *d = wgd->data;
+ tree decl = NAMESPACE_LEVEL (namespace)->vtables;
+ int result = 0;
+
+ for (; decl ; decl = TREE_CHAIN (decl))
+ result |= (*f) (&decl, d);
+
+ return result;
+}
+
+/* Walk the vtable declarations. Whenever one is found for which P
+ returns nonzero, call F with its address. If any call to F
+ returns a nonzero value, return a nonzero value. */
+int
+walk_vtables (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_vtables_r, &wgd);
+}
+
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
@@ -1789,22 +2073,13 @@ walk_namespaces_r (namespace, f, data)
walk_namespaces_fn f;
void *data;
{
- tree current;
int result = 0;
+ tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
- for (current = cp_namespace_decls (namespace);
- current;
- current = TREE_CHAIN (current))
- {
- if (TREE_CODE (current) != NAMESPACE_DECL
- || DECL_NAMESPACE_ALIAS (current))
- continue;
-
- /* We found a namespace. */
- result |= walk_namespaces_r (current, f, data);
- }
+ for (; current; current = TREE_CHAIN (current))
+ result |= walk_namespaces_r (current, f, data);
return result;
}
@@ -1820,15 +2095,9 @@ walk_namespaces (f, 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. */
+ for which P returns nonzero, call F with its address. If any call
+ to F returns a nonzero value, return a nonzero value. */
static int
walk_globals_r (namespace, data)
@@ -1861,8 +2130,8 @@ walk_globals_r (namespace, data)
}
/* 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. */
+ returns nonzero, call F with its address. If any call to F
+ returns a nonzero value, return a nonzero value. */
int
walk_globals (p, f, data)
@@ -1887,106 +2156,68 @@ wrapup_globals_for_namespace (namespace, data)
tree namespace;
void *data;
{
- tree globals = cp_namespace_decls (namespace);
- int len = list_length (globals);
- tree *vec = (tree *) alloca (sizeof (tree) * len);
- int i;
- int result;
- tree decl;
+ struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+ varray_type statics = level->static_decls;
+ tree *vec = &VARRAY_TREE (statics, 0);
+ int len = VARRAY_ACTIVE_SIZE (statics);
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;
+ return wrapup_global_declarations (vec, len);
}
-/* Mark ARG (which is really a struct binding_level **) for GC. */
+/* For debugging. */
+static int no_print_functions = 0;
+static int no_print_builtins = 0;
+/* Called from print_binding_level through binding_table_foreach to
+ print the content of binding ENTRY. DATA is a pointer to line offset
+ marker. */
static void
-mark_binding_level (arg)
- void *arg;
+bt_print_entry (binding_entry entry, void *data)
{
- struct binding_level *lvl = *(struct binding_level **)arg;
+ int *p = (int *) data;
+ int len;
- for (; lvl; lvl = lvl->level_chain)
- {
- ggc_mark_tree (lvl->names);
- ggc_mark_tree (lvl->tags);
- ggc_mark_tree (lvl->usings);
- ggc_mark_tree (lvl->using_directives);
- ggc_mark_tree (lvl->class_shadowed);
- ggc_mark_tree (lvl->type_shadowed);
- ggc_mark_tree (lvl->shadowed_labels);
- ggc_mark_tree (lvl->blocks);
- ggc_mark_tree (lvl->this_class);
- ggc_mark_tree (lvl->dead_vars_from_for);
- }
-}
+ if (entry->name == NULL)
+ len = 3;
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ len = 2;
+ else
+ len = 4;
-static void
-mark_named_label_lists (labs, uses)
- void *labs;
- void *uses;
-{
- struct named_label_list *l = *(struct named_label_list **)labs;
- struct named_label_use_list *u = *(struct named_label_use_list **)uses;
+ *p += len;
- for (; l; l = l->next)
+ if (*p > 5)
{
- ggc_mark (l);
- mark_binding_level (&l->binding_level);
- ggc_mark_tree (l->old_value);
- ggc_mark_tree (l->label_decl);
- ggc_mark_tree (l->bad_decls);
+ fprintf (stderr, "\n\t");
+ *p = len;
+ }
+ if (entry->name == NULL)
+ {
+ print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
+ fprintf (stderr, ">");
+ }
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ print_node_brief (stderr, "", entry->type, 0);
+ else
+ {
+ print_node_brief (stderr, "<typedef", entry->name, 0);
+ print_node_brief (stderr, "", entry->type, 0);
+ fprintf (stderr, ">");
}
-
- for (; u; u = u->next)
- ggc_mark (u);
}
-
-/* For debugging. */
-static int no_print_functions = 0;
-static int no_print_builtins = 0;
void
print_binding_level (lvl)
- struct binding_level *lvl;
+ struct cp_binding_level *lvl;
{
tree t;
int i = 0, len;
@@ -2030,38 +2261,11 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->tags)
+ if (lvl->type_decls)
{
fprintf (stderr, " tags:\t");
i = 0;
- for (t = lvl->tags; t; t = TREE_CHAIN (t))
- {
- if (TREE_PURPOSE (t) == NULL_TREE)
- len = 3;
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- len = 2;
- else
- len = 4;
- i += len;
- if (i > 5)
- {
- fprintf (stderr, "\n\t");
- i = len;
- }
- if (TREE_PURPOSE (t) == NULL_TREE)
- {
- print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- else
- {
- print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- }
+ binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
if (i)
fprintf (stderr, "\n");
}
@@ -2087,10 +2291,10 @@ print_binding_level (lvl)
void
print_other_binding_stack (stack)
- struct binding_level *stack;
+ struct cp_binding_level *stack;
{
- struct binding_level *level;
- for (level = stack; level != global_binding_level; level = level->level_chain)
+ struct cp_binding_level *level;
+ for (level = stack; !global_scope_p (level); level = level->level_chain)
{
fprintf (stderr, "binding level ");
fprintf (stderr, HOST_PTR_PRINTF, level);
@@ -2102,13 +2306,14 @@ print_other_binding_stack (stack)
void
print_binding_stack ()
{
- struct binding_level *b;
+ struct cp_binding_level *b;
fprintf (stderr, "current_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
fprintf (stderr, "\nclass_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
- fprintf (stderr, "\nglobal_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
+ fprintf (stderr, "\nNAMESPACE_LEVEL (global_namespace)=");
+ fprintf (stderr, HOST_PTR_PRINTF,
+ (void *) NAMESPACE_LEVEL (global_namespace));
fprintf (stderr, "\n");
if (class_binding_level)
{
@@ -2124,104 +2329,95 @@ print_binding_stack ()
b = current_binding_level;
print_other_binding_stack (b);
fprintf (stderr, "global:\n");
- print_binding_level (global_binding_level);
+ print_binding_level (NAMESPACE_LEVEL (global_namespace));
}
-/* Namespace binding access routines: The namespace_bindings field of
- the identifier is polymorphic, with three possible values:
- NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
- indicating the BINDING_VALUE of global_namespace. */
+/* Namespace binding access routines. */
/* Check whether the a binding for the name to scope is known.
- Assumes that the bindings of the name are already a list
- of bindings. Returns the binding found, or NULL_TREE. */
+ Returns the binding found, or NULL. */
-static tree
-find_binding (name, scope)
- tree name;
- tree scope;
+static inline cxx_binding *
+find_binding (tree name, tree scope, cxx_binding *front)
{
- tree iter, prev = NULL_TREE;
+ cxx_binding *iter;
+ cxx_binding *prev = NULL;
- scope = ORIGINAL_NAMESPACE (scope);
+ timevar_push (TV_NAME_LOOKUP);
- for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
- iter = TREE_CHAIN (iter))
+ for (iter = front; iter; iter = iter->previous)
{
- my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
if (BINDING_SCOPE (iter) == scope)
{
/* Move binding found to the front of the list, so
- subsequent lookups will find it faster. */
+ subsequent lookups will find it faster. */
if (prev)
{
- TREE_CHAIN (prev) = TREE_CHAIN (iter);
- TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ prev->previous = iter->previous;
+ iter->previous = front;
IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
}
- return iter;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
}
prev = iter;
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
+}
+
+/* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */
+cxx_binding *
+cxx_scope_find_binding_for_name (tree scope, tree name)
+{
+ cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b)
+ {
+ scope = ORIGINAL_NAMESPACE (scope);
+ /* Fold-in case where NAME is used only once. */
+ if (scope == BINDING_SCOPE (b) && b->previous == NULL)
+ return b;
+ return find_binding (name, scope, b);
+ }
+ return b;
}
-/* Always returns a binding for name in scope. If the
- namespace_bindings is not a list, convert it to one first.
- If no binding is found, make a new one. */
-tree
-binding_for_name (name, scope)
- tree name;
- tree scope;
+/* Always returns a binding for name in scope.
+ If no binding is found, make a new one. */
+
+cxx_binding *
+binding_for_name (tree name, tree scope)
{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- tree result;
+ cxx_binding *result;
scope = ORIGINAL_NAMESPACE (scope);
-
- if (b && TREE_CODE (b) != CPLUS_BINDING)
- {
- /* Get rid of optimization for global scope. */
- IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
- BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- }
- if (b && (result = find_binding (name, scope)))
+ result = cxx_scope_find_binding_for_name (scope, name);
+ if (result)
return result;
- /* Not found, make a new one. */
- result = make_node (CPLUS_BINDING);
- TREE_CHAIN (result) = b;
- IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
- BINDING_SCOPE (result) = scope;
+ /* Not found, make a new one. */
+ result = cxx_binding_make ();
+ result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
BINDING_TYPE (result) = NULL_TREE;
BINDING_VALUE (result) = NULL_TREE;
+ BINDING_SCOPE (result) = scope;
+ result->is_local = false;
+ result->value_is_inherited = false;
+ result->has_level = false;
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
return result;
}
-/* Return the binding value for name in scope, considering that
- namespace_binding may or may not be a list of CPLUS_BINDINGS. */
+/* Return the binding value for name in scope. */
tree
-namespace_binding (name, scope)
- tree name;
- tree scope;
+namespace_binding (tree name, tree scope)
{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE)
- return NULL_TREE;
- if (scope == NULL_TREE)
- scope = global_namespace;
- if (TREE_CODE (b) != CPLUS_BINDING)
- return (scope == global_namespace) ? b : NULL_TREE;
- name = find_binding (name,scope);
- if (name == NULL_TREE)
- return name;
- return BINDING_VALUE (name);
+ cxx_binding *b =
+ cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
+
+ return b ? b->value : NULL_TREE;
}
-/* Set the binding value for name in scope. If modifying the binding
- of global_namespace is attempted, try to optimize it. */
+/* Set the binding value for name in scope. */
void
set_namespace_binding (name, scope, val)
@@ -2229,22 +2425,15 @@ set_namespace_binding (name, scope, val)
tree scope;
tree val;
{
- tree b;
+ cxx_binding *b;
+ timevar_push (TV_NAME_LOOKUP);
if (scope == NULL_TREE)
scope = global_namespace;
- if (scope == global_namespace)
- {
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
- {
- IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
- return;
- }
- }
b = binding_for_name (name, scope);
BINDING_VALUE (b) = val;
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
@@ -2258,9 +2447,12 @@ push_namespace (name)
int need_new = 1;
int implicit_use = 0;
int global = 0;
+
+ timevar_push (TV_NAME_LOOKUP);
+
if (!global_namespace)
{
- /* This must be ::. */
+ /* This must be ::. */
my_friendly_assert (name == get_identifier ("::"), 377);
global = 1;
}
@@ -2279,7 +2471,7 @@ push_namespace (name)
}
else
{
- /* Check whether this is an extended namespace definition. */
+ /* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
{
@@ -2295,7 +2487,7 @@ push_namespace (name)
if (need_new)
{
- /* Make a new namespace, binding the name to it. */
+ /* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
/* The global namespace is not pushed, and the global binding
level is set elsewhere. */
@@ -2306,6 +2498,13 @@ push_namespace (name)
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
+ current_binding_level->type_decls =
+ binding_table_new (name == std_identifier
+ ? NAMESPACE_STD_HT_SIZE
+ : NAMESPACE_ORDINARY_HT_SIZE);
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ name != std_identifier ? 10 : 200,
+ "Static declarations");
}
}
else
@@ -2313,8 +2512,10 @@ push_namespace (name)
if (implicit_use)
do_using_directive (d);
- /* Enter the name space. */
+ /* Enter the name space. */
current_namespace = d;
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Pop from the scope of the current namespace. */
@@ -2351,6 +2552,7 @@ void
pop_nested_namespace (ns)
tree ns;
{
+ timevar_push (TV_NAME_LOOKUP);
while (ns != global_namespace)
{
pop_namespace ();
@@ -2358,9 +2560,26 @@ pop_nested_namespace (ns)
}
pop_from_top_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
+/* Allocate storage for saving a C++ binding. */
+#define cxx_saved_binding_make() \
+ (ggc_alloc (sizeof (cxx_saved_binding)))
+
+struct cxx_saved_binding GTY(())
+{
+ /* Link that chains saved C++ bindings for a given name into a stack. */
+ cxx_saved_binding *previous;
+ /* The name of the current binding. */
+ tree identifier;
+ /* The binding we're saving. */
+ cxx_binding *binding;
+ tree class_value;
+ tree real_type_value;
+};
+
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
local-value slots of all identifiers, so that only the global values
@@ -2368,48 +2587,18 @@ pop_nested_namespace (ns)
scope isn't enough, because more binding levels may be pushed. */
struct saved_scope *scope_chain;
-/* Mark ARG (which is really a struct saved_scope **) for GC. */
-
-static void
-mark_saved_scope (arg)
- void *arg;
-{
- struct saved_scope *t = *(struct saved_scope **)arg;
- while (t)
- {
- mark_binding_level (&t->class_bindings);
- ggc_mark_tree (t->old_bindings);
- ggc_mark_tree (t->old_namespace);
- ggc_mark_tree (t->decl_ns_list);
- ggc_mark_tree (t->class_name);
- ggc_mark_tree (t->class_type);
- ggc_mark_tree (t->access_specifier);
- ggc_mark_tree (t->function_decl);
- if (t->lang_base)
- ggc_mark_tree_varray (t->lang_base);
- ggc_mark_tree (t->lang_name);
- ggc_mark_tree (t->template_parms);
- ggc_mark_tree (t->x_previous_class_type);
- ggc_mark_tree (t->x_previous_class_values);
- ggc_mark_tree (t->x_saved_tree);
- ggc_mark_tree (t->lookups);
-
- mark_stmt_tree (&t->x_stmt_tree);
- mark_binding_level (&t->bindings);
- t = t->prev;
- }
-}
-
-static tree
-store_bindings (names, old_bindings)
- tree names, old_bindings;
+static cxx_saved_binding *
+store_bindings (tree names, cxx_saved_binding *old_bindings)
{
tree t;
- tree search_bindings = old_bindings;
+ cxx_saved_binding *search_bindings = old_bindings;
+ timevar_push (TV_NAME_LOOKUP);
for (t = names; t; t = TREE_CHAIN (t))
{
- tree binding, t1, id;
+ tree id;
+ cxx_saved_binding *saved;
+ cxx_saved_binding *t1;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
@@ -2423,24 +2612,24 @@ store_bindings (names, old_bindings)
|| !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
- for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
+ for (t1 = search_bindings; t1; t1 = t1->previous)
+ if (t1->identifier == id)
goto skip_it;
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- binding = make_tree_vec (4);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_BINDING (id) = NULL_TREE;
+ saved = cxx_saved_binding_make ();
+ saved->previous = old_bindings;
+ saved->identifier = id;
+ saved->binding = IDENTIFIER_BINDING (id);
+ saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
+ saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
+ IDENTIFIER_BINDING (id) = NULL;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
+ old_bindings = saved;
skip_it:
;
}
- return old_bindings;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
}
void
@@ -2448,11 +2637,13 @@ maybe_push_to_top_level (pseudo)
int pseudo;
{
struct saved_scope *s;
- struct binding_level *b;
- tree old_bindings;
+ struct cp_binding_level *b;
+ cxx_saved_binding *old_bindings;
int need_pop;
- s = (struct saved_scope *) xcalloc (1, sizeof (struct saved_scope));
+ timevar_push (TV_NAME_LOOKUP);
+
+ s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
b = scope_chain ? current_binding_level : 0;
@@ -2465,11 +2656,11 @@ maybe_push_to_top_level (pseudo)
else
need_pop = 0;
- old_bindings = NULL_TREE;
+ old_bindings = NULL;
if (scope_chain && previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
- /* Have to include global_binding_level, because class-level decls
+ /* Have to include the global scope, because class-scope decls
aren't listed anywhere useful. */
for (; b; b = b->level_chain)
{
@@ -2479,7 +2670,7 @@ maybe_push_to_top_level (pseudo)
inserted into namespace level, finish_file wouldn't find them
when doing pending instantiations. Therefore, don't stop at
namespace level, but continue until :: . */
- if (b == global_binding_level || (pseudo && b->template_parms_p))
+ if (global_scope_p (b) || (pseudo && b->template_parms_p))
break;
old_bindings = store_bindings (b->names, old_bindings);
@@ -2504,6 +2695,7 @@ maybe_push_to_top_level (pseudo)
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
+ timevar_pop (TV_NAME_LOOKUP);
}
void
@@ -2516,22 +2708,24 @@ void
pop_from_top_level ()
{
struct saved_scope *s = scope_chain;
- tree t;
+ cxx_saved_binding *saved;
+
+ timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
if (previous_class_type)
invalidate_class_lookup_cache ();
- VARRAY_FREE (current_lang_base);
+ current_lang_base = 0;
scope_chain = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+ for (saved = s->old_bindings; saved; saved = saved->previous)
{
- tree id = TREE_VEC_ELT (t, 0);
+ tree id = saved->identifier;
- SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
- IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
+ IDENTIFIER_BINDING (id) = saved->binding;
+ IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
+ SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
/* If we were in the middle of compiling a function, restore our
@@ -2541,7 +2735,7 @@ pop_from_top_level ()
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
- free (s);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a definition of struct, union or enum tag "name".
@@ -2561,21 +2755,21 @@ static void
set_identifier_type_value_with_scope (id, type, b)
tree id;
tree type;
- struct binding_level *b;
+ struct cp_binding_level *b;
{
if (!b->namespace_p)
{
/* Shadow the marker, not the real thing, so that the marker
- gets restored later. */
+ gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
else
{
- tree binding = binding_for_name (id, current_namespace);
+ cxx_binding *binding = binding_for_name (id, current_namespace);
BINDING_TYPE (binding) = type;
- /* Store marker instead of real type. */
+ /* Store marker instead of real type. */
type = global_type_node;
}
SET_IDENTIFIER_TYPE_VALUE (id, type);
@@ -2591,24 +2785,25 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, current_binding_level);
}
-/* Return the type associated with id. */
+/* Return the type associated with id. */
tree
identifier_type_value (id)
tree id;
{
- /* There is no type with that name, anywhere. */
+ timevar_push (TV_NAME_LOOKUP);
+ /* There is no type with that name, anywhere. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
- return NULL_TREE;
- /* This is not the type marker, but the real thing. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ /* This is not the type marker, but the real thing. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
- return REAL_IDENTIFIER_TYPE_VALUE (id);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
/* Have to search for it. It must be on the global level, now.
- Ask lookup_name not to return non-types. */
+ Ask lookup_name not to return non-types. */
id = lookup_name_real (id, 2, 1, 0);
if (id)
- return TREE_TYPE (id);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Pop off extraneous binding levels left over due to syntax errors.
@@ -2618,9 +2813,8 @@ identifier_type_value (id)
void
pop_everything ()
{
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "XXX entering pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX entering pop_everything ()\n");
while (!toplevel_bindings_p ())
{
if (current_binding_level->parm_flag == 2)
@@ -2628,14 +2822,13 @@ pop_everything ()
else
poplevel (0, 0, 0);
}
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "XXX leaving pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX leaving pop_everything ()\n");
}
/* 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
+ perform error-checking. If IS_FRIEND is nonzero, this TYPE is
being declared a friend. B is the binding level at which this TYPE
should be bound.
@@ -2646,7 +2839,7 @@ static tree
maybe_process_template_type_declaration (type, globalize, b)
tree type;
int globalize;
- struct binding_level* b;
+ struct cp_binding_level* b;
{
tree decl = TYPE_NAME (type);
@@ -2688,10 +2881,17 @@ maybe_process_template_type_declaration (type, globalize, b)
/* 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 =
- tree_cons (name, type, b->level_chain->tags);
+ if (b->level_chain->type_decls == NULL)
+ b->level_chain->type_decls =
+ binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->level_chain->type_decls, name, type);
if (!COMPLETE_TYPE_P (current_class_type))
- CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ {
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
+ CLASSTYPE_NESTED_UDTS (current_class_type) =
+ b->level_chain->type_decls;
+ }
}
}
}
@@ -2731,6 +2931,8 @@ push_local_name (decl)
size_t i, nelts;
tree t, name;
+ timevar_push (TV_NAME_LOOKUP);
+
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
@@ -2744,17 +2946,19 @@ push_local_name (decl)
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
+ DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
}
VARRAY_PUSH_TREE (local_names, decl);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
@@ -2767,7 +2971,9 @@ pushtag (name, type, globalize)
tree name, type;
int globalize;
{
- register struct binding_level *b;
+ register struct cp_binding_level *b;
+
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->tag_transparent
@@ -2776,11 +2982,13 @@ pushtag (name, type, globalize)
/* We may be defining a new type in the initializer
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
- type punning via an anonymous union. */
+ type punning via an anonymous union. */
|| COMPLETE_TYPE_P (b->this_class))))
b = b->level_chain;
- b->tags = tree_cons (name, type, b->tags);
+ if (b->type_decls == NULL)
+ b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->type_decls, name, type);
if (name)
{
@@ -2854,7 +3062,11 @@ pushtag (name, type, globalize)
if (b->parm_flag == 2)
{
if (!COMPLETE_TYPE_P (current_class_type))
- CLASSTYPE_TAGS (current_class_type) = b->tags;
+ {
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
+ CLASSTYPE_NESTED_UDTS (current_class_type) = b->type_decls;
+ }
}
}
@@ -2874,6 +3086,8 @@ pushtag (name, type, globalize)
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Counter used to create anonymous type names. */
@@ -2898,8 +3112,7 @@ make_anon_name ()
void
clear_anon_tags ()
{
- register struct binding_level *b;
- register tree tags;
+ register struct cp_binding_level *b;
static int last_cnt = 0;
/* Fast out if no new anon names were declared. */
@@ -2909,17 +3122,8 @@ clear_anon_tags ()
b = current_binding_level;
while (b->tag_transparent)
b = b->level_chain;
- tags = b->tags;
- while (tags)
- {
- /* A NULL purpose means we have already processed all tags
- from here to the end of the list. */
- if (TREE_PURPOSE (tags) == NULL_TREE)
- break;
- if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
- TREE_PURPOSE (tags) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
+ if (b->type_decls != NULL)
+ binding_table_remove_anonymous_types (b->type_decls);
last_cnt = anon_cnt;
}
@@ -3135,7 +3339,7 @@ duplicate_decls (newdecl, olddecl)
}
}
- /* Check for redeclaration and other discrepancies. */
+ /* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
@@ -3200,6 +3404,10 @@ duplicate_decls (newdecl, olddecl)
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
+ /* Even if the types match, prefer the new declarations type
+ for anitipated built-ins, for exception lists, etc... */
+ else if (DECL_ANTICIPATED (olddecl))
+ TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
@@ -3275,7 +3483,11 @@ duplicate_decls (newdecl, olddecl)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
- DECL_TEMPLATE_PARMS (olddecl)))
+ DECL_TEMPLATE_PARMS (olddecl))
+ /* Template functions can be disambiguated by
+ return type. */
+ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+ TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@@ -3323,7 +3535,7 @@ duplicate_decls (newdecl, olddecl)
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
- specialize one of its methods. This situation is legal, but
+ specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */
return 0;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -3337,7 +3549,7 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
- /* Redeclaration of namespace alias, ignore it. */
+ /* Redeclaration of namespace alias, ignore it. */
return 1;
else
{
@@ -3447,12 +3659,8 @@ duplicate_decls (newdecl, olddecl)
definition. */
if (DECL_VINDEX (olddecl))
DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
- if (DECL_VIRTUAL_CONTEXT (olddecl))
- DECL_VIRTUAL_CONTEXT (newdecl) = DECL_VIRTUAL_CONTEXT (olddecl);
if (DECL_CONTEXT (olddecl))
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
- if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
- DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
@@ -3469,9 +3677,9 @@ duplicate_decls (newdecl, olddecl)
definition. */
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
- /* Don't warn about extern decl followed by definition. */
+ /* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
- /* Don't warn about friends, let add_friend take care of it. */
+ /* Don't warn about friends, let add_friend take care of it. */
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
warning ("redundant redeclaration of `%D' in same scope", newdecl);
@@ -3487,12 +3695,9 @@ duplicate_decls (newdecl, olddecl)
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
- {
- CLASSTYPE_VSIZE (newtype) = CLASSTYPE_VSIZE (oldtype);
- CLASSTYPE_FRIEND_CLASSES (newtype)
- = CLASSTYPE_FRIEND_CLASSES (oldtype);
- }
-
+ CLASSTYPE_FRIEND_CLASSES (newtype)
+ = CLASSTYPE_FRIEND_CLASSES (oldtype);
+\
DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
}
@@ -3513,12 +3718,9 @@ duplicate_decls (newdecl, olddecl)
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
- DECL_SOURCE_LINE (olddecl)
- = DECL_SOURCE_LINE (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_SOURCE_LINE (newdecl);
- DECL_SOURCE_FILE (olddecl)
- = DECL_SOURCE_FILE (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_SOURCE_FILE (newdecl);
+ DECL_SOURCE_LOCATION (olddecl)
+ = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+ = DECL_SOURCE_LOCATION (newdecl);
}
return 1;
@@ -3539,7 +3741,11 @@ duplicate_decls (newdecl, olddecl)
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
- DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ {
+ DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+ }
+
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -3589,8 +3795,7 @@ duplicate_decls (newdecl, olddecl)
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
- DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+ DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
&& DECL_LANG_SPECIFIC (newdecl)
&& DECL_LANG_SPECIFIC (olddecl))
@@ -3658,7 +3863,8 @@ duplicate_decls (newdecl, 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_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
+ DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
@@ -3668,9 +3874,15 @@ duplicate_decls (newdecl, 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));
+ {
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
+ /* DECL_THUNKS is only valid for virtual functions,
+ otherwise it is a DECL_FRIEND_CONTEXT. */
+ if (DECL_VIRTUAL_P (newdecl))
+ DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+ }
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3697,17 +3909,26 @@ duplicate_decls (newdecl, olddecl)
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
+
+ /* [temp.expl.spec/14] We don't inline explicit specialization
+ just because the primary template says so. */
}
- DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
+ else
+ {
+ if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
+ DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
+
+ DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
- /* If either decl says `inline', this fn is inline, unless its
- definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ /* If either decl says `inline', this fn is inline, unless
+ its definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+ DECL_INLINE (olddecl) = 1;
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
- DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
- = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+ DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+ = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+ }
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
@@ -3807,7 +4028,7 @@ duplicate_decls (newdecl, olddecl)
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
- + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
+ + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
@@ -3837,6 +4058,8 @@ pushdecl (x)
register tree name;
int need_new_binding;
+ timevar_push (TV_NAME_LOOKUP);
+
/* We shouldn't be calling pushdecl when we're generating RTL for a
function that we already did semantic analysis on previously. */
my_friendly_assert (!cfun || doing_semantic_analysis_p (),
@@ -3960,12 +4183,12 @@ pushdecl (x)
/* Check for duplicate params. */
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
- /* Don't do anything just yet. */;
+ /* Don't do anything just yet. */;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
@@ -3973,12 +4196,12 @@ pushdecl (x)
TREE_TYPE (x));
/* Throw away the redeclaration. */
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
@@ -3987,7 +4210,7 @@ pushdecl (x)
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{
@@ -4001,7 +4224,7 @@ pushdecl (x)
error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
}
@@ -4019,7 +4242,7 @@ pushdecl (x)
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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
@@ -4031,12 +4254,12 @@ pushdecl (x)
t = push_overloaded_decl (x, PUSH_GLOBAL);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
- name. See the extensive comment in ../c-decl.c (pushdecl). */
+ name. See the extensive comment in ../c-decl.c (pushdecl). */
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
@@ -4206,7 +4429,9 @@ pushdecl (x)
if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
/* Inline decls shadow nothing. */
&& !DECL_FROM_INLINE (x)
- && TREE_CODE (oldlocal) == PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't check the `this' parameter. */
+ && !DECL_ARTIFICIAL (oldlocal))
{
bool err = false;
@@ -4216,7 +4441,7 @@ pushdecl (x)
{
/* Go to where the parms should be and see if we find
them there. */
- struct binding_level *b = current_binding_level->level_chain;
+ struct cp_binding_level *b = current_binding_level->level_chain;
/* ARM $8.3 */
if (b->parm_flag == 1)
@@ -4266,7 +4491,7 @@ pushdecl (x)
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
@@ -4275,11 +4500,13 @@ pushdecl (x)
static tree
pushdecl_with_scope (x, level)
tree x;
- struct binding_level *level;
+ struct cp_binding_level *level;
{
- register struct binding_level *b;
+ register struct cp_binding_level *b;
tree function_decl = current_function_decl;
+ timevar_push (TV_NAME_LOOKUP);
+
current_function_decl = NULL_TREE;
if (level->parm_flag == 2)
{
@@ -4296,7 +4523,7 @@ pushdecl_with_scope (x, level)
current_binding_level = b;
}
current_function_decl = function_decl;
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Like pushdecl, only it places X in the current namespace,
@@ -4306,9 +4533,10 @@ tree
pushdecl_namespace_level (x)
tree x;
{
- register struct binding_level *b = current_binding_level;
+ register struct cp_binding_level *b = current_binding_level;
register tree t;
+ timevar_push (TV_NAME_LOOKUP);
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
@@ -4318,7 +4546,7 @@ pushdecl_namespace_level (x)
tree name = DECL_NAME (x);
tree newval;
tree *ptr = (tree *)0;
- for (; b != global_binding_level; b = b->level_chain)
+ for (; !global_scope_p (b); b = b->level_chain)
{
tree shadowed = b->type_shadowed;
for (; shadowed; shadowed = TREE_CHAIN (shadowed))
@@ -4342,51 +4570,83 @@ pushdecl_namespace_level (x)
*ptr = newval;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
- if appropriate. */
+/* Like pushdecl, only it places X in the global scope if appropriate.
+ Calls cp_finish_decl to register the variable, initializing it with
+ *INIT, if INIT is non-NULL. */
-tree
-pushdecl_top_level (x)
- tree x;
+static tree
+pushdecl_top_level_1 (tree x, tree *init)
{
+ timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
+ if (init)
+ cp_finish_decl (x, *init, NULL_TREE, 0);
pop_from_top_level ();
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
+}
+
+/* Like pushdecl, only it places X in the global scope if appropriate. */
+
+tree
+pushdecl_top_level (tree x)
+{
+ return pushdecl_top_level_1 (x, NULL);
+}
+
+/* Like pushdecl, only it places X in the global scope if
+ appropriate. Calls cp_finish_decl to register the variable,
+ initializing it with INIT. */
+
+tree
+pushdecl_top_level_and_finish (tree x, tree init)
+{
+ return pushdecl_top_level_1 (x, &init);
}
/* Make the declaration of X appear in CLASS scope. */
-void
+bool
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;
+ tree name;
+ bool is_valid = true;
+ timevar_push (TV_NAME_LOOKUP);
+ /* Get the name of X. */
if (TREE_CODE (x) == OVERLOAD)
- x = OVL_CURRENT (x);
- name = DECL_NAME (x);
+ name = DECL_NAME (get_first_fn (x));
+ else
+ name = DECL_NAME (x);
if (name)
{
- push_class_level_binding (name, x);
+ is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x));
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
{
+ /* If X is an anonymous aggregate, all of its members are
+ treated as if they were members of the class containing the
+ aggregate, for naming purposes. */
tree f;
- for (f = TYPE_FIELDS (TREE_TYPE (x));
- f;
- f = TREE_CHAIN (f))
- pushdecl_class_level (f);
+ for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
+ {
+ push_srcloc (DECL_SOURCE_FILE (f), DECL_SOURCE_LINE (f));
+ if (!pushdecl_class_level (f))
+ is_valid = false;
+ pop_srcloc ();
+ }
}
+ timevar_pop (TV_NAME_LOOKUP);
+
+ return is_valid;
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
@@ -4405,7 +4665,7 @@ maybe_push_decl (decl)
|| (TREE_CODE (decl) != PARM_DECL
&& DECL_CONTEXT (decl) != NULL_TREE
/* Definitions of namespace members outside their namespace are
- possible. */
+ possible. */
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == UNKNOWN_TYPE
@@ -4419,19 +4679,19 @@ maybe_push_decl (decl)
return pushdecl (decl);
}
-/* Make the declaration(s) of X appear in CLASS scope
- under the name NAME. */
+/* Make the declaration(s) of X appear in CLASS scope under the name
+ NAME. Returns true if the binding is valid. */
-void
-push_class_level_binding (name, x)
- tree name;
- tree x;
+bool
+push_class_level_binding (tree name, tree x)
{
- tree binding;
+ cxx_binding *binding;
+
+ timevar_push (TV_NAME_LOOKUP);
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
/* Make sure that this new member does not have the same name
as a template parameter. */
@@ -4481,7 +4741,7 @@ push_class_level_binding (name, x)
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
}
@@ -4495,7 +4755,10 @@ push_class_level_binding (name, x)
/* 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;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
}
/* Insert another USING_DECL into the current binding level, returning
@@ -4510,18 +4773,21 @@ push_using_decl (scope, name)
{
tree decl;
+ timevar_push (TV_NAME_LOOKUP);
+
my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
- return namespace_bindings_p () ? decl : NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_bindings_p () ? decl : NULL_TREE);
decl = build_lang_decl (USING_DECL, name, void_type_node);
DECL_INITIAL (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was
@@ -4535,19 +4801,22 @@ push_using_directive (used)
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
- /* Check if we already have this. */
- if (purpose_member (used, ud) != NULL_TREE)
- return NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
- /* Recursively add all namespaces used. */
- for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
- push_using_directive (TREE_PURPOSE (iter));
+ /* Check if we already have this. */
+ if (purpose_member (used, ud) != NULL_TREE)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
- return ud;
+
+ /* Recursively add all namespaces used. */
+ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ push_using_directive (TREE_PURPOSE (iter));
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
}
/* DECL is a FUNCTION_DECL for a non-member function, which may have
@@ -4579,6 +4848,8 @@ push_overloaded_decl (decl, flags)
tree new_binding;
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
+ timevar_push (TV_NAME_LOOKUP);
+
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
@@ -4611,7 +4882,7 @@ push_overloaded_decl (decl, flags)
decl, fn);
if (duplicate_decls (decl, fn))
- return fn;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
@@ -4621,7 +4892,7 @@ push_overloaded_decl (decl, flags)
{
cp_error_at ("previous non-function declaration `%#D'", old);
error ("conflicts with function declaration `%#D'", decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
}
@@ -4667,10 +4938,10 @@ push_overloaded_decl (decl, flags)
*d = tree_cons (NULL_TREE, new_binding,
TREE_CHAIN (*d));
- /* And update the CPLUS_BINDING node. */
+ /* And update the cxx_binding node. */
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* We should always find a previous binding in this case. */
@@ -4681,7 +4952,7 @@ push_overloaded_decl (decl, flags)
push_local_binding (name, new_binding, flags);
}
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Generate an implicit declaration for identifier FUNCTIONID
@@ -4747,7 +5018,7 @@ redeclaration_error_message (newdecl, olddecl)
return 0;
/* If both functions come from different namespaces, this is not
- a redeclaration - this is a conflict with a used function. */
+ a redeclaration - this is a conflict with a used function. */
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
return "`%D' conflicts with used function";
@@ -4865,18 +5136,20 @@ lookup_label (id)
tree decl;
struct named_label_list *ent;
+ timevar_push (TV_NAME_LOOKUP);
+
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* See if we've already got this label. */
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
@@ -4893,7 +5166,7 @@ lookup_label (id)
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Declare a local label named ID. */
@@ -4949,14 +5222,14 @@ decl_jump_unsafe (decl)
static void
check_previous_goto_1 (decl, level, names, file, line)
tree decl;
- struct binding_level *level;
+ struct cp_binding_level *level;
tree names;
const char *file;
int line;
{
int identified = 0;
int saw_eh = 0;
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
{
tree new_decls = b->names;
@@ -5023,7 +5296,7 @@ check_previous_goto (use)
static void
check_switch_goto (level)
- struct binding_level *level;
+ struct cp_binding_level *level;
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
}
@@ -5125,7 +5398,9 @@ define_label (filename, line, name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
- register struct binding_level *p;
+ register struct cp_binding_level *p;
+
+ timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
@@ -5142,7 +5417,7 @@ define_label (filename, line, name)
if (DECL_INITIAL (decl) != NULL_TREE)
{
error ("duplicate label `%D'", decl);
- return 0;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
{
@@ -5157,13 +5432,14 @@ define_label (filename, line, name)
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct cp_switch
{
- struct binding_level *level;
+ struct cp_binding_level *level;
struct cp_switch *next;
/* The SWITCH_STMT being built. */
tree switch_stmt;
@@ -5219,7 +5495,7 @@ finish_case_label (low_value, high_value)
tree high_value;
{
tree cond, r;
- register struct binding_level *p;
+ register struct cp_binding_level *p;
if (! switch_stack)
{
@@ -5273,14 +5549,6 @@ getdecls ()
return current_binding_level->names;
}
-/* Return the list of type-tags (for structs, etc) of the current level. */
-
-tree
-gettags ()
-{
- return current_binding_level->tags;
-}
-
/* Store the list of declarations of the current level.
This is done for the parameter declarations of a function being defined,
after they are modified in the light of any missing parameters. */
@@ -5292,14 +5560,15 @@ storedecls (decls)
current_binding_level->names = decls;
}
-/* Similarly, store the list of tags of the current level. */
-
+/* Set the current binding TABLE for type declarations.. This is a
+ temporary workaround of the fact that the data structure classtypes
+ does not currently carry its allocated cxx_scope structure. */
void
-storetags (tags)
- tree tags;
+cxx_remember_type_decls (binding_table table)
{
- current_binding_level->tags = tags;
+ current_binding_level->type_decls = table;
}
+
/* Return the type that should be used when TYPE's name is preceded
by a tag such as 'struct' or 'union', or null if the name cannot
@@ -5357,41 +5626,48 @@ static tree
lookup_tag (form, name, binding_level, thislevel_only)
enum tree_code form;
tree name;
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
int thislevel_only;
{
- register struct binding_level *level;
- /* Non-zero if, we should look past a template parameter level, even
+ register struct cp_binding_level *level;
+ /* Nonzero if, we should look past a template parameter level, even
if THISLEVEL_ONLY. */
int allow_template_parms_p = 1;
+ bool type_is_anonymous = ANON_AGGRNAME_P (name);
+
+ timevar_push (TV_NAME_LOOKUP);
for (level = binding_level; level; level = level->level_chain)
{
register tree tail;
- if (ANON_AGGRNAME_P (name))
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- /* There's no need for error checking here, because
- anon names are unique throughout the compilation. */
- if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
- return TREE_VALUE (tail);
- }
+ if (type_is_anonymous && level->type_decls != NULL)
+ {
+ tree type = binding_table_find_anon_type (level->type_decls, name);
+ /* There's no need for error checking here, because
+ anon names are unique throughout the compilation. */
+ if (type != NULL)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
+ }
else if (level->namespace_p)
- /* Do namespace lookup. */
+ /* Do namespace lookup. */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
- tree old = binding_for_name (name, tail);
+ cxx_binding *binding =
+ cxx_scope_find_binding_for_name (tail, name);
+ tree old;
/* If we just skipped past a template parameter 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_template_parms_p
- && old && BINDING_VALUE (old)
- && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
- old = TREE_TYPE (BINDING_VALUE (old));
- else
- old = BINDING_TYPE (old);
+ && binding && BINDING_VALUE (binding)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
+ old = TREE_TYPE (BINDING_VALUE (binding));
+ else if (binding)
+ old = BINDING_TYPE (binding);
+ else
+ old = NULL;
if (old)
{
@@ -5400,36 +5676,36 @@ lookup_tag (form, name, binding_level, thislevel_only)
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- return old;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
}
if (thislevel_only || tail == global_namespace)
- return NULL_TREE;
- }
- else
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_PURPOSE (tail) == name)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (tail));
-
- if (code != form
- && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
- {
- /* Definition isn't the kind we were looking for. */
- error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
- return NULL_TREE;
- }
- return TREE_VALUE (tail);
- }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
+ else if (level->type_decls != NULL)
+ {
+ binding_entry entry = binding_table_find (level->type_decls, name);
+ if (entry != NULL)
+ {
+ enum tree_code code = TREE_CODE (entry->type);
+
+ if (code != form
+ && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
+ {
+ /* Definition isn't the kind we were looking for. */
+ error ("`%#D' redeclared as %C", entry->type, form);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
+ }
+ }
if (thislevel_only && ! level->tag_transparent)
{
if (level->template_parms_p && allow_template_parms_p)
@@ -5444,15 +5720,15 @@ lookup_tag (form, name, binding_level, thislevel_only)
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. */
+ even though THISLEVEL_ONLY is nonzero. */
allow_template_parms_p = 0;
continue;
}
else
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
#if 0
@@ -5468,7 +5744,7 @@ set_current_level_tags_transparency (tags_transparent)
Otherwise return 0. However, the value can never be 0
in the cases in which this is used.
- C++: If NAME is non-zero, this is the new name to install. This is
+ C++: If NAME is nonzero, this is the new name to install. This is
done when replacing anonymous tags with real tag names. */
static tree
@@ -5476,22 +5752,19 @@ lookup_tag_reverse (type, name)
tree type;
tree name;
{
- register struct binding_level *level;
+ register struct cp_binding_level *level;
+
+ timevar_push (TV_NAME_LOOKUP);
for (level = current_binding_level; level; level = level->level_chain)
{
- register tree tail;
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_VALUE (tail) == type)
- {
- if (name)
- TREE_PURPOSE (tail) = name;
- return TREE_PURPOSE (tail);
- }
- }
+ binding_entry entry = level->type_decls == NULL
+ ? NULL
+ : binding_table_reverse_maybe_remap (level->type_decls, type, name);
+ if (entry)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Look up NAME in the NAMESPACE. */
@@ -5502,18 +5775,21 @@ lookup_namespace_name (namespace, name)
{
tree val;
tree template_id = NULL_TREE;
+ cxx_binding binding;
+
+ timevar_push (TV_NAME_LOOKUP);
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;
+ /* This happens for A::B<int> when B is a namespace. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
error ("invalid use of `%D'", name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
namespace = ORIGINAL_NAMESPACE (namespace);
@@ -5530,13 +5806,13 @@ lookup_namespace_name (namespace, name)
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
- val = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, namespace, val, 0))
- return error_mark_node;
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (BINDING_VALUE (val))
+ if (binding.value)
{
- val = BINDING_VALUE (val);
+ val = binding.value;
if (template_id)
{
@@ -5555,7 +5831,7 @@ lookup_namespace_name (namespace, name)
{
error ("`%D::%D' is not a template",
namespace, name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
@@ -5567,35 +5843,34 @@ lookup_namespace_name (namespace, name)
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
-static unsigned long
+static hashval_t
typename_hash (k)
- hash_table_key k;
+ const void * k;
{
- unsigned long hash;
- tree t;
+ hashval_t hash;
+ tree t = (tree) k;
- t = (tree) k;
- hash = (((unsigned long) TYPE_CONTEXT (t))
- ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+ hash = (htab_hash_pointer (TYPE_CONTEXT (t))
+ ^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
return hash;
}
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
-static bool
+static int
typename_compare (k1, k2)
- hash_table_key k1;
- hash_table_key k2;
+ const void * k1;
+ const void * k2;
{
tree t1;
tree t2;
@@ -5608,7 +5883,7 @@ typename_compare (k1, k2)
d2 = TYPE_NAME (t2);
return (DECL_NAME (d1) == DECL_NAME (d2)
- && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+ && 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))
@@ -5623,6 +5898,8 @@ typename_compare (k1, k2)
Returns the new TYPENAME_TYPE. */
+static GTY ((param_is (union tree_node))) htab_t typename_htab;
+
tree
build_typename_type (context, name, fullname, base_type)
tree context;
@@ -5632,16 +5909,12 @@ build_typename_type (context, name, fullname, base_type)
{
tree t;
tree d;
- struct hash_entry *e;
-
- static struct hash_table ht;
+ PTR *e;
- if (!ht.table)
+ if (typename_htab == NULL)
{
- static struct hash_table *h = &ht;
-
- hash_table_init (&ht, &hash_newfunc, &typename_hash, &typename_compare);
- ggc_add_tree_hash_table_root (&h, 1);
+ typename_htab = htab_create_ggc (61, &typename_hash,
+ &typename_compare, NULL);
}
/* Build the TYPENAME_TYPE. */
@@ -5658,12 +5931,11 @@ build_typename_type (context, name, fullname, base_type)
DECL_ARTIFICIAL (d) = 1;
/* See if we already have this type. */
- e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
- if (e)
- t = (tree) e->key;
+ e = htab_find_slot (typename_htab, t, INSERT);
+ if (*e)
+ t = (tree) *e;
else
- /* Insert the type into the table. */
- hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+ *e = t;
return t;
}
@@ -5739,6 +6011,14 @@ make_typename_type (context, name, complain)
return error_mark_node;
}
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
+
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
@@ -5765,6 +6045,15 @@ make_typename_type (context, name, complain)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
+
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, t);
+ else
+ enforce_access (context, t);
+ }
+
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
if (IMPLICIT_TYPENAME_P (t))
@@ -5792,7 +6081,6 @@ make_typename_type (context, name, complain)
return error_mark_node;
}
-
return build_typename_type (context, name, fullname, NULL_TREE);
}
@@ -5805,7 +6093,7 @@ make_typename_type (context, name, complain)
tree
make_unbound_class_template (context, name, complain)
tree context, name;
- int complain;
+ tsubst_flags_t complain;
{
tree t;
tree d;
@@ -5827,13 +6115,18 @@ make_unbound_class_template (context, name, complain)
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
- if (complain)
+ if (complain & tf_error)
error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
- if (!enforce_access (context, tmpl))
- return error_mark_node;
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
return tmpl;
}
@@ -5853,22 +6146,23 @@ make_unbound_class_template (context, name, complain)
return t;
}
-/* Select the right _DECL from multiple choices. */
+/* Select the right _DECL from multiple choices. */
static tree
-select_decl (binding, flags)
- tree binding;
- int flags;
+select_decl (cxx_binding *binding, int flags)
{
tree val;
+
+ timevar_push (TV_NAME_LOOKUP);
+
val = BINDING_VALUE (binding);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
- /* We are not interested in types. */
+ /* We are not interested in types. */
if (val && TREE_CODE (val) == NAMESPACE_DECL)
- return val;
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* If we could have a type and
@@ -5877,13 +6171,13 @@ select_decl (binding, flags)
&& (!val || ((flags & LOOKUP_PREFER_TYPES)
&& TREE_CODE (val) != TYPE_DECL)))
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
- /* Don't return non-types if we really prefer types. */
+ /* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (TREE_CODE (val) != TEMPLATE_DECL
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Unscoped lookup of a global: iterate over current namespaces,
@@ -5896,65 +6190,65 @@ unqualified_namespace_lookup (name, flags, spacesp)
int flags;
tree *spacesp;
{
- tree b = make_node (CPLUS_BINDING);
tree initial = current_decl_namespace ();
tree scope = initial;
tree siter;
- struct binding_level *level;
+ struct cp_binding_level *level;
tree val = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
+ cxx_binding_clear (&binding);
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
+ cxx_binding *b;
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
- val = binding_for_name (name, scope);
+ b = cxx_scope_find_binding_for_name (scope, name);
/* Ignore anticipated built-in functions. */
- if (val && BINDING_VALUE (val)
- && DECL_P (BINDING_VALUE (val))
- && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
- && DECL_ANTICIPATED (BINDING_VALUE (val)))
- {
- BINDING_VALUE (b) = NULL_TREE;
- BINDING_TYPE (b) = NULL_TREE;
- }
- else
+ if (b && BINDING_VALUE (b) && DECL_P (BINDING_VALUE (b))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
+ && DECL_ANTICIPATED (BINDING_VALUE (b)))
+ /* Keep binding cleared. */;
+ else if (b)
{
- /* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ /* Initialize binding for this context. */
+ binding.value = BINDING_VALUE (b);
+ binding.type = BINDING_TYPE (b);
}
- /* Add all _DECLs seen through local using-directives. */
+ /* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
- if (!lookup_using_namespace (name, b, level->using_directives,
+ if (!lookup_using_namespace (name, &binding, level->using_directives,
scope, flags, spacesp))
- /* Give up because of error. */
- return error_mark_node;
+ /* Give up because of error. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- /* Add all _DECLs seen through global using-directives. */
- /* XXX local and global using lists should work equally. */
+ /* Add all _DECLs seen through global using-directives. */
+ /* XXX local and global using lists should work equally. */
siter = initial;
while (1)
{
- if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+ if (!lookup_using_namespace (name, &binding,
+ DECL_NAMESPACE_USING (siter),
scope, flags, spacesp))
- /* Give up because of error. */
- return error_mark_node;
+ /* Give up because of error. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (b, flags);
+ val = select_decl (&binding, flags);
if (scope == global_namespace)
break;
}
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Combine prefer_type and namespaces_only into flags. */
@@ -6006,6 +6300,7 @@ warn_about_implicit_typename_lookup (typename, binding)
tree name = DECL_NAME (typename);
if (! (TREE_CODE (binding) == TEMPLATE_DECL
+ && CLASS_TYPE_P (subtype)
&& CLASSTYPE_TEMPLATE_INFO (subtype)
&& CLASSTYPE_TI_TEMPLATE (subtype) == binding)
&& ! (TREE_CODE (binding) == TYPE_DECL
@@ -6020,6 +6315,65 @@ warn_about_implicit_typename_lookup (typename, binding)
}
}
+/* Check to see whether or not DECL is a variable that would have been
+ in scope under the ARM, but is not in scope under the ANSI/ISO
+ standard. If so, issue an error message. If name lookup would
+ work in both cases, but return a different result, this function
+ returns the result of ANSI/ISO lookup. Otherwise, it returns
+ DECL. */
+
+tree
+check_for_out_of_scope_variable (tree decl)
+{
+ tree shadowed;
+
+ /* We only care about out of scope variables. */
+ if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
+ return decl;
+
+ shadowed = DECL_SHADOWED_FOR_VAR (decl);
+ while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
+ && DECL_DEAD_FOR_LOCAL (shadowed))
+ shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
+ if (!shadowed)
+ shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (decl));
+ if (shadowed)
+ {
+ if (!DECL_ERROR_REPORTED (decl))
+ {
+ warning ("name lookup of `%D' changed",
+ DECL_NAME (decl));
+ cp_warning_at (" matches this `%D' under ISO standard rules",
+ shadowed);
+ cp_warning_at (" matches this `%D' under old rules", decl);
+ DECL_ERROR_REPORTED (decl) = 1;
+ }
+ return shadowed;
+ }
+
+ /* If we have already complained about this declaration, there's no
+ need to do it again. */
+ if (DECL_ERROR_REPORTED (decl))
+ return decl;
+
+ DECL_ERROR_REPORTED (decl) = 1;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ {
+ error ("name lookup of `%D' changed for new ISO `for' scoping",
+ DECL_NAME (decl));
+ cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", decl);
+ return error_mark_node;
+ }
+ else
+ {
+ pedwarn ("name lookup of `%D' changed for new ISO `for' scoping",
+ DECL_NAME (decl));
+ cp_pedwarn_at (" using obsolete binding at `%D'", decl);
+ }
+
+ return decl;
+}
+
/* 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
@@ -6031,7 +6385,7 @@ warn_about_implicit_typename_lookup (typename, binding)
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs.
- If NONCLASS is non-zero, we don't look for the NAME in class scope,
+ If NONCLASS is nonzero, we don't look for the NAME in class scope,
using IDENTIFIER_CLASS_VALUE. */
static tree
@@ -6045,8 +6399,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree from_obj = NULL_TREE;
int flags;
int val_is_implicit_typename = 0;
+ cxx_binding *iter;
- /* Hack: copy flag set by parser, if set. */
+ timevar_push (TV_NAME_LOOKUP);
+
+ /* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
namespaces_only = 1;
@@ -6059,7 +6416,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
- /* If the next thing is '<', class templates are types. */
+ /* If the next thing is '<', class templates are types. */
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
@@ -6071,8 +6428,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
if (type)
{
if (type == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (IMPLICIT_TYPENAME_P (type))
type = TREE_TYPE (type);
if (TYPE_P (type))
@@ -6082,11 +6439,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
type = global_namespace;
if (TREE_CODE (type) == NAMESPACE_DECL)
{
- val = make_node (CPLUS_BINDING);
+ cxx_binding b;
+ cxx_binding_clear (&b);
flags |= LOOKUP_COMPLAIN;
- if (!qualified_lookup_using_namespace (name, type, val, flags))
- return NULL_TREE;
- val = select_decl (val, flags);
+ if (!qualified_lookup_using_namespace (name, type, &b, flags))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ val = select_decl (&b, flags);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
@@ -6099,7 +6457,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
{
val = lookup_member (type, name, 0, prefer_type);
- type_access_control (type, val);
+ if (!uses_template_parms (type))
+ type_access_control (type, val);
/* Restore the containing TYPENAME_TYPE if we looked
through it before. */
@@ -6129,36 +6488,65 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
{
flags = lookup_flags (prefer_type, namespaces_only);
- /* If we're not parsing, we need to complain. */
+ /* If we're not parsing, we need to complain. */
flags |= LOOKUP_COMPLAIN;
}
+ /* Conversion operators are handled specially because ordinary
+ unqualified name lookup will not find template conversion
+ operators. */
+ if (IDENTIFIER_TYPENAME_P (name))
+ {
+ struct cp_binding_level *level;
+
+ for (level = current_binding_level;
+ level && !level->namespace_p;
+ level = level->level_chain)
+ {
+ tree class_type;
+ tree operators;
+
+ /* A conversion operator can only be declared in a class
+ scope. */
+ if (level->parm_flag != 2)
+ continue;
+
+ /* Lookup the conversion operator in the class. */
+ class_type = level->this_class;
+ operators = lookup_fnfields (class_type, name, /*protect=*/0);
+ if (operators)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
+ }
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+
/* First, look in non-namespace scopes. */
if (current_class_type == NULL_TREE)
nonclass = 1;
- for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
{
tree binding;
- if (!LOCAL_BINDING_P (t) && nonclass)
+ if (!LOCAL_BINDING_P (iter) && 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);
+ if (qualify_lookup (BINDING_VALUE (iter), flags))
+ binding = BINDING_VALUE (iter);
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (BINDING_TYPE (t), flags))
- binding = BINDING_TYPE (t);
+ && qualify_lookup (BINDING_TYPE (iter), flags))
+ binding = BINDING_TYPE (iter);
else
binding = NULL_TREE;
/* Handle access control on types from enclosing or base classes. */
if (binding && ! yylex
- && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
- type_access_control (BINDING_LEVEL (t)->this_class, binding);
+ && BINDING_LEVEL (iter) && BINDING_LEVEL (iter)->parm_flag == 2)
+ type_access_control (BINDING_LEVEL (iter)->this_class, binding);
if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
@@ -6217,7 +6605,7 @@ does not match lookup in the current scope (`%#D')",
else if (from_obj)
val = from_obj;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
@@ -6258,9 +6646,11 @@ tree
lookup_name_current_level (name)
tree name;
{
- struct binding_level *b;
+ struct cp_binding_level *b;
tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
+
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
@@ -6279,7 +6669,7 @@ lookup_name_current_level (name)
while (1)
{
if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
- return IDENTIFIER_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
@@ -6288,7 +6678,7 @@ lookup_name_current_level (name)
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Like lookup_name_current_level, but for types. */
@@ -6298,17 +6688,20 @@ lookup_type_current_level (name)
tree name;
{
register tree t = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
&& REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
{
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
while (1)
{
if (purpose_member (name, b->type_shadowed))
- return REAL_IDENTIFIER_TYPE_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
@@ -6316,7 +6709,7 @@ lookup_type_current_level (name)
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
void
@@ -6357,7 +6750,7 @@ record_builtin_type (rid_index, name, type)
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
- /* Built-in types live in the global namespace. */
+ /* Built-in types live in the global namespace. */
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname != NULL_TREE)
@@ -6389,12 +6782,12 @@ record_builtin_java_type (name, size)
if (size > 0)
type = make_signed_type (size);
else if (size > -32)
- { /* "__java_char" or ""__java_boolean". */
+ { /* "__java_char" or ""__java_boolean". */
type = make_unsigned_type (-size);
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
else
- { /* "__java_float" or ""__java_double". */
+ { /* "__java_float" or ""__java_double". */
type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
@@ -6404,14 +6797,14 @@ record_builtin_java_type (name, size)
/* 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. */
+ However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
TYPE_FOR_JAVA (type) = 1;
return type;
}
-/* Push a type into the namespace so that the back-ends ignore it. */
+/* Push a type into the namespace so that the back-ends ignore it. */
static void
record_unknown_type (type, name)
@@ -6437,7 +6830,7 @@ typedef struct predefined_identifier
const char *const name;
/* The place where the IDENTIFIER_NODE should be stored. */
tree *const node;
- /* Non-zero if this is the name of a constructor or destructor. */
+ /* Nonzero if this is the name of a constructor or destructor. */
const int ctor_or_dtor_p;
} predefined_identifier;
@@ -6494,26 +6887,19 @@ cxx_init_decl_processing ()
initialize_predefined_identifiers ();
/* Fill in back-end hooks. */
- init_lang_status = &push_cp_function_context;
- free_lang_status = &pop_cp_function_context;
- mark_lang_status = &mark_cp_function_context;
lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
- cp_parse_init ();
- init_decl2 ();
- init_pt ();
-
/* Create the global variables. */
push_to_top_level ();
- /* Enter the global namespace. */
+ /* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
push_namespace (get_identifier ("::"));
global_namespace = current_namespace;
current_lang_name = NULL_TREE;
/* Adjust various flags based on command-line settings. */
- if (! flag_permissive && ! pedantic)
+ if (!flag_permissive)
flag_pedantic_errors = 1;
if (!flag_no_inline)
{
@@ -6546,18 +6932,20 @@ cxx_init_decl_processing ()
/* Make the binding_level structure for global names. */
pushlevel (0);
- global_binding_level = current_binding_level;
+ current_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
/* The global level is the namespace level of ::. */
- NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+ NAMESPACE_LEVEL (global_namespace) = current_binding_level;
declare_namespace_level ();
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ 200,
+ "Static declarations");
+
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
pop_namespace ();
- lang_attribute_table = cp_attribute_table;
-
c_common_nodes_and_builtins ();
java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
@@ -6585,9 +6973,6 @@ cxx_init_decl_processing ()
boolean_true_node = build_int_2 (1, 0);
TREE_TYPE (boolean_true_node) = boolean_type_node;
- signed_size_zero_node = build_int_2 (0, 0);
- TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype));
-
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
#if 0
@@ -6598,8 +6983,6 @@ cxx_init_decl_processing ()
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_type_node);
- lang_type_promotes_to = convert_type_from_ellipsis;
-
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
@@ -6657,8 +7040,9 @@ cxx_init_decl_processing ()
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
- bad_alloc_type_node = xref_tag
- (class_type_node, get_identifier ("bad_alloc"), 1);
+ bad_alloc_type_node
+ = xref_tag (class_type, get_identifier ("bad_alloc"),
+ /*attributes=*/NULL_TREE, 1);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
@@ -6680,7 +7064,6 @@ cxx_init_decl_processing ()
/* Perform other language dependent initializations. */
init_class_processing ();
- init_init_processing ();
init_search_processing ();
init_rtti_processing ();
@@ -6700,41 +7083,11 @@ cxx_init_decl_processing ()
say -fwritable-strings? */
if (flag_writable_strings)
flag_const_strings = 0;
-
- /* Add GC roots for all of our global variables. */
- ggc_add_tree_root (c_global_trees, sizeof c_global_trees / sizeof(tree));
- ggc_add_tree_root (cp_global_trees, sizeof cp_global_trees / sizeof(tree));
- ggc_add_tree_root (&integer_three_node, 1);
- ggc_add_tree_root (&integer_two_node, 1);
- ggc_add_tree_root (&signed_size_zero_node, 1);
- ggc_add_tree_root (&size_one_node, 1);
- ggc_add_tree_root (&size_zero_node, 1);
- ggc_add_root (&global_binding_level, 1, sizeof global_binding_level,
- mark_binding_level);
- ggc_add_root (&scope_chain, 1, sizeof scope_chain, &mark_saved_scope);
- ggc_add_tree_root (&static_ctors, 1);
- ggc_add_tree_root (&static_dtors, 1);
- ggc_add_tree_root (&lastiddecl, 1);
-
- ggc_add_tree_root (&last_function_parms, 1);
- ggc_add_tree_root (&error_mark_list, 1);
-
- ggc_add_tree_root (&global_namespace, 1);
- ggc_add_tree_root (&global_type_node, 1);
- ggc_add_tree_root (&anonymous_namespace_name, 1);
-
- ggc_add_tree_root (&got_object, 1);
- ggc_add_tree_root (&got_scope, 1);
-
- ggc_add_tree_root (&current_lang_name, 1);
- ggc_add_tree_root (&static_aggregates, 1);
- ggc_add_tree_root (&free_bindings, 1);
- ggc_add_tree_root (&incomplete_vars, 1);
}
/* Generate an initializer for a function naming variable from
NAME. NAME may be NULL, in which case we generate a special
- ERROR_MARK node which should be replaced later. */
+ ERROR_MARK node which should be replaced later. */
tree
cp_fname_init (name)
@@ -6759,7 +7112,7 @@ cp_fname_init (name)
TREE_TYPE (init) = type;
else
/* We don't know the value until instantiation time. Make
- something which will be digested now, but replaced later. */
+ something which will be digested now, but replaced later. */
init = build (ERROR_MARK, type);
return init;
@@ -6781,7 +7134,7 @@ cp_make_fname_decl (id, type_dep)
tree init = cp_fname_init (name);
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
- /* As we don't push the decl here, we must set the context. */
+ /* As we don't push the decl here, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
@@ -6805,26 +7158,25 @@ cp_make_fname_decl (id, type_dep)
See tree.h for possible values.
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function.
+ If ATTRS is nonzero, use that for the function's attribute
+ list. */
static tree
-builtin_function_1 (name, type, context, code, class, libname)
+builtin_function_1 (name, type, context, code, class, libname, attrs)
const char *name;
tree type;
tree context;
int code;
enum built_in_class class;
const char *libname;
+ tree attrs;
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
DECL_CONTEXT (decl) = context;
- /* The return builtins leave the current function. */
- if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
- TREE_THIS_VOLATILE (decl) = 1;
-
pushdecl (decl);
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
@@ -6840,7 +7192,10 @@ builtin_function_1 (name, type, context, code, class, libname)
DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
- decl_attributes (&decl, NULL_TREE, 0);
+ if (attrs)
+ decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+ else
+ decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
@@ -6856,26 +7211,31 @@ builtin_function_1 (name, type, context, code, class, libname)
See tree.h for possible values.
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function.
+
+ If ATTRS is nonzero, use that for the function's attribute
+ list. */
tree
-builtin_function (name, type, code, class, libname)
+builtin_function (name, type, code, class, libname, attrs)
const char *name;
tree type;
int code;
enum built_in_class class;
const char *libname;
+ tree attrs;
{
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
if (name[0] != '_')
{
push_namespace (std_identifier);
- builtin_function_1 (name, type, std_node, code, class, libname);
+ builtin_function_1 (name, type, std_node, code, class, libname, attrs);
pop_namespace ();
}
- return builtin_function_1 (name, type, NULL_TREE, code, class, libname);
+ return builtin_function_1 (name, type, NULL_TREE, code,
+ class, libname, attrs);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
@@ -7002,7 +7362,7 @@ push_throw_library_fn (name, type)
attributes. */
void
-insert_default_attributes (decl)
+cxx_insert_default_attributes (decl)
tree decl;
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
@@ -7140,7 +7500,8 @@ check_tag_decl (declspecs)
|| value == ridpointers[(int) RID_VIRTUAL]
|| value == ridpointers[(int) RID_CONST]
|| value == ridpointers[(int) RID_VOLATILE]
- || value == ridpointers[(int) RID_EXPLICIT])
+ || value == ridpointers[(int) RID_EXPLICIT]
+ || value == ridpointers[(int) RID_THREAD])
ob_modifier = value;
}
@@ -7280,8 +7641,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree decl;
register tree type, tem;
tree context;
- extern int have_extern_spec;
- extern int used_extern_spec;
#if 0
/* See code below that used this. */
@@ -7289,11 +7648,11 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
#endif
/* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
/* An object declared as __attribute__((deprecated)) suppresses
@@ -7322,11 +7681,11 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
&& context != current_namespace && TREE_CODE (decl) == VAR_DECL)
{
/* When parsing the initializer, lookup should use the object's
- namespace. */
+ namespace. */
push_decl_namespace (context);
}
- /* We are only interested in class contexts, later. */
+ /* We are only interested in class contexts, later. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
@@ -7370,7 +7729,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
cplus_decl_attributes (&decl, attributes, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
@@ -7449,7 +7808,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
wrong semantics. If we say -fno-conserve-space, we want this to
produce errors about redefs; to do this we force variables into the
data segment. */
- DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
+ DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
+ || !DECL_THREAD_LOCAL (tem))
+ && (flag_conserve_space || ! TREE_PUBLIC (tem)));
#endif
if (! processing_template_decl)
@@ -7577,10 +7938,7 @@ grok_reference_init (decl, type, init)
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
- tmp = convert_to_reference
- (type, init, CONV_IMPLICIT,
- LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
- decl);
+ tmp = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;
@@ -7598,39 +7956,6 @@ grok_reference_init (decl, type, init)
return NULL_TREE;
}
-/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
- mucking with forces it does not comprehend (i.e. initialization with a
- constructor). If we are at global scope and won't go into COMMON, fill
- it in with a dummy CONSTRUCTOR to force the variable into .data;
- otherwise we can use error_mark_node. */
-
-static tree
-obscure_complex_init (decl, init)
- tree decl, init;
-{
- if (! flag_no_inline && TREE_STATIC (decl))
- {
- if (extract_init (decl, init))
- return NULL_TREE;
- }
-
-#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
- if (toplevel_bindings_p () && ! DECL_COMMON (decl))
- DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
- NULL_TREE);
- else
-#endif
- {
- if (zero_init_p (TREE_TYPE (decl)))
- DECL_INITIAL (decl) = error_mark_node;
- /* Otherwise, force_store_init_value will have already stored a
- zero-init initializer in DECL_INITIAL, that should be
- retained. */
- }
-
- return init;
-}
-
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
@@ -7691,11 +8016,16 @@ layout_var_decl (decl)
/* If we haven't already layed out this declaration, do so now.
Note that we must not call complete type for an external object
because it's type might involve templates that we are not
- supposed to isntantiate yet. (And it's perfectly legal to say
+ supposed to isntantiate yet. (And it's perfectly valid to say
`extern X x' for some incomplete type `X'.) */
if (!DECL_EXTERNAL (decl))
complete_type (type);
- if (!DECL_SIZE (decl) && COMPLETE_TYPE_P (type))
+ if (!DECL_SIZE (decl)
+ && TREE_TYPE (decl) != error_mark_node
+ && (COMPLETE_TYPE_P (type)
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && !TYPE_DOMAIN (type)
+ && COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -7748,40 +8078,43 @@ maybe_commonize_var (decl)
if (TREE_STATIC (decl)
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
- && current_function_decl
- && DECL_CONTEXT (decl) == current_function_decl
- && (DECL_DECLARED_INLINE_P (current_function_decl)
- || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
- && TREE_PUBLIC (current_function_decl))
- {
- /* If flag_weak, we don't need to mess with this, as we can just
- make the function weak, and let it refer to its unique local
- copy. This works because we don't allow the function to be
- inlined. */
- if (! flag_weak)
- {
- if (DECL_INTERFACE_KNOWN (current_function_decl))
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
- }
- else if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
+ && DECL_FUNCTION_SCOPE_P (decl)
+ /* Unfortunately, import_export_decl has not always been called
+ before the function is processed, so we cannot simply check
+ DECL_COMDAT. */
+ && (DECL_COMDAT (DECL_CONTEXT (decl))
+ || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
+ || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
+ && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ {
+ if (flag_weak)
+ {
+ /* With weak symbols, we simply make the variable COMDAT;
+ that will cause copies in multiple translations units to
+ be merged. */
+ comdat_linkage (decl);
+ }
+ else
+ {
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
{
+ /* Without weak symbols, we can use COMMON to merge
+ uninitialized variables. */
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
- /* else we lose. We can only do this if we can use common,
- which we can't if it has been initialized. */
-
- if (!TREE_PUBLIC (decl))
+ else
{
+ /* While for initialized variables, we must use internal
+ linkage -- which means that multiple copies will not
+ be merged. */
+ TREE_PUBLIC (decl) = 0;
+ DECL_COMMON (decl) = 0;
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
- else
- comdat_linkage (decl);
}
else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
/* Set it up again; we might have set DECL_INITIAL since the last
@@ -7808,53 +8141,277 @@ check_for_uninitialized_const_var (decl)
error ("uninitialized const `%D'", decl);
}
-/* Verify INIT (the initializer for DECL), and record the
- initialization in DECL_INITIAL, if appropriate. Returns a new
- value for INIT. */
+/* FIELD is a FIELD_DECL or NULL. In the former case, the value
+ returned is the next FIELD_DECL (possibly FIELD itself) that can be
+ initialized. If there are no more such fields, the return value
+ will be NULL. */
static tree
-check_initializer (decl, init)
- tree decl;
- tree init;
+next_initializable_field (tree field)
{
- tree type;
+ while (field
+ && (TREE_CODE (field) != FIELD_DECL
+ || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+ || DECL_ARTIFICIAL (field)))
+ field = TREE_CHAIN (field);
- if (TREE_CODE (decl) == FIELD_DECL)
- return init;
+ return field;
+}
- type = TREE_TYPE (decl);
+/* Undo the brace-elision allowed by [dcl.init.aggr] in a
+ brace-enclosed aggregate initializer.
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
+ *INITP is one of a list of initializers describing a brace-enclosed
+ initializer for an entity of the indicated aggregate TYPE. It may
+ not presently match the shape of the TYPE; for example:
+
+ struct S { int a; int b; };
+ struct S a[] = { 1, 2, 3, 4 };
- /* Check the initializer. */
- if (init)
+ Here *INITP will point to TREE_LIST of four elements, rather than a
+ list of two elements, each itself a list of two elements. This
+ routine transforms INIT from the former form into the latter. The
+ revised initializer is returned. */
+
+static tree
+reshape_init (tree type, tree *initp)
+{
+ tree inits;
+ tree old_init;
+ tree old_init_value;
+ tree new_init;
+ bool brace_enclosed_p;
+
+ old_init = *initp;
+ old_init_value = (TREE_CODE (*initp) == TREE_LIST
+ ? TREE_VALUE (*initp) : old_init);
+
+ /* For some parse errors, OLD_INIT_VALUE may be NULL. */
+ if (!old_init_value)
{
- /* Things that are going to be initialized need to have complete
- type. */
- TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
+ my_friendly_assert (TREE_CODE (old_init) == TREE_LIST, 20021202);
+ TREE_VALUE (old_init) = error_mark_node;
+ return old_init;
+ }
- if (type == error_mark_node)
- /* We will have already complained. */
- init = NULL_TREE;
- else if (COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
- {
- error ("variable-sized object `%D' may not be initialized", decl);
- init = NULL_TREE;
- }
- else if (TREE_CODE (type) == ARRAY_TYPE
- && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+ /* If the initializer is brace-enclosed, pull initializers from the
+ enclosed elements. Advance past the brace-enclosed initializer
+ now. */
+ if (TREE_CODE (old_init_value) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ inits = CONSTRUCTOR_ELTS (old_init_value);
+ initp = &inits;
+ brace_enclosed_p = true;
+ }
+ else
+ {
+ inits = NULL_TREE;
+ brace_enclosed_p = false;
+ }
+
+ /* A non-aggregate type is always initialized with a single
+ initializer. */
+ if (!CP_AGGREGATE_TYPE_P (type))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ /* It is invalid to initialize a non-aggregate type with a
+ brace-enclosed initializer. */
+ if (brace_enclosed_p)
+ {
+ error ("brace-enclosed initializer used to initialize `%T'",
+ type);
+ if (TREE_CODE (old_init) == TREE_LIST)
+ TREE_VALUE (old_init) = error_mark_node;
+ else
+ old_init = error_mark_node;
+ }
+
+ return old_init;
+ }
+
+ /* [dcl.init.aggr]
+
+ All implicit type conversions (clause _conv_) are considered when
+ initializing the aggregate member with an initializer from an
+ initializer-list. If the initializer can initialize a member,
+ the member is initialized. Otherwise, if the member is itself a
+ non-empty subaggregate, brace elision is assumed and the
+ initializer is considered for the initialization of the first
+ member of the subaggregate. */
+ if (CLASS_TYPE_P (type)
+ && !brace_enclosed_p
+ && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ return old_init;
+ }
+
+ if (TREE_CODE (old_init_value) == STRING_CST
+ && TREE_CODE (type) == ARRAY_TYPE
+ && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
+ {
+ /* [dcl.init.string]
+
+ A char array (whether plain char, signed char, or unsigned char)
+ can be initialized by a string-literal (optionally enclosed in
+ braces); a wchar_t array can be initialized by a wide
+ string-literal (optionally enclosed in braces). */
+ new_init = old_init;
+ /* Move past the initializer. */
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ }
+ else
+ {
+ /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
+ new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ TREE_HAS_CONSTRUCTOR (new_init) = 1;
+
+ if (CLASS_TYPE_P (type))
{
- error ("elements of array `%#D' have incomplete type", decl);
- init = NULL_TREE;
+ tree field;
+
+ field = next_initializable_field (TYPE_FIELDS (type));
+
+ if (!field)
+ {
+ /* [dcl.init.aggr]
+
+ An initializer for an aggregate member that is an
+ empty class shall have the form of an empty
+ initializer-list {}. */
+ if (!brace_enclosed_p)
+ error ("initializer for `%T' must be brace-enclosed",
+ type);
+ }
+ else
+ {
+ /* Loop through the initializable fields, gathering
+ initializers. */
+ while (*initp)
+ {
+ tree field_init;
+
+ /* Handle designated initializers, as an extension. */
+ if (TREE_PURPOSE (*initp))
+ {
+ if (pedantic)
+ pedwarn ("ISO C++ does not allow designated initializers");
+ field = lookup_field_1 (type, TREE_PURPOSE (*initp),
+ /*want_type=*/false);
+ if (!field || TREE_CODE (field) != FIELD_DECL)
+ error ("`%T' has no non-static data member named `%D'",
+ type, TREE_PURPOSE (*initp));
+ }
+ if (!field)
+ break;
+
+ field_init = reshape_init (TREE_TYPE (field), initp);
+ TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = field_init;
+ /* [dcl.init.aggr]
+
+ When a union is initialized with a brace-enclosed
+ initializer, the braces shall only contain an
+ initializer for the first member of the union. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ field = next_initializable_field (TREE_CHAIN (field));
+ }
+ }
}
- else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("`%D' has incomplete type", decl);
- TREE_TYPE (decl) = error_mark_node;
- init = NULL_TREE;
+ tree index;
+ tree max_index;
+
+ /* If the bound of the array is known, take no more initializers
+ than are allowed. */
+ max_index = (TYPE_DOMAIN (type)
+ ? array_type_nelts (type) : NULL_TREE);
+ /* Loop through the array elements, gathering initializers. */
+ for (index = size_zero_node;
+ *initp && (!max_index || !tree_int_cst_lt (max_index, index));
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ {
+ tree element_init;
+
+ element_init = reshape_init (TREE_TYPE (type), initp);
+ TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = element_init;
+ if (TREE_PURPOSE (element_init))
+ index = TREE_PURPOSE (element_init);
+ }
}
+ else
+ abort ();
+
+ /* The initializers were placed in reverse order in the
+ CONSTRUCTOR. */
+ CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
+
+ if (TREE_CODE (old_init) == TREE_LIST)
+ new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
+ }
+
+ /* If this was a brace-enclosed initializer and all of the
+ initializers were not used up, there is a problem. */
+ if (brace_enclosed_p && *initp)
+ error ("too many initializers for `%T'", type);
+
+ return new_init;
+}
+
+/* Verify INIT (the initializer for DECL), and record the
+ initialization in DECL_INITIAL, if appropriate.
+
+ If the return value is non-NULL, it is an expression that must be
+ evaluated dynamically to initialize DECL. */
+
+static tree
+check_initializer (tree decl, tree init, int flags)
+{
+ tree type = TREE_TYPE (decl);
+
+ /* If `start_decl' didn't like having an initialization, ignore it now. */
+ if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
+ init = NULL_TREE;
+
+ /* If an initializer is present, DECL_INITIAL has been
+ error_mark_node, to indicate that an as-of-yet unevaluated
+ initialization will occur. From now on, DECL_INITIAL reflects
+ the static initialization -- if any -- of DECL. */
+ DECL_INITIAL (decl) = NULL_TREE;
+
+ /* Things that are going to be initialized need to have complete
+ type. */
+ TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
+
+ if (type == error_mark_node)
+ /* We will have already complained. */
+ init = NULL_TREE;
+ else if (init && COMPLETE_TYPE_P (type)
+ && !TREE_CONSTANT (TYPE_SIZE (type)))
+ {
+ error ("variable-sized object `%D' may not be initialized", decl);
+ init = NULL_TREE;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+ {
+ error ("elements of array `%#D' have incomplete type", decl);
+ init = NULL_TREE;
+ }
+ else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+ {
+ error ("`%D' has incomplete type", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ init = NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
@@ -7867,37 +8424,64 @@ check_initializer (decl, init)
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
- {
- init = grok_reference_init (decl, type, init);
- if (init)
- init = obscure_complex_init (decl, init);
- }
- else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
- {
- force_store_init_value (decl, build_forced_zero_init (type));
-
- if (init)
- goto process_init;
- }
+ init = grok_reference_init (decl, type, init);
else if (init)
{
- process_init:
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ {
+ /* [dcl.init] paragraph 13,
+ If T is a scalar type, then a declaration of the form
+ T x = { a };
+ is equivalent to
+ T x = a;
+
+ reshape_init will complain about the extra braces,
+ and doesn't do anything useful in the case where TYPE is
+ scalar, so just don't call it. */
+ if (CP_AGGREGATE_TYPE_P (type))
+ init = reshape_init (type, &init);
+ }
+
+ /* If DECL has an array type without a specific bound, deduce the
+ array size from the initializer. */
+ maybe_deduce_size_from_array_init (decl, init);
+ type = TREE_TYPE (decl);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ TREE_TYPE (init) = type;
+
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
- init = digest_init (type, init, (tree *) 0);
+ goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("`%D' must be initialized by constructor, not by `{...}'",
- decl);
+ decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
+ else
+ {
+ int saved_stmts_are_full_exprs_p;
+
+ initialize_aggr:
+ saved_stmts_are_full_exprs_p = 0;
+ if (building_stmt_tree ())
+ {
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ }
+ init = build_aggr_init (decl, init, flags);
+ if (building_stmt_tree ())
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ return init;
+ }
}
else
{
@@ -7905,37 +8489,29 @@ check_initializer (decl, init)
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
-
- if (init)
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
- else if (TYPE_P (type)
- && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
+ else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
+ goto initialize_aggr;
+ else if (IS_AGGR_TYPE (type))
{
tree core_type = strip_array_types (type);
- if (! TYPE_NEEDS_CONSTRUCTING (core_type))
- {
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized reference members",
- decl);
- }
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized const members", decl);
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized reference members",
+ decl);
check_for_uninitialized_const_var (decl);
-
- if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- init = obscure_complex_init (decl, NULL_TREE);
-
}
else
check_for_uninitialized_const_var (decl);
+ if (init && init != error_mark_node)
+ init = build (INIT_EXPR, type, decl, init);
+
return init;
}
@@ -8033,18 +8609,20 @@ void
maybe_inject_for_scope_var (decl)
tree decl;
{
+ timevar_push (TV_NAME_LOOKUP);
+
if (!DECL_NAME (decl))
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
/* Declarations of __FUNCTION__ and its ilk appear magically when
the variable is first used. If that happens to be inside a
for-loop, we don't want to do anything special. */
if (DECL_PRETTY_FUNCTION_P (decl))
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
if (current_binding_level->is_for_scope)
{
- struct binding_level *outer
+ struct cp_binding_level *outer
= current_binding_level->level_chain;
/* Check to see if the same name is already bound at the outer
@@ -8056,8 +8634,8 @@ maybe_inject_for_scope_var (decl)
Otherwise, we need to preserve the temp slot for decl to last
into the outer binding level. */
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
if (outer_binding && BINDING_LEVEL (outer_binding) == outer
&& (TREE_CODE (BINDING_VALUE (outer_binding))
@@ -8071,39 +8649,32 @@ maybe_inject_for_scope_var (decl)
else if (DECL_IN_MEMORY_P (decl))
preserve_temp_slots (DECL_RTL (decl));
}
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Generate code to initialize DECL (a local variable). */
-void
-initialize_local_var (decl, init, flags)
+static void
+initialize_local_var (decl, init)
tree decl;
tree init;
- int flags;
{
tree type = TREE_TYPE (decl);
+ tree cleanup;
- /* If the type is bogus, don't bother initializing the variable. */
- if (type == error_mark_node)
- return;
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == RESULT_DECL,
+ 20021010);
+ my_friendly_assert (!TREE_STATIC (decl), 20021010);
- if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
+ if (DECL_SIZE (decl) == NULL_TREE)
{
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
- /* Local statics are handled differently from ordinary automatic
- variables. */
- if (TREE_STATIC (decl))
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- expand_static_init (decl, init);
- return;
- }
-
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
@@ -8111,14 +8682,15 @@ initialize_local_var (decl, init, flags)
/* Compute and store the initial value. */
already_used = TREE_USED (decl) || TREE_USED (type);
- if (init || TYPE_NEEDS_CONSTRUCTING (type))
+ /* Perform the initialization. */
+ if (init)
{
int saved_stmts_are_full_exprs_p;
my_friendly_assert (building_stmt_tree (), 20000906);
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- finish_expr_stmt (build_aggr_init (decl, init, flags));
+ finish_expr_stmt (init);
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
}
@@ -8137,37 +8709,9 @@ initialize_local_var (decl, init, flags)
else if (already_used)
TREE_USED (decl) = 1;
}
-}
-
-/* Generate code to destroy DECL (a local variable). */
-
-static void
-destroy_local_var (decl)
- tree decl;
-{
- tree type = TREE_TYPE (decl);
- tree cleanup;
-
- /* Only variables get cleaned up. */
- if (TREE_CODE (decl) != VAR_DECL)
- return;
-
- /* And only things with destructors need cleaning up. */
- if (type == error_mark_node
- || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
- return;
-
- if (TREE_CODE (decl) == VAR_DECL &&
- (DECL_EXTERNAL (decl) || TREE_STATIC (decl)))
- /* We don't clean up things that aren't defined in this
- translation unit, or that need a static cleanup. The latter
- are handled by finish_file. */
- return;
-
- /* Compute the cleanup. */
- cleanup = maybe_build_cleanup (decl);
- /* Record the cleanup required for this declaration. */
+ /* Generate a cleanup, if necessary. */
+ cleanup = cxx_maybe_build_cleanup (decl);
if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
@@ -8202,7 +8746,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
}
/* If a name was specified, get the string. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -8226,7 +8770,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
&& DECL_CONTEXT (decl) != current_namespace
&& init)
{
- /* Leave the namespace of the object. */
+ /* Leave the namespace of the object. */
pop_decl_namespace ();
}
@@ -8281,7 +8825,8 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
ttype = target_type (type);
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
- && TYPE_NEEDS_CONSTRUCTING (type))
+ && (TYPE_NEEDS_CONSTRUCTING (type)
+ || TREE_CODE (type) == REFERENCE_TYPE))
{
/* Currently, GNU C++ puts constants in text space, making them
impossible to initialize. In the future, one would hope for
@@ -8299,10 +8844,59 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
-
- /* Deduce size of array from initialization, if not already known. */
- init = check_initializer (decl, init);
- maybe_deduce_size_from_array_init (decl, init);
+ else if (TREE_CODE (decl) == RESULT_DECL)
+ init = check_initializer (decl, init, flags);
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ /* Only PODs can have thread-local storage. Other types may require
+ various kinds of non-trivial initialization. */
+ if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
+ error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+ decl, TREE_TYPE (decl));
+ /* Convert the initializer to the type of DECL, if we have not
+ already initialized DECL. */
+ if (!DECL_INITIALIZED_P (decl)
+ /* If !DECL_EXTERNAL then DECL is being defined. In the
+ case of a static data member initialized inside the
+ class-specifier, there can be an initializer even if DECL
+ is *not* defined. */
+ && (!DECL_EXTERNAL (decl) || init))
+ {
+ init = check_initializer (decl, init, flags);
+ /* Thread-local storage cannot be dynamically initialized. */
+ if (DECL_THREAD_LOCAL (decl) && init)
+ {
+ error ("`%D' is thread-local and so cannot be dynamically "
+ "initialized", decl);
+ init = NULL_TREE;
+ }
+ /* Handle:
+
+ [dcl.init]
+
+ The memory occupied by any object of static storage
+ duration is zero-initialized at program startup before
+ any other initialization takes place.
+
+ We cannot create an appropriate initializer until after
+ the type of DECL is finalized. If DECL_INITIAL is set,
+ then the DECL is statically initialized, and any
+ necessary zero-initialization has already been performed. */
+ if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/true);
+ /* Remember that the initialization for this variable has
+ taken place. */
+ DECL_INITIALIZED_P (decl) = 1;
+ }
+ /* If the variable has an array type, lay out the type, even if
+ there is no initializer. It is valid to index through the
+ array, and we must get TYPE_ALIGN set correctly on the array
+ type. */
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ layout_type (type);
+ }
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
@@ -8333,7 +8927,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
else
abstract_virtuals_error (decl, strip_array_types (type));
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_TYPE (decl) == error_mark_node)
+ /* No initialization required. */
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
@@ -8342,35 +8938,25 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
if (init)
DECL_INITIAL (decl) = init;
}
- else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ else
{
- /* This is a local declaration. */
- if (doing_semantic_analysis_p ())
- maybe_inject_for_scope_var (decl);
- /* Initialize the local variable. But, if we're building a
- statement-tree, we'll do the initialization when we
- expand the tree. */
- if (processing_template_decl)
- {
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
- else
+ /* A variable definition. */
+ if (DECL_FUNCTION_SCOPE_P (decl))
{
- /* If we're not building RTL, then we need to do so
- now. */
- my_friendly_assert (building_stmt_tree (), 20000906);
- /* Initialize the variable. */
- initialize_local_var (decl, init, flags);
- /* Clean up the variable. */
- destroy_local_var (decl);
+ /* This is a local declaration. */
+ if (doing_semantic_analysis_p ())
+ maybe_inject_for_scope_var (decl);
+ /* Initialize the local variable. */
+ if (processing_template_decl)
+ {
+ if (init || DECL_INITIAL (decl) == error_mark_node)
+ DECL_INITIAL (decl) = init;
+ }
+ else if (!TREE_STATIC (decl))
+ initialize_local_var (decl, init);
}
- }
- else if (TREE_STATIC (decl) && type != error_mark_node)
- {
- /* Cleanups for static variables are handled by `finish_file'. */
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+
+ if (TREE_STATIC (decl))
expand_static_init (decl, init);
}
finish_end0:
@@ -8438,7 +9024,7 @@ declare_global_var (name, type)
}
/* Returns a pointer to the `atexit' function. Note that if
- FLAG_USE_CXA_ATEXIT is non-zero, then this will actually be the new
+ FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
`__cxa_atexit' function specified in the IA64 C++ ABI. */
static tree
@@ -8567,9 +9153,8 @@ start_cleanup_fn ()
{
tree parmdecl;
- parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node);
+ parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
- DECL_ARG_TYPE (parmdecl) = ptr_type_node;
TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
@@ -8636,7 +9221,7 @@ register_dtor_fn (decl)
end_cleanup_fn ();
/* Call atexit with the cleanup function. */
- mark_addressable (cleanup);
+ cxx_mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
@@ -8651,12 +9236,27 @@ register_dtor_fn (decl)
finish_expr_stmt (build_function_call (get_atexit_node (), args));
}
-void
+/* DECL is a VAR_DECL with static storage duration. INIT, if present,
+ is its initializer. Generate code to handle the construction
+ and destruction of DECL. */
+
+static void
expand_static_init (decl, init)
tree decl;
tree init;
{
- tree oldstatic = value_member (decl, static_aggregates);
+ tree oldstatic;
+
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
+ my_friendly_assert (TREE_STATIC (decl), 20021010);
+
+ /* Some variables require no initialization. */
+ if (!init
+ && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ return;
+
+ oldstatic = value_member (decl, static_aggregates);
if (oldstatic)
{
@@ -8706,15 +9306,7 @@ expand_static_init (decl, init)
then_clause = begin_compound_stmt (/*has_no_scope=*/0);
/* Do the initialization itself. */
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
- || (init && TREE_CODE (init) == TREE_LIST))
- assignment = build_aggr_init (decl, init, 0);
- else if (init)
- /* The initialization we're doing here is just a bitwise
- copy. */
- assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- else
- assignment = NULL_TREE;
+ assignment = init ? init : NULL_TREE;
/* Once the assignment is complete, set TEMP to 1. Since the
construction of the static object is complete at this point,
@@ -8954,7 +9546,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
- /* Propagate volatile out from type to decl. */
+ /* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
@@ -9045,13 +9637,19 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
+ DID_INLINE_FUNC (decl) = 0;
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
/* We inline functions that are explicitly declared inline, or, when
the user explicitly asks us to, all functions. */
- if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+ if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
+ if (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag)
+ {
+ DID_INLINE_FUNC (decl) = 1;
+ DECL_INLINE (decl) = 1;
+ }
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@@ -9105,7 +9703,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
/* Due to bison parser ickiness, we will have already looked
up an operator_name or PFUNCNAME within the current class
(see template_id in parse.y). If the current class contains
- such a name, we'll get a COMPONENT_REF here. Undo that. */
+ such a name, we'll get a COMPONENT_REF here. Undo that. */
my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
== current_class_type, 20001120);
@@ -9197,7 +9795,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = DECL_TEMPLATE_RESULT (decl);
/* Attempt to merge the declarations. This can fail, in
- the case of some illegal specialization declarations. */
+ the case of some invalid specialization declarations. */
if (!duplicate_decls (decl, old_decl))
error ("no `%#D' member function declared in class `%T'",
decl, ctype);
@@ -9217,64 +9815,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
return decl;
}
+/* Create a VAR_DECL named NAME with the indicated TYPE.
+
+ If SCOPE is non-NULL, it is the class type or namespace containing
+ the variable. If SCOPE is NULL, the variable should is created in
+ the innermost enclosings scope. */
+
static tree
-grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
+grokvardecl (type, name, specbits_in, initialized, constp, scope)
tree type;
- tree declarator;
+ tree name;
RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
- tree in_namespace;
+ tree scope;
{
tree decl;
RID_BIT_TYPE specbits;
+ my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
+ 20020808);
+
specbits = *specbits_in;
- if (TREE_CODE (type) == OFFSET_TYPE)
+ /* Compute the scope in which to place the variable. */
+ if (!scope)
{
- /* If you declare a static member so that it
- can be initialized, the code will reach here. */
- tree basetype = TYPE_OFFSET_BASETYPE (type);
- type = TREE_TYPE (type);
- decl = build_lang_decl (VAR_DECL, declarator, type);
- DECL_CONTEXT (decl) = basetype;
- }
+ /* An explicit "extern" specifier indicates a namespace-scope
+ variable. */
+ if (RIDBIT_SETP (RID_EXTERN, specbits))
+ scope = current_namespace;
+ else if (!at_function_scope_p ())
+ {
+ scope = current_scope ();
+ if (!scope)
+ scope = current_namespace;
+ }
+ }
+
+ if (scope
+ && (/* If the variable is a namespace-scope variable declared in a
+ template, we need DECL_LANG_SPECIFIC. */
+ (TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
+ /* Similarly for namespace-scope variables with language linkage
+ other than C++. */
+ || (TREE_CODE (scope) == NAMESPACE_DECL
+ && current_lang_name != lang_name_cplusplus)
+ /* Similarly for static data members. */
+ || TYPE_P (scope)))
+ decl = build_lang_decl (VAR_DECL, name, type);
else
- {
- tree context;
+ decl = build_decl (VAR_DECL, name, type);
- if (in_namespace)
- context = in_namespace;
- else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
- context = current_namespace;
- else
- context = NULL_TREE;
-
- /* For namespace-scope variables, declared in a template, we
- need the full lang_decl. The same is true for
- namespace-scope variables that do not have C++ language
- linkage. */
- if (context
- && (processing_template_decl
- || current_lang_name != lang_name_cplusplus))
- decl = build_lang_decl (VAR_DECL, declarator, type);
- else
- decl = build_decl (VAR_DECL, declarator, type);
-
- if (context)
- set_decl_namespace (decl, context, 0);
-
- context = DECL_CONTEXT (decl);
- if (declarator && context && current_lang_name != lang_name_c)
- /* We can't mangle lazily here because we don't have any
- way to recover whether or not a variable was `extern
- "C"' later. */
- mangle_decl (decl);
- }
+ if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+ set_decl_namespace (decl, scope, 0);
+ else
+ DECL_CONTEXT (decl) = scope;
- if (in_namespace)
- set_decl_namespace (decl, in_namespace, 0);
+ if (name && scope && current_lang_name != lang_name_c)
+ /* We can't mangle lazily here because we don't have any
+ way to recover whether or not a variable was `extern
+ "C"' later. */
+ mangle_decl (decl);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -9305,6 +9907,16 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
+ if (RIDBIT_SETP (RID_THREAD, specbits))
+ {
+ if (targetm.have_tls)
+ DECL_THREAD_LOCAL (decl) = 1;
+ else
+ /* A mere warning is sure to result in improper semantics
+ at runtime. Don't bother to allow this to compile. */
+ error ("thread-local storage not supported for this target");
+ }
+
if (TREE_PUBLIC (decl))
{
/* [basic.link]: A name with no linkage (notably, the name of a class
@@ -9330,8 +9942,7 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
-build_ptrmemfunc_type (type)
- tree type;
+build_ptrmemfunc_type (tree type)
{
tree fields[4];
tree t;
@@ -9390,6 +10001,14 @@ build_ptrmemfunc_type (type)
return t;
}
+/* Create and return a pointer to data member type. */
+
+tree
+build_ptrmem_type (tree class_type, tree member_type)
+{
+ return build_pointer_type (build_offset_type (class_type, member_type));
+}
+
/* 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
@@ -9458,7 +10077,7 @@ compute_array_index_type (name, size)
size, integer_one_node));
}
- /* The size might be the result of a cast. */
+ /* The size might be the result of a cast. */
STRIP_TYPE_NOPS (size);
/* It might be a const variable or enumeration constant. */
@@ -9863,7 +10482,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
break;
case ADDR_EXPR: /* C++ reference declaration */
- /* Fall through. */
+ /* Fall through. */
case ARRAY_REF:
case INDIRECT_REF:
ctype = NULL_TREE;
@@ -9881,6 +10500,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree attributes;
+ if (decl_context != NORMAL)
+ {
+ error ("variable declaration is not allowed here");
+ return error_mark_node;
+ }
+
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
@@ -9905,7 +10530,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else
error ("invalid declarator");
- return 0;
+ return NULL_TREE;
}
innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE)
@@ -9913,10 +10538,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (ctype
&& TREE_OPERAND (decl, 0)
&& (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
- && ((DECL_NAME (TREE_OPERAND (decl, 0))
- == constructor_name_full (ctype))
- || (DECL_NAME (TREE_OPERAND (decl, 0))
- == constructor_name (ctype)))))
+ && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
+ ctype)))
TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0);
decl = *next;
@@ -9947,7 +10570,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
dname = DECL_NAME (get_first_fn (dname));
}
}
- /* Fall through. */
+ /* Fall through. */
case IDENTIFIER_NODE:
if (TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -10022,11 +10645,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype = cname;
}
+ /* If the parser sees something like "void a::b" where
+ "a::b" is a namespace, it will build a SCOPE_REF with
+ a NAMESPACE_DECL, rather than an IDENTIFIER_NODE, as
+ the second operand. Since the SCOPE_REF is being
+ used as a declarator, we recover from that here. */
+ if (TREE_CODE (TREE_OPERAND (decl, 1)) == NAMESPACE_DECL)
+ TREE_OPERAND (decl, 1) = DECL_NAME (TREE_OPERAND (decl, 1));
+
if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
- && ((DECL_NAME (TREE_OPERAND (decl, 1))
- == constructor_name_full (ctype))
- || (DECL_NAME (TREE_OPERAND (decl, 1))
- == constructor_name (ctype))))
+ && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
+ ctype))
TREE_OPERAND (decl, 1) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 1);
decl = *next;
@@ -10040,8 +10669,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (TREE_CODE (decl) == BIT_NOT_EXPR
&& TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
- && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
- || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
+ && constructor_name_p (TREE_OPERAND (decl, 0),
+ ctype))
{
sfk = sfk_destructor;
ctor_return_type = ctype;
@@ -10075,18 +10704,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
next = 0;
break;
+ case BASELINK:
+ next = &BASELINK_FUNCTIONS (decl);
+ break;
+
case TEMPLATE_DECL:
/* Sometimes, we see a template-name used as part of a
decl-specifier like in
- std::allocator alloc;
- Handle that gracefully. */
- error ("invalid use of template-name '%E' in a declarator",
- decl);
+ std::allocator alloc;
+ Handle that gracefully. */
+ error ("invalid use of template-name '%E' in a declarator", decl);
return error_mark_node;
break;
-
+
default:
- internal_error ("`%D' as declarator", decl);
+ my_friendly_assert (0, 20020917);
}
}
}
@@ -10121,7 +10753,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl_context == NORMAL && !toplevel_bindings_p ())
{
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
if (current_binding_level != 0 && toplevel_bindings_p ())
decl_context = PARM;
@@ -10217,10 +10849,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (RIDBIT_SETP (i, specbits))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+
+ /* Diagnose "__thread extern". Recall that this list
+ is in the reverse order seen in the text. */
+ if (i == (int)RID_THREAD)
+ {
+ if (RIDBIT_SETP (RID_EXTERN, specbits))
+ error ("`__thread' before `extern'");
+ if (RIDBIT_SETP (RID_STATIC, specbits))
+ error ("`__thread' before `static'");
+ }
+
if (i == (int)RID_EXTERN
&& TREE_PURPOSE (spec) == error_mark_node)
/* This extern was part of a language linkage. */
extern_langp = 1;
+
RIDBIT_SET (i, specbits);
goto found;
}
@@ -10429,7 +11073,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = unsigned_type (type);
+ type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
@@ -10517,6 +11161,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
+ if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
if (decl_context == PARM && nclasses > 0)
error ("storage class specifiers invalid in parameter declarations");
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
@@ -10548,6 +11193,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
+ /* "static __thread" and "extern __thread" are allowed. */
+ if (nclasses == 2
+ && RIDBIT_SETP (RID_THREAD, specbits)
+ && (RIDBIT_SETP (RID_EXTERN, specbits)
+ || RIDBIT_SETP (RID_STATIC, specbits)))
+ nclasses = 1;
+
if (nclasses > 1)
error ("multiple storage classes in declaration of `%s'", name);
else if (decl_context != NORMAL && nclasses > 0)
@@ -10603,6 +11255,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
RIDBIT_RESET (RID_REGISTER, specbits);
RIDBIT_RESET (RID_AUTO, specbits);
RIDBIT_RESET (RID_EXTERN, specbits);
+ RIDBIT_RESET (RID_THREAD, specbits);
}
}
else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
@@ -10625,13 +11278,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("top-level declaration of `%s' specifies `auto'", name);
}
+ else if (RIDBIT_SETP (RID_THREAD, specbits)
+ && !RIDBIT_SETP (RID_EXTERN, specbits)
+ && !RIDBIT_SETP (RID_STATIC, specbits))
+ {
+ error ("function-scope `%s' implicitly auto and declared `__thread'",
+ name);
+ RIDBIT_RESET (RID_THREAD, specbits);
+ }
if (nclasses > 0 && friendp)
error ("storage class specifiers invalid in friend function declarations");
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an absolute declarator). */
+ the declared identifier (or NULL_TREE, in an abstract declarator). */
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
@@ -10923,21 +11584,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error ("cannot declare %s to references",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "references" : "pointers");
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
-
- if (TREE_CODE (type) == OFFSET_TYPE
- && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
- || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
- {
- error ("cannot declare pointer to `%#T' member",
- TREE_TYPE (type));
+ error (TREE_CODE (declarator) == ADDR_EXPR
+ ? "cannot declare reference to `%#T'"
+ : "cannot declare pointer to `%#T'", type);
type = TREE_TYPE (type);
}
+ else if (VOID_TYPE_P (type)
+ && (ctype || TREE_CODE (declarator) == ADDR_EXPR))
+ error (ctype ? "cannot declare pointer to `%#T' member"
+ : "cannot declare reference to `%#T'", type);
/* Merge any constancy or volatility into the target type
for the pointer. */
@@ -10948,13 +11603,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (declarator) == ADDR_EXPR)
{
- if (TREE_CODE (type) == VOID_TYPE)
- error ("invalid type: `void &'");
- else
+ if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
+ else if (ctype)
+ type = build_ptrmem_type (ctype, type);
else
type = build_pointer_type (type);
@@ -11027,7 +11682,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* This needs to be here, in case we are called
multiple times. */ ;
else if (TREE_COMPLEXITY (declarator) == -1)
- /* Namespace member. */
+ /* Namespace member. */
pop_decl_namespace ();
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
/* Don't fall out into global scope. Hides real bug? --eichin */ ;
@@ -11141,11 +11796,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype, name, current_class_type);
return void_type_node;
}
- type = build_offset_type (ctype, type);
}
else
{
- incomplete_type_error (NULL_TREE, ctype);
+ cxx_incomplete_type_error (NULL_TREE, ctype);
return error_mark_node;
}
@@ -11160,14 +11814,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (declarator && TREE_CODE (declarator) == CALL_EXPR)
/* In this case, we will deal with it later. */
;
- else
- {
- if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (ctype, TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- else
- type = build_offset_type (ctype, type);
- }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
}
}
break;
@@ -11176,6 +11825,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
declarator = TREE_OPERAND (declarator, 0);
break;
+ case BASELINK:
+ declarator = BASELINK_FUNCTIONS (declarator);
+ break;
+
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
@@ -11213,11 +11866,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = error_mark_node;
}
- if (decl_context == FIELD
+ if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type))
{
- error ("data member may not have variably modified type `%T'", type);
+ if (decl_context == FIELD)
+ error ("data member may not have variably modified type `%T'", type);
+ else
+ error ("parameter may not have variably modified type `%T'", type);
type = error_mark_node;
}
@@ -11231,7 +11887,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (current_class_name == NULL_TREE || decl_context == PARM || friendp)
+ if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -11384,7 +12040,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
{
- tree decl = build_decl (PARM_DECL, NULL_TREE, TREE_VALUE (args));
+ tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
TREE_CHAIN (decl) = decls;
decls = decl;
@@ -11417,22 +12073,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
inlinep = 0;
}
- /* Until core issue 180 is resolved, allow 'friend typename A::B'.
- But don't allow implicit typenames except with a class-key. */
- if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
- || IMPLICIT_TYPENAME_P (type)))
+ if (!current_aggr)
{
+ /* Don't allow friend declaration without a class-key. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- pedwarn ("template parameters cannot be friends");
+ pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
- pedwarn ("\
-friend declaration requires class-key, i.e. `friend class %T::%T'",
- constructor_name (current_class_type),
- TYPE_IDENTIFIER (type));
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. `friend class %T::%D'",
+ TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
- pedwarn ("\
-friend declaration requires class-key, i.e. `friend %#T'",
- type);
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. `friend %#T'",
+ type);
}
/* Only try to do this stuff if we didn't already give up. */
@@ -11528,17 +12181,10 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (decl_context == PARM)
{
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = cp_build_parm_decl (declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
-
- /* Compute the type actually passed in the parmlist,
- for the case where there is no prototype.
- (For example, shorts and chars are passed as ints.)
- When there is a prototype, this is overridden later. */
-
- DECL_ARG_TYPE (decl) = type_promotes_to (type);
}
else if (decl_context == FIELD)
{
@@ -11818,6 +12464,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
error ("storage class `register' invalid for function `%s'", name);
+ else if (RIDBIT_SETP (RID_THREAD, specbits))
+ error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
@@ -11860,23 +12508,23 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (staticp == 1)
{
- int illegal_static = 0;
+ int invalid_static = 0;
/* Don't allow a static member function in a class, and forbid
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
pedwarn ("cannot declare member function `%D' to have static linkage", decl);
- illegal_static = 1;
+ invalid_static = 1;
}
else if (current_function_decl)
{
/* FIXME need arm citation */
error ("cannot declare static function inside another function");
- illegal_static = 1;
+ invalid_static = 1;
}
- if (illegal_static)
+ if (invalid_static)
{
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
@@ -11891,7 +12539,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
decl = grokvardecl (type, declarator, &specbits,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
- in_namespace);
+ ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -11983,13 +12631,16 @@ require_complete_types_for_parms (parms)
/* grokparms will have already issued an error */
TREE_TYPE (parms) = error_mark_node;
else if (complete_type_or_else (TREE_TYPE (parms), parms))
- layout_decl (parms, 0);
+ {
+ layout_decl (parms, 0);
+ DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
+ }
else
TREE_TYPE (parms) = error_mark_node;
}
}
-/* Returns non-zero if T is a local variable. */
+/* Returns nonzero if T is a local variable. */
int
local_variable_p (t)
@@ -12007,7 +12658,7 @@ local_variable_p (t)
return 0;
}
-/* Returns non-zero if T is an automatic local variable or a label.
+/* Returns nonzero if T is an automatic local variable or a label.
(These are the declarations that need to be remapped when the code
containing them is duplicated.) */
@@ -12034,7 +12685,7 @@ local_variable_p_walkfn (tp, walk_subtrees, data)
}
/* Check that ARG, which is a default-argument expression for a
- parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if
+ parameter DECL, is valid. 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. */
@@ -12173,7 +12824,7 @@ grokparms (first_parm)
&& !DECL_NAME (decl) && !result && !chain && !ellipsis)
/* this is a parmlist of `(void)', which is ok. */
break;
- incomplete_type_error (decl, type);
+ cxx_incomplete_type_error (decl, type);
/* It's not a good idea to actually create parameters of
type `void'; other parts of the compiler assume that a
void type terminates the parameter list. */
@@ -12199,7 +12850,7 @@ grokparms (first_parm)
TREE_TYPE (decl) = type;
}
else if (abstract_virtuals_error (decl, type))
- any_error = 1; /* Seems like a good idea. */
+ any_error = 1; /* Seems like a good idea. */
else if (POINTER_TYPE_P (type))
{
/* [dcl.fct]/6, parameter types cannot contain pointers
@@ -12222,11 +12873,6 @@ grokparms (first_parm)
decl, ptr ? "pointer" : "reference", t);
}
- DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (decl) = integer_type_node;
if (!any_error && init)
init = check_default_argument (decl, init);
else
@@ -12262,7 +12908,7 @@ grokparms (first_parm)
first parameter is a reference to non-const qualified T.
This function can be used as a predicate. Positive values indicate
- a copy constructor and non-zero values indicate a copy assignment
+ a copy constructor and nonzero values indicate a copy assignment
operator. */
int
@@ -12567,7 +13213,7 @@ grok_op_properties (decl, friendp)
}
if (operator_code == CALL_EXPR)
- return; /* No restrictions on args. */
+ return; /* No restrictions on args. */
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
@@ -12590,7 +13236,7 @@ grok_op_properties (decl, friendp)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
- if (what)
+ if (what && warn_conversion)
warning ("conversion to %s%s will never use a type conversion operator",
ref ? "a reference to " : "", what);
}
@@ -12771,6 +13417,38 @@ tag_name (code)
}
}
+/* Name lookup in an elaborated-type-specifier (after the keyword
+ indicated by TAG_CODE) has found TYPE. If the
+ elaborated-type-specifier is invalid, issue a diagnostic and return
+ error_mark_node; otherwise, return TYPE itself. */
+
+static tree
+check_elaborated_type_specifier (enum tag_types tag_code,
+ tree type)
+{
+ tree t;
+
+ t = follow_tag_typedef (type);
+
+ /* [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)
+ {
+ error ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (type), tag_name (tag_code));
+ t = error_mark_node;
+ }
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter `%T' after `%s'",
+ type, tag_name (tag_code));
+ t = error_mark_node;
+ }
+
+ return t;
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -12782,29 +13460,16 @@ tag_name (code)
scope.) */
tree
-xref_tag (code_type_node, name, globalize)
- tree code_type_node;
- tree name;
- int globalize;
+xref_tag (enum tag_types tag_code, tree name, tree attributes,
+ bool globalize)
{
- enum tag_types tag_code;
enum tree_code code;
register tree ref, t;
- struct binding_level *b = current_binding_level;
- tree attributes = NULL_TREE;
+ struct cp_binding_level *b = current_binding_level;
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
- "class __attribute__ ((foo)) bar". Extract the attributes so we can
- use them later. */
- if (TREE_CODE (code_type_node) == TREE_LIST)
- {
- attributes = TREE_PURPOSE (code_type_node);
- code_type_node = TREE_VALUE (code_type_node);
- }
+ timevar_push (TV_NAME_LOOKUP);
- tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
switch (tag_code)
{
case record_type:
@@ -12846,7 +13511,7 @@ xref_tag (code_type_node, name, globalize)
TYPE_IDENTIFIER (t));
/* We need to remove the class scope binding for the
- TYPENAME_TYPE as otherwise poplevel_class gets confused. */
+ TYPENAME_TYPE as otherwise poplevel_class gets confused. */
for (shadowed = b->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
@@ -12871,20 +13536,9 @@ xref_tag (code_type_node, name, globalize)
{
if (t)
{
- ref = follow_tag_typedef (t);
-
- /* [dcl.type.elab] If the identifier resolves to a
- typedef-name or a template type-parameter, the
- elaborated-type-specifier is ill-formed. */
- if (!ref)
- {
- pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
- ref = t;
- }
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- error ("using template type parameter `%T' after `%s'",
- t, tag_name (tag_code));
+ ref = check_elaborated_type_specifier (tag_code, t);
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
ref = lookup_tag (code, name, b, 0);
@@ -12903,9 +13557,15 @@ xref_tag (code_type_node, name, globalize)
template, so we want this type. */
ref = DECL_TEMPLATE_RESULT (ref);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
+ if (ref && TREE_CODE (ref) == TYPE_DECL)
+ {
+ ref = check_elaborated_type_specifier (tag_code,
+ TREE_TYPE (ref));
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (ref && TREE_CODE (ref) != code)
+ ref = NULL_TREE;
+ }
else
ref = NULL_TREE;
}
@@ -12914,7 +13574,7 @@ xref_tag (code_type_node, name, globalize)
&& template_class_depth (current_class_type)
&& PROCESSING_REAL_TEMPLATE_DECL_P ())
{
- /* Since GLOBALIZE is non-zero, we are not looking at a
+ /* Since GLOBALIZE is nonzero, 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:
@@ -12986,14 +13646,14 @@ xref_tag (code_type_node, name, globalize)
}
else
{
- struct binding_level *old_b = class_binding_level;
+ struct cp_binding_level *old_b = class_binding_level;
ref = make_aggr_type (code);
TYPE_CONTEXT (ref) = context;
#ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */
- class_binding_level = (struct binding_level *)0;
+ class_binding_level = (struct cp_binding_level *)0;
#endif
pushtag (name, ref, globalize);
class_binding_level = old_b;
@@ -13007,7 +13667,7 @@ xref_tag (code_type_node, name, globalize)
TYPE_ATTRIBUTES (ref) = attributes;
- return ref;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
@@ -13015,18 +13675,17 @@ xref_tag_from_type (old, id, globalize)
tree old, id;
int globalize;
{
- tree code_type_node;
+ enum tag_types tag_kind;
if (TREE_CODE (old) == RECORD_TYPE)
- code_type_node = (CLASSTYPE_DECLARED_CLASS (old)
- ? class_type_node : record_type_node);
+ tag_kind = (CLASSTYPE_DECLARED_CLASS (old) ? class_type : record_type);
else
- code_type_node = union_type_node;
+ tag_kind = union_type;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (code_type_node, id, globalize);
+ return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize);
}
/* REF is a type (named NAME), for which we have just seen some
@@ -13036,9 +13695,7 @@ xref_tag_from_type (old, id, globalize)
struct, or union. */
void
-xref_basetypes (code_type_node, name, ref, binfo)
- tree code_type_node;
- tree name ATTRIBUTE_UNUSED;
+xref_basetypes (ref, binfo)
tree ref;
tree binfo;
{
@@ -13050,21 +13707,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
int i, len;
enum tag_types tag_code;
- /* If we are called from the parser, code_type_node will sometimes be a
- TREE_LIST. This indicates that the user wrote
- "class __attribute__ ((foo)) bar". Extract the attributes so that
- tree_low_cst doesn't crash. */
- if (TREE_CODE (code_type_node) == TREE_LIST)
- code_type_node = TREE_VALUE (code_type_node);
-
- tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
-
- if (tag_code == union_type)
+ if (TREE_CODE (ref) == UNION_TYPE)
{
error ("derived union `%T' invalid", ref);
return;
}
+ tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
+
len = list_length (binfo);
/* First, make sure that any templates in base-classes are
@@ -13225,7 +13875,7 @@ start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -13270,47 +13920,56 @@ finish_enum (enumtype)
/* We built up the VALUES in reverse order. */
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
- /* [dcl.enum]
-
- Following the closing brace of an enum-specifier, each
- enumerator has the type of its enumeration. Prior to the
- closing brace, the type of each enumerator is the type of
- its initializing value. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-
- /* For a enum defined in a template, all further processing is
- postponed until the template is instantiated. */
+ /* For an enum defined in a template, just set the type of the values;
+ all further processing is postponed until the template is
+ instantiated. We need to set the type so that tsubst of a CONST_DECL
+ works. */
if (processing_template_decl)
{
- tree scope = current_scope ();
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
-
-
return;
}
- /* Figure out what the minimum and maximum values of the enumerators
- are. */
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
- for (pair = TYPE_VALUES (enumtype);
- pair;
- pair = TREE_CHAIN (pair))
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
{
- tree value;
+ tree decl = TREE_VALUE (pair);
+ tree value = DECL_INITIAL (decl);
- value = DECL_INITIAL (TREE_VALUE (pair));
+ /* [dcl.enum]: Following the closing brace of an enum-specifier,
+ each enumerator has the type of its enumeration. Prior to the
+ closing brace, the type of each enumerator is the type of its
+ initializing value. */
+ TREE_TYPE (decl) = enumtype;
+ /* Figure out what the minimum and maximum values of the
+ enumerators are. */
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;
+
+ /* Set the TREE_TYPE for the values 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). But first make a copy so we
+ don't clobber shared INTEGER_CSTs. */
+ if (TREE_TYPE (value) != enumtype)
+ {
+ value = DECL_INITIAL (decl) = copy_node (value);
+ TREE_TYPE (value) = enumtype;
+ }
+
+ /* In addition, transform the TYPE_VALUES list to contain the
+ values, rather than the CONST_DECLs for them. */
+ TREE_VALUE (pair) = value;
}
}
else
@@ -13325,36 +13984,36 @@ finish_enum (enumtype)
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
- /* Set the TREE_TYPE for the values 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). In addition, transform the TYPE_VALUES
- list to contain the values, rather than the CONST_DECLs for them. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ /* DR 377
+
+ IF no integral type can represent all the enumerator values, the
+ enumeration is ill-formed. */
+ if (precision > TYPE_PRECISION (long_long_integer_type_node))
{
- tree value = DECL_INITIAL (TREE_VALUE (pair));
-
- TREE_TYPE (value) = enumtype;
- TREE_VALUE (pair) = value;
+ error ("no integral type can represent all of the enumerator values "
+ "for `%T'", enumtype);
+ precision = TYPE_PRECISION (long_long_integer_type_node);
}
- /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
- TYPE_SIZE (enumtype) = NULL_TREE;
+ /* Compute the minium and maximum values for the type, the size of
+ the type, and so forth. */
TYPE_PRECISION (enumtype) = precision;
+ TYPE_SIZE (enumtype) = NULL_TREE;
if (unsignedp)
fixup_unsigned_type (enumtype);
else
fixup_signed_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);
-
- TYPE_SIZE (enumtype) = NULL_TREE;
- layout_type (enumtype);
+ /* We use "int" or "unsigned int" as the underlying type, unless all
+ the values will not fit or the user has requested that we try to
+ use shorter types where possible. */
+ if (precision < TYPE_PRECISION (integer_type_node)
+ && !flag_short_enums)
+ {
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_SIZE (enumtype) = NULL_TREE;
+ layout_type (enumtype);
+ }
/* Fix up all variant types of this enum type. */
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
@@ -13388,7 +14047,6 @@ build_enumerator (name, value, enumtype)
tree decl;
tree context;
tree type;
- tree values;
/* Remove no-op casts from the value. */
if (value)
@@ -13420,7 +14078,7 @@ build_enumerator (name, value, enumtype)
if (TYPE_VALUES (enumtype))
{
- /* The next value is the previous value ... */
+ /* The next value is the previous value ... */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
/* ... plus one. */
value = cp_build_binary_op (PLUS_EXPR,
@@ -13435,26 +14093,9 @@ build_enumerator (name, value, enumtype)
}
/* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-#if 0
- /* To fix MAX_VAL enum consts. (bkoz) */
- TREE_TYPE (value) = integer_type_node;
-#endif
+ STRIP_TYPE_NOPS (value);
}
- /* 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. But, we don't need to make a copy if this
- VALUE is one of the enumeration constants for this same
- enumeration type. */
- for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
- if (TREE_VALUE (values) == value)
- break;
- /* If we didn't break out of the loop, then we do need a copy. */
- if (!values && value)
- value = copy_node (value);
-
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
@@ -13470,7 +14111,7 @@ build_enumerator (name, value, enumtype)
initializing value.
In finish_enum we will reset the type. Of course, if we're
- processing a template, there may be no value. */
+ processing a template, there may be no value. */
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
@@ -13569,10 +14210,8 @@ start_function (declspecs, declarator, attrs, flags)
tree ctype = NULL_TREE;
tree fntype;
tree restype;
- extern int have_extern_spec;
- extern int used_extern_spec;
int doing_friend = 0;
- struct binding_level *bl;
+ struct cp_binding_level *bl;
tree current_function_parms;
/* Sanity check. */
@@ -13580,10 +14219,10 @@ start_function (declspecs, declarator, attrs, flags)
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
/* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
if (flags & SF_PRE_PARSED)
@@ -13622,7 +14261,7 @@ start_function (declspecs, declarator, attrs, flags)
cplus_decl_attributes (&decl1, attrs, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
@@ -13781,7 +14420,7 @@ start_function (declspecs, declarator, attrs, flags)
decl1 = pushdecl (decl1);
else
{
- /* We need to set the DECL_CONTEXT. */
+ /* We need to set the DECL_CONTEXT. */
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
/* And make sure we have enough default args. */
@@ -13796,12 +14435,8 @@ start_function (declspecs, declarator, attrs, flags)
/* If we are (erroneously) defining a function that we have already
defined before, wipe out what we knew before. */
- if (!DECL_PENDING_INLINE_P (decl1)
- && DECL_SAVED_FUNCTION_DATA (decl1))
- {
- free (DECL_SAVED_FUNCTION_DATA (decl1));
- DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
- }
+ if (!DECL_PENDING_INLINE_P (decl1))
+ DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
{
@@ -13983,7 +14618,6 @@ store_parm_decls (current_function_parms)
function. This is all and only the PARM_DECLs that were
pushed into scope by the loop above. */
DECL_ARGUMENTS (fndecl) = getdecls ();
- storetags (gettags ());
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -14010,7 +14644,7 @@ static void
save_function_data (decl)
tree decl;
{
- struct cp_language_function *f;
+ struct language_function *f;
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
@@ -14018,9 +14652,9 @@ save_function_data (decl)
19990908);
/* Make a copy. */
- f = ((struct cp_language_function *)
- xmalloc (sizeof (struct cp_language_function)));
- memcpy (f, cp_function_chain, sizeof (struct cp_language_function));
+ f = ((struct language_function *)
+ ggc_alloc (sizeof (struct language_function)));
+ memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
@@ -14050,9 +14684,6 @@ save_function_data (decl)
static void
begin_constructor_body ()
{
- tree ctor_stmt = build_stmt (CTOR_STMT);
- CTOR_BEGIN_P (ctor_stmt) = 1;
- add_stmt (ctor_stmt);
}
/* Add a note to mark the end of the main body of the constructor. This is
@@ -14062,12 +14693,6 @@ begin_constructor_body ()
static void
finish_constructor_body ()
{
- /* Mark the end of the cleanups for a partially constructed object.
-
- ??? These should really be handled automatically by closing the block,
- as with the destructor cleanups; the only difference is that these are
- only run if an exception is thrown. */
- add_stmt (build_stmt (CTOR_STMT));
}
/* Do all the processing for the beginning of a destructor; set up the
@@ -14100,7 +14725,6 @@ begin_destructor_body ()
appropriately, so we just assume that we always need to
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
- current_vcalls_possible_p = &IF_COND (if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
@@ -14112,6 +14736,10 @@ begin_destructor_body ()
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
+
+ /* And insert cleanups for our bases and members so that they
+ will be properly destroyed if we throw. */
+ push_base_cleanups ();
}
/* At the end of every destructor we generate code to delete the object if
@@ -14126,14 +14754,11 @@ finish_destructor_body ()
and member cleanups will be run when the function returns. */
add_stmt (build_stmt (LABEL_STMT, dtor_label));
- /* And perform cleanups for our bases and members. */
- perform_base_cleanups ();
-
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
{
tree if_stmt;
- tree virtual_size = c_sizeof (current_class_type);
+ tree virtual_size = cxx_sizeof (current_class_type);
/* [class.dtor]
@@ -14236,6 +14861,15 @@ finish_function (flags)
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && DECL_VIRTUAL_P (fndecl)
+ && !processing_template_decl)
+ {
+ tree fnclass = DECL_CONTEXT (fndecl);
+ if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+ keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ }
+
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
@@ -14273,6 +14907,12 @@ finish_function (flags)
/* If we're saving up tree structure, tie off the function now. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* If this function can't throw any exceptions, remember that. */
+ if (!processing_template_decl
+ && !cp_function_chain->can_throw
+ && !flag_non_call_exceptions)
+ TREE_NOTHROW (fndecl) = 1;
+
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
@@ -14307,11 +14947,20 @@ finish_function (flags)
if (current_function_return_value)
{
tree r = current_function_return_value;
- /* This is only worth doing for fns that return in memory--and
- simpler, since we don't have to worry about promoted modes. */
+ tree outer;
+
if (r != error_mark_node
- && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ /* This is only worth doing for fns that return in memory--and
+ simpler, since we don't have to worry about promoted modes. */
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+ /* Only allow this for variables declared in the outer scope of
+ the function so we know that their lifetime always ends with a
+ return; see g++.dg/opt/nrv6.C. We could be more flexible if
+ we were to do this optimization in tree-ssa. */
+ && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)),
+ chain_member (r, BLOCK_VARS (outer))))
{
+
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
@@ -14369,7 +15018,7 @@ finish_function (flags)
free_after_compilation (cfun);
cfun = NULL;
- /* If this is a in-class inline definition, we may have to pop the
+ /* If this is an 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. */
@@ -14386,7 +15035,7 @@ finish_function (flags)
if (! nested)
/* Let the error reporting routines know that we're outside a
function. For a nested function, this value is used in
- pop_cp_function_context and then reset via pop_function_context. */
+ cxx_pop_function_context and then reset via pop_function_context. */
current_function_decl = NULL_TREE;
return fndecl;
@@ -14451,6 +15100,7 @@ start_method (declspecs, declarator, attrlist)
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
@@ -14598,7 +15248,7 @@ complete_vars (type)
here. */
tree
-maybe_build_cleanup (decl)
+cxx_maybe_build_cleanup (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
@@ -14612,7 +15262,7 @@ maybe_build_cleanup (decl)
rval = decl;
else
{
- mark_addressable (decl);
+ cxx_mark_addressable (decl);
rval = build_unary_op (ADDR_EXPR, decl, 0);
}
@@ -14675,14 +15325,14 @@ revert_static_member_fn (decl)
/* Initialize the variables used during compilation of a C++
function. */
-static void
-push_cp_function_context (f)
+void
+cxx_push_function_context (f)
struct function *f;
{
- struct cp_language_function *p
- = ((struct cp_language_function *)
- xcalloc (1, sizeof (struct cp_language_function)));
- f->language = (struct language_function *) p;
+ struct language_function *p
+ = ((struct language_function *)
+ ggc_alloc_cleared (sizeof (struct language_function)));
+ f->language = p;
/* It takes an explicit call to expand_body to generate RTL for a
function. */
@@ -14696,141 +15346,30 @@ push_cp_function_context (f)
/* Free the language-specific parts of F, now that we've finished
compiling the function. */
-static void
-pop_cp_function_context (f)
+void
+cxx_pop_function_context (f)
struct function *f;
{
- if (f->language)
- {
- struct cp_language_function *cp =
- (struct cp_language_function *) f->language;
- if (cp->x_local_names)
- VARRAY_FREE (cp->x_local_names);
- free (f->language);
- }
f->language = 0;
}
-/* Mark P for GC. */
+/* Return which tree structure is used by T, or TS_CP_GENERIC if T is
+ one of the language-independent trees. */
-static void
-mark_lang_function (p)
- struct cp_language_function *p;
+enum cp_tree_node_structure_enum
+cp_tree_node_structure (t)
+ union lang_tree_node *t;
{
- if (!p)
- return;
-
- mark_c_language_function (&p->base);
-
- ggc_mark_tree (p->x_dtor_label);
- ggc_mark_tree (p->x_current_class_ptr);
- ggc_mark_tree (p->x_current_class_ref);
- ggc_mark_tree (p->x_eh_spec_block);
- ggc_mark_tree_varray (p->x_local_names);
-
- mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
- mark_binding_level (&p->bindings);
- mark_pending_inlines (&p->unparsed_inlines);
-}
-
-/* Mark the language-specific data in F for GC. */
-
-static void
-mark_cp_function_context (f)
- struct function *f;
-{
- mark_lang_function ((struct cp_language_function *) f->language);
-}
-
-void
-lang_mark_tree (t)
- tree t;
-{
- enum tree_code code = TREE_CODE (t);
- if (code == IDENTIFIER_NODE)
- {
- struct lang_identifier *li = (struct lang_identifier *) t;
- struct lang_id2 *li2 = li->x;
- ggc_mark_tree (li->namespace_bindings);
- ggc_mark_tree (li->bindings);
- ggc_mark_tree (li->class_value);
- ggc_mark_tree (li->class_template_info);
-
- if (li2)
- {
- ggc_mark_tree (li2->label_value);
- ggc_mark_tree (li2->implicit_decl);
- ggc_mark_tree (li2->error_locus);
- }
- }
- else if (code == CPLUS_BINDING)
+ switch (TREE_CODE (&t->generic))
{
- if (BINDING_HAS_LEVEL_P (t))
- mark_binding_level (&BINDING_LEVEL (t));
- else
- ggc_mark_tree (BINDING_SCOPE (t));
- ggc_mark_tree (BINDING_VALUE (t));
- }
- else if (code == OVERLOAD)
- ggc_mark_tree (OVL_FUNCTION (t));
- else if (code == TEMPLATE_PARM_INDEX)
- ggc_mark_tree (TEMPLATE_PARM_DECL (t));
- else if (TREE_CODE_CLASS (code) == 'd')
- {
- struct lang_decl *ld = DECL_LANG_SPECIFIC (t);
-
- if (ld)
- {
- ggc_mark (ld);
- c_mark_lang_decl (&ld->decl_flags.base);
- if (!DECL_GLOBAL_CTOR_P (t)
- && !DECL_GLOBAL_DTOR_P (t)
- && !DECL_THUNK_P (t)
- && !DECL_DISCRIMINATOR_P (t))
- ggc_mark_tree (ld->decl_flags.u2.access);
- else if (DECL_THUNK_P (t))
- ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
- if (TREE_CODE (t) != NAMESPACE_DECL)
- ggc_mark_tree (ld->decl_flags.u.template_info);
- else
- mark_binding_level (&NAMESPACE_LEVEL (t));
- if (CAN_HAVE_FULL_LANG_DECL_P (t))
- {
- ggc_mark_tree (ld->befriending_classes);
- ggc_mark_tree (ld->context);
- ggc_mark_tree (ld->cloned_function);
- if (TREE_CODE (t) == TYPE_DECL)
- ggc_mark_tree (ld->u.sorted_fields);
- else if (TREE_CODE (t) == FUNCTION_DECL
- && !DECL_PENDING_INLINE_P (t))
- mark_lang_function (DECL_SAVED_FUNCTION_DATA (t));
- }
- }
- }
- else if (TREE_CODE_CLASS (code) == 't')
- {
- struct lang_type *lt = TYPE_LANG_SPECIFIC (t);
-
- if (lt && !(TREE_CODE (t) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
- {
- ggc_mark (lt);
- ggc_mark_tree (lt->primary_base);
- ggc_mark_tree (lt->vfields);
- ggc_mark_tree (lt->vbases);
- ggc_mark_tree (lt->tags);
- ggc_mark_tree (lt->size);
- ggc_mark_tree (lt->pure_virtuals);
- ggc_mark_tree (lt->friend_classes);
- ggc_mark_tree (lt->rtti);
- ggc_mark_tree (lt->methods);
- ggc_mark_tree (lt->template_info);
- ggc_mark_tree (lt->befriending_classes);
- }
- else if (lt)
- /* In the case of pointer-to-member function types, the
- TYPE_LANG_SPECIFIC is really just a tree. */
- ggc_mark_tree ((tree) lt);
+ case DEFAULT_ARG: return TS_CP_IDENTIFIER;
+ case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
+ case OVERLOAD: return TS_CP_OVERLOAD;
+ case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
+ case PTRMEM_CST: return TS_CP_PTRMEM;
+ case WRAPPER: return TS_CP_WRAPPER;
+ case SRCLOC: return TS_CP_SRCLOC;
+ default: return TS_CP_GENERIC;
}
}
@@ -14860,3 +15399,6 @@ cp_missing_noreturn_ok_p (decl)
/* A missing noreturn is ok for the `main' function. */
return DECL_MAIN_P (decl);
}
+
+#include "gt-cp-decl.h"
+#include "gtype-cp.h"
diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h
index 2316f06..2b917a4 100644
--- a/contrib/gcc/cp/decl.h
+++ b/contrib/gcc/cp/decl.h
@@ -36,13 +36,7 @@ extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int,
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
-extern tree last_function_parms;
-
-/* 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
- in the TREE_PURPOSE slot. */
-extern tree static_aggregates;
+extern GTY(()) tree last_function_parms;
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index 1dbaaf4..452f9ad 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -44,26 +44,26 @@ Boston, MA 02111-1307, USA. */
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
+#include "c-common.h"
+#include "timevar.h"
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
and/or destructions required for a particular priority level. */
typedef struct priority_info_s {
- /* Non-zero if there have been any initializations at this priority
+ /* Nonzero 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
+ /* Nonzero if there have been any destructions at this priority
throughout the translation unit. */
int destructions_p;
} *priority_info;
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
-static int finish_vtable_vardecl PARAMS ((tree *, void *));
-static int prune_vtable_vardecl PARAMS ((tree *, void *));
-static int is_namespace_ancestor PARAMS ((tree, tree));
+static int maybe_emit_vtables (tree);
static void add_using_namespace PARAMS ((tree, tree, int));
-static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
+static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *,int);
static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
static int acceptable_java_type PARAMS ((tree));
static void output_vtable_inherit PARAMS ((tree));
@@ -84,23 +84,21 @@ static void finish_static_initialization_or_destruction PARAMS ((tree));
static void generate_ctor_or_dtor_function PARAMS ((int, int));
static int generate_ctor_and_dtor_functions_for_priority
PARAMS ((splay_tree_node, void *));
-static tree prune_vars_needing_no_initialization PARAMS ((tree));
+static tree prune_vars_needing_no_initialization PARAMS ((tree *));
static void write_out_vars PARAMS ((tree));
static void import_export_class PARAMS ((tree));
-static tree key_method PARAMS ((tree));
-static int compare_options PARAMS ((const PTR, const PTR));
static tree get_guard_bits PARAMS ((tree));
/* 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, statically, outside the class. */
-static varray_type pending_statics;
+static GTY(()) varray_type pending_statics;
#define pending_statics_used \
(pending_statics ? pending_statics->elements_used : 0)
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
-static varray_type deferred_fns;
+static GTY(()) varray_type deferred_fns;
#define deferred_fns_used \
(deferred_fns ? deferred_fns->elements_used : 0)
@@ -117,623 +115,10 @@ int at_eof;
tree static_ctors;
tree static_dtors;
-/* The :: namespace. */
+/* The :: namespace. */
tree global_namespace;
-/* C (and C++) language-specific option variables. */
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-int flag_no_asm;
-
-/* Nonzero means don't recognize any extension keywords. */
-
-int flag_no_gnu_keywords;
-
-/* Nonzero means do some things the same way PCC does. Only provided so
- the compiler will link. */
-
-int flag_traditional;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-int flag_signed_bitfields = 1;
-
-/* Nonzero means enable obscure standard features and disable GNU
- extensions that might cause standard-compliant code to be
- miscompiled. */
-
-int flag_ansi;
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-int flag_implement_inlines = 1;
-
-/* Nonzero means do emit exported implementations of templates, instead of
- multiple static copies in each file that needs a definition. */
-
-int flag_external_templates;
-
-/* Nonzero means that the decision to emit or not emit the implementation of a
- template depends on where the template is instantiated, rather than where
- it is defined. */
-
-int flag_alt_external_templates;
-
-/* Nonzero means that implicit instantiations will be emitted if needed. */
-
-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 things that will change when compiling
- with an ABI-compliant compiler. */
-
-int warn_abi = 0;
-
-/* Nonzero means warn about implicit declarations. */
-
-int warn_implicit = 1;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-int warn_long_long = 1;
-
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-int warn_ctor_dtor_privacy = 1;
-
-/* Nonzero means generate separate instantiation control files and juggle
- them at link time. */
-
-int flag_use_repository;
-
-/* Nonzero if we want to issue diagnostics that the standard says are not
- required. */
-
-int flag_optional_diags = 1;
-
-/* Nonzero means give string constants the type `const char *', 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;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith = 1;
-
-/* Nonzero means warn for any function def without prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls;
-
-/* Warn if initializer is not completely bracketed. */
-
-int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values. */
-
-int warn_sign_compare;
-
-/* Warn about testing equality of floating point numbers. */
-
-int warn_float_equal = 0;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-int warn_missing_format_attribute;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-
-int warn_overloaded_virtual;
-
-/* Non-zero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
-
-int warn_nonvdtor;
-
-/* Non-zero means warn when the compiler will reorder code. */
-
-int warn_reorder;
-
-/* Non-zero means warn when synthesis behavior differs from Cfront's. */
-
-int warn_synth;
-
-/* Non-zero means warn when we convert a pointer to member function
- into a pointer to (void or function). */
-
-int warn_pmf2ptr = 1;
-
-/* Nonzero means warn about violation of some Effective C++ style rules. */
-
-int warn_ecpp;
-
-/* Nonzero means warn where overload resolution chooses a promotion from
- unsigned to signed over a conversion to an unsigned of the same size. */
-
-int warn_sign_promo;
-
-/* Nonzero means warn when an old-style cast is used. */
-
-int warn_old_style_cast;
-
-/* Warn about #pragma directives that are not recognised. */
-
-int warn_unknown_pragmas; /* Tri state variable. */
-
-/* Nonzero means warn about use of multicharacter literals. */
-
-int warn_multichar = 1;
-
-/* Nonzero means 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
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-
-int flag_ms_extensions;
-
-/* C++ specific flags. */
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-int flag_elide_constructors = 1;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-int flag_default_inline = 1;
-
-/* Controls whether compiler generates 'type descriptor' that give
- run-time type information. */
-
-int flag_rtti = 1;
-
-/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
-
-int flag_huge_objects;
-
-/* Nonzero if we want to conserve space in the .o files. We do this
- by putting uninitialized data and runtime initialized data into
- .common instead of .data at the expense of not flagging multiple
- definitions. */
-
-int flag_conserve_space;
-
-/* Nonzero if we want to obey access control semantics. */
-
-int flag_access_control = 1;
-
-/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */
-
-int flag_operator_names = 1;
-
-/* Nonzero if we want to check the return value of new and avoid calling
- constructors if it is a null pointer. */
-
-int flag_check_new;
-
-/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
- initialization variables.
- 0: Old rules, set by -fno-for-scope.
- 2: New ISO rules, set by -ffor-scope.
- 1: Try to implement new ISO rules, but with backup compatibility
- (and warnings). This is the default, for now. */
-
-int flag_new_for_scope = 1;
-
-/* Nonzero if we want to emit defined symbols with common-like linkage as
- weak symbols where possible, in order to conform to C++ semantics.
- Otherwise, emit them as local symbols. */
-
-int flag_weak = 1;
-
-/* Nonzero to use __cxa_atexit, rather than atexit, to register
- destructors for local statics and global objects. */
-
-int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
-
-/* Maximum template instantiation depth. This limit is rather
- arbitrary, but it exists to limit the time it takes to notice
- infinite template instantiations. */
-
-int max_tinst_depth = 500;
-
-/* 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;
-
-/* Nonzero means to implement standard semantics for exception
- specifications, calling unexpected if an exception is thrown that
- doesn't match the specification. Zero means to treat them as
- assertions and optimize accordingly, but not check them. */
-
-int flag_enforce_eh_specs = 1;
-
-/* Table of language-dependent -f options.
- STRING is the option name. VARIABLE is the address of the variable.
- ON_VALUE is the value to store in VARIABLE
- if `-fSTRING' is seen as an option.
- (If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-
-static const struct { const char *const string; int *const variable; const 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},
- {"unsigned-bitfields", &flag_signed_bitfields, 0},
- {"short-enums", &flag_short_enums, 1},
- {"short-double", &flag_short_double, 1},
- {"short-wchar", &flag_short_wchar, 1},
- {"asm", &flag_no_asm, 0},
- {"builtin", &flag_no_builtin, 0},
-
- /* 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},
- {"enforce-eh-specs", &flag_enforce_eh_specs, 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},
- {"implement-inlines", &flag_implement_inlines, 1},
- {"implicit-inline-templates", &flag_implicit_inline_templates, 1},
- {"implicit-templates", &flag_implicit_templates, 1},
- {"ms-extensions", &flag_ms_extensions, 1},
- {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
- {"operator-names", &flag_operator_names, 1},
- {"optional-diags", &flag_optional_diags, 1},
- {"permissive", &flag_permissive, 1},
- {"repo", &flag_use_repository, 1},
- {"rtti", &flag_rtti, 1},
- {"stats", &flag_detailed_statistics, 1},
- {"vtable-gc", &flag_vtable_gc, 1},
- {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
- {"weak", &flag_weak, 1}
-};
-
-/* The list of `-f' options that we no longer support. The `-f'
- prefix is not given in this table. The `-fno-' variants are not
- listed here. This table must be kept in alphabetical order. */
-static const char * const unsupported_options[] = {
- "all-virtual",
- "cond-mismatch",
- "enum-int-equiv",
- "guiding-decls",
- "honor-std",
- "huge-objects",
- "labels-ok",
- "new-abi",
- "nonnull-objects",
- "squangle",
- "strict-prototype",
- "this-is-variable",
- "vtable-thunks",
- "xref"
-};
-
-/* Compare two option strings, pointed two by P1 and P2, for use with
- bsearch. */
-
-static int
-compare_options (p1, p2)
- const PTR p1;
- const PTR p2;
-{
- return strcmp (*((const char *const *) p1), *((const char *const *) p2));
-}
-
-/* Decode the string P as a language-specific option.
- Return the number of strings consumed for a valid option.
- Otherwise return 0. Should not complain if it does not
- recognise the option. */
-
-int
-cxx_decode_option (argc, argv)
- int argc;
- char **argv;
-{
- int strings_processed;
- const char *p = argv[0];
-
- strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
-
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- /* ignore */;
- else if (p[0] == '-' && p[1] == 'f')
- {
- /* Some kind of -f option.
- P's value is the option sans `-f'.
- Search for it in the table of options. */
- const char *option_value = NULL;
- const char *positive_option;
- size_t j;
-
- p += 2;
- /* Try special -f options. */
-
- /* See if this is one of the options no longer supported. We
- used to support these options, so we continue to accept them,
- with a warning. */
- if (strncmp (p, "no-", strlen ("no-")) == 0)
- positive_option = p + strlen ("no-");
- else
- positive_option = p;
-
- /* If the option is present, issue a warning. Indicate to our
- caller that the option was processed successfully. */
- if (bsearch (&positive_option,
- unsupported_options,
- (sizeof (unsupported_options)
- / sizeof (unsupported_options[0])),
- sizeof (unsupported_options[0]),
- compare_options))
- {
- warning ("-f%s is no longer supported", p);
- return 1;
- }
-
- if (!strcmp (p, "handle-exceptions")
- || !strcmp (p, "no-handle-exceptions"))
- warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
- else if (! strcmp (p, "alt-external-templates"))
- {
- flag_external_templates = 1;
- flag_alt_external_templates = 1;
- cp_deprecated ("-falt-external-templates");
- }
- else if (! strcmp (p, "no-alt-external-templates"))
- flag_alt_external_templates = 0;
- else if (!strcmp (p, "repo"))
- {
- flag_use_repository = 1;
- flag_implicit_templates = 0;
- }
- else if (!strcmp (p, "external-templates"))
- {
- flag_external_templates = 1;
- cp_deprecated ("-fexternal-templates");
- }
- else if ((option_value
- = skip_leading_substring (p, "template-depth-")))
- max_tinst_depth
- = read_integral_parameter (option_value, p - 2, max_tinst_depth);
- else if ((option_value
- = skip_leading_substring (p, "name-mangling-version-")))
- {
- warning ("-fname-mangling-version is no longer supported");
- return 1;
- }
- else if (dump_switch_p (p))
- ;
- else
- {
- int found = 0;
-
- for (j = 0;
- !found && j < (sizeof (lang_f_options)
- / sizeof (lang_f_options[0]));
- j++)
- {
- if (!strcmp (p, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = lang_f_options[j].on_value;
- /* A goto here would be cleaner,
- but breaks the VAX pcc. */
- found = 1;
- }
- else if (p[0] == 'n' && p[1] == 'o' && p[2] == '-'
- && ! strcmp (p+3, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = ! lang_f_options[j].on_value;
- found = 1;
- }
- }
-
- return found;
- }
- }
- else if (p[0] == '-' && p[1] == 'W')
- {
- int setting = 1;
-
- /* The -W options control the warning behavior of the compiler. */
- p += 2;
-
- if (p[0] == 'n' && p[1] == 'o' && p[2] == '-')
- setting = 0, p += 3;
-
- if (!strcmp (p, "abi"))
- warn_abi = setting;
- else if (!strcmp (p, "implicit"))
- warn_implicit = setting;
- else if (!strcmp (p, "long-long"))
- warn_long_long = setting;
- else if (!strcmp (p, "return-type"))
- warn_return_type = setting;
- else if (!strcmp (p, "ctor-dtor-privacy"))
- warn_ctor_dtor_privacy = setting;
- else if (!strcmp (p, "write-strings"))
- warn_write_strings = setting;
- else if (!strcmp (p, "cast-qual"))
- warn_cast_qual = setting;
- else if (!strcmp (p, "char-subscripts"))
- warn_char_subscripts = setting;
- else if (!strcmp (p, "pointer-arith"))
- warn_pointer_arith = setting;
- else if (!strcmp (p, "missing-prototypes"))
- warn_missing_prototypes = setting;
- else if (!strcmp (p, "strict-prototypes"))
- {
- if (setting == 0)
- warning ("-Wno-strict-prototypes is not supported in C++");
- }
- else if (!strcmp (p, "redundant-decls"))
- warn_redundant_decls = setting;
- else if (!strcmp (p, "missing-braces"))
- warn_missing_braces = setting;
- else if (!strcmp (p, "sign-compare"))
- warn_sign_compare = setting;
- else if (!strcmp (p, "float-equal"))
- warn_float_equal = setting;
- else if (!strcmp (p, "format"))
- set_Wformat (setting);
- else if (!strcmp (p, "format=2"))
- set_Wformat (2);
- else if (!strcmp (p, "format-y2k"))
- warn_format_y2k = setting;
- else if (!strcmp (p, "format-extra-args"))
- warn_format_extra_args = setting;
- else if (!strcmp (p, "format-nonliteral"))
- warn_format_nonliteral = setting;
- else if (!strcmp (p, "format-security"))
- warn_format_security = setting;
- else if (!strcmp (p, "missing-format-attribute"))
- warn_missing_format_attribute = setting;
- else if (!strcmp (p, "conversion"))
- warn_conversion = setting;
- else if (!strcmp (p, "parentheses"))
- warn_parentheses = setting;
- else if (!strcmp (p, "non-virtual-dtor"))
- warn_nonvdtor = setting;
- else if (!strcmp (p, "reorder"))
- warn_reorder = setting;
- else if (!strcmp (p, "synth"))
- warn_synth = setting;
- else if (!strcmp (p, "pmf-conversions"))
- warn_pmf2ptr = setting;
- else if (!strcmp (p, "effc++"))
- warn_ecpp = setting;
- else if (!strcmp (p, "sign-promo"))
- warn_sign_promo = setting;
- else if (!strcmp (p, "old-style-cast"))
- warn_old_style_cast = setting;
- else if (!strcmp (p, "overloaded-virtual"))
- warn_overloaded_virtual = setting;
- else if (!strcmp (p, "multichar"))
- warn_multichar = setting;
- else if (!strcmp (p, "unknown-pragmas"))
- /* Set to greater than 1, so that even unknown pragmas in
- system headers will be warned about. */
- warn_unknown_pragmas = setting * 2;
- else if (!strcmp (p, "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"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "trigraphs"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "import"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "all"))
- {
- warn_return_type = setting;
- set_Wunused (setting);
- warn_implicit = setting;
- warn_switch = setting;
- set_Wformat (setting);
- warn_parentheses = setting;
- warn_missing_braces = setting;
- warn_sign_compare = 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);
- /* Only warn about unknown pragmas that are not in system
- headers. */
- 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;
- }
- else if (!strcmp (p, "-ansi"))
- flag_no_nonansi_builtin = 1, flag_ansi = 1,
- flag_noniso_default_format_attributes = 0, flag_no_gnu_keywords = 1;
-#ifdef SPEW_DEBUG
- /* Undocumented, only ever used when you're invoking cc1plus by hand, since
- it's probably safe to assume no sane person would ever want to use this
- under normal circumstances. */
- else if (!strcmp (p, "-spew-debug"))
- spew_debug = 1;
-#endif
- else
- return strings_processed;
-
- return 1;
-}
-
/* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
QUALS is a list of qualifiers. Returns any explicit
@@ -836,6 +221,19 @@ grok_x_components (specs)
finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t));
}
+/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
+ appropriately. */
+
+tree
+cp_build_parm_decl (name, type)
+ tree name;
+ tree type;
+{
+ tree parm = build_decl (PARM_DECL, name, type);
+ DECL_ARG_TYPE (parm) = type_passed_as (type);
+ return parm;
+}
+
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */
@@ -844,14 +242,11 @@ build_artificial_parm (name, type)
tree name;
tree type;
{
- tree parm;
-
- parm = build_decl (PARM_DECL, name, type);
+ tree parm = cp_build_parm_decl (name, type);
DECL_ARTIFICIAL (parm) = 1;
/* All our artificial parms are implicitly `const'; they cannot be
assigned to. */
TREE_READONLY (parm) = 1;
- DECL_ARG_TYPE (parm) = type;
return parm;
}
@@ -1139,7 +534,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node;
}
- /* Deleting ptr to void is undefined behaviour [expr.delete/3]. */
+ /* Deleting ptr to void is undefined behavior [expr.delete/3]. */
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
{
warning ("deleting `%T' is undefined", type);
@@ -1183,7 +578,7 @@ check_member_template (tmpl)
if (current_function_decl)
/* 14.5.2.2 [temp.mem]
- A local class shall not have member templates. */
+ A local class shall not have member templates. */
error ("invalid declaration of member template `%#D' in local class",
decl);
@@ -1206,7 +601,7 @@ check_member_template (tmpl)
error ("template declaration of `%#D'", decl);
}
-/* Return true iff TYPE is a valid Java parameter or return type. */
+/* Return true iff TYPE is a valid Java parameter or return type. */
static int
acceptable_java_type (type)
@@ -1278,11 +673,8 @@ tree
check_classfn (ctype, function)
tree ctype, function;
{
- tree fn_name = DECL_NAME (function);
- tree fndecl, fndecls;
- tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
- tree *methods = 0;
- tree *end = 0;
+ int ix;
+ int is_template;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
@@ -1299,81 +691,99 @@ check_classfn (ctype, function)
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)
+
+ /* OK, is this a definition of a member template? */
+ is_template = (TREE_CODE (function) == TEMPLATE_DECL
+ || (processing_template_decl - template_class_depth (ctype)));
+
+ ix = lookup_fnfields_1 (complete_type (ctype),
+ DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
+ DECL_DESTRUCTOR_P (function) ? dtor_identifier :
+ DECL_NAME (function));
+
+ if (ix >= 0)
{
- methods = &TREE_VEC_ELT (method_vec, 0);
- end = TREE_VEC_END (method_vec);
-
- /* First suss out ctors and dtors. */
- if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
- && DECL_CONSTRUCTOR_P (function))
- goto got_it;
- if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
- && DECL_DESTRUCTOR_P (function))
- goto got_it;
-
- while (++methods != end && *methods)
+ tree methods = CLASSTYPE_METHOD_VEC (ctype);
+ tree fndecls, fndecl = 0;
+ bool is_conv_op;
+ const char *format = NULL;
+
+ for (fndecls = TREE_VEC_ELT (methods, ix);
+ fndecls; fndecls = OVL_NEXT (fndecls))
{
- fndecl = *methods;
- if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
+ tree p1, p2;
+
+ fndecl = OVL_CURRENT (fndecls);
+ p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
+ p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+
+ /* We cannot simply call decls_match because this doesn't
+ work for static member functions that are pretending to
+ be methods, and because the name may have been changed by
+ asm("new_name"). */
+
+ /* Get rid of the this parameter on functions that become
+ static. */
+ if (DECL_STATIC_FUNCTION_P (fndecl)
+ && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+ p1 = TREE_CHAIN (p1);
+
+ /* A member template definition only matches a member template
+ declaration. */
+ if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
+ continue;
+
+ 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;
+ }
+ error ("prototype for `%#D' does not match any in class `%T'",
+ function, ctype);
+ is_conv_op = DECL_CONV_FN_P (fndecl);
+
+ if (is_conv_op)
+ ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ fndecls = TREE_VEC_ELT (methods, ix);
+ while (fndecls)
+ {
+ fndecl = OVL_CURRENT (fndecls);
+ fndecls = OVL_NEXT (fndecls);
+
+ if (!fndecls && is_conv_op)
{
- got_it:
- for (fndecls = *methods; fndecls != NULL_TREE;
- fndecls = OVL_NEXT (fndecls))
+ if (TREE_VEC_LENGTH (methods) > ix)
{
- fndecl = OVL_CURRENT (fndecls);
-
- /* We cannot simply call decls_match because this
- doesn't work for static member functions that are
- pretending to be methods, and because the name
- may have been changed by asm("new_name"). */
- if (DECL_NAME (function) == DECL_NAME (fndecl))
+ ix++;
+ fndecls = TREE_VEC_ELT (methods, ix);
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
- tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-
- /* Get rid of the this parameter on functions that become
- static. */
- if (DECL_STATIC_FUNCTION_P (fndecl)
- && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- p1 = TREE_CHAIN (p1);
-
- 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;
+ fndecls = NULL_TREE;
+ is_conv_op = false;
}
}
- break; /* loser */
+ else
+ is_conv_op = false;
}
+ if (format)
+ format = " %#D";
+ else if (fndecls)
+ format = "candidates are: %#D";
+ else
+ format = "candidate is: %#D";
+ cp_error_at (format, fndecl);
}
}
-
- if (methods != end && *methods)
- {
- tree fndecl = *methods;
- error ("prototype for `%#D' does not match any in class `%T'",
- function, ctype);
- cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is",
- OVL_CURRENT (fndecl));
- while (fndecl = OVL_NEXT (fndecl), fndecl)
- cp_error_at (" %#D", OVL_CURRENT(fndecl));
- }
+ else if (!COMPLETE_TYPE_P (ctype))
+ cxx_incomplete_type_error (function, ctype);
else
- {
- methods = 0;
- if (!COMPLETE_TYPE_P (ctype))
- incomplete_type_error (function, ctype);
- else
- error ("no `%#D' member function declared in class `%T'",
- function, ctype);
- }
+ 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 (unless the CTYPE is not yet defined, in which
@@ -1592,12 +1002,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
init = decl_constant_value (init);
else if (TREE_CODE (init) == CONSTRUCTOR)
init = digest_init (TREE_TYPE (value), init, (tree *)0);
- if (init == error_mark_node)
- /* We must make this look different than `error_mark_node'
- because `decl_const_value' would mis-interpret it
- as only meaning that this VAR_DECL is defined. */
- init = build1 (NOP_EXPR, TREE_TYPE (value), init);
- else if (! TREE_CONSTANT (init))
+ if (init != error_mark_node && ! TREE_CONSTANT (init))
{
/* We can allow references to things that are effectively
static, since references are initialized with the
@@ -1614,7 +1019,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
}
}
- if (processing_template_decl && ! current_function_decl
+ if (processing_template_decl
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value);
@@ -1722,11 +1127,29 @@ grokbitfield (declarator, declspecs, width)
return value;
}
+/* Convert a conversion operator name to an identifier. SCOPE is the
+ scope of the conversion operator, if explicit. */
+
tree
-grokoptypename (declspecs, declarator)
+grokoptypename (declspecs, declarator, scope)
tree declspecs, declarator;
+ tree scope;
{
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
+
+ /* Resolve any TYPENAME_TYPEs that refer to SCOPE, before mangling
+ the name, so that we mangle the right thing. */
+ if (scope && current_template_parms
+ && uses_template_parms (t)
+ && uses_template_parms (scope))
+ {
+ tree args = current_template_args ();
+
+ push_scope (scope);
+ t = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ pop_scope (scope);
+ }
+
return mangle_conv_op_name_for_type (t);
}
@@ -1845,6 +1268,16 @@ constructor_name (thing)
return thing;
return t;
}
+
+/* Returns TRUE if NAME is the name for the constructor for TYPE. */
+
+bool
+constructor_name_p (tree name, tree type)
+{
+ return (name == constructor_name (type)
+ || name == constructor_name_full (type));
+}
+
/* Defer the compilation of the FN until the end of compilation. */
@@ -1971,7 +1404,7 @@ finish_anon_union (anon_union_decl)
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
- /* The VAR_DECL's context is the same as the TYPE's context. */
+ /* The VAR_DECL's context is the same as the TYPE's context. */
DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
if (TYPE_FIELDS (type) == NULL_TREE)
@@ -2191,7 +1624,7 @@ comdat_linkage (decl)
DECL_COMMON (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
- else
+ else if (!DECL_EXPLICIT_INSTANTIATION (decl))
{
/* We can't do anything useful; leave vars for explicit
instantiation. */
@@ -2217,7 +1650,7 @@ maybe_make_one_only (decl)
one. However, that's not actually the case in SVR4; a strong definition
after a weak one is an error. Also, not making explicit
instantiations one_only means that we can end up with two copies of
- some template instantiations. */
+ some template instantiations. */
if (! flag_weak)
return;
@@ -2236,34 +1669,6 @@ maybe_make_one_only (decl)
}
}
-/* Returns the virtual function with which the vtable for TYPE is
- emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
-
-static tree
-key_method (type)
- tree type;
-{
- tree method;
-
- if (TYPE_FOR_JAVA (type)
- || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || CLASSTYPE_INTERFACE_KNOWN (type))
- return NULL_TREE;
-
- for (method = TYPE_METHODS (type); method != NULL_TREE;
- method = TREE_CHAIN (method))
- if (DECL_VINDEX (method) != NULL_TREE
- && ! DECL_DECLARED_INLINE_P (method)
- && (! DECL_PURE_VIRTUAL_P (method)
-#if 0
- /* This would be nice, but we didn't think of it in time. */
- || DECL_DESTRUCTOR_P (method)
-#endif
- ))
- return method;
-
- return NULL_TREE;
-}
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags.
@@ -2297,7 +1702,7 @@ import_export_vtable (decl, type, final)
functions in our class, or if we come from a template. */
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || key_method (type));
+ || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found)
{
@@ -2357,7 +1762,7 @@ import_export_class (ctype)
if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype))
{
- tree method = key_method (ctype);
+ tree method = CLASSTYPE_KEY_METHOD (ctype);
if (method)
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
@@ -2401,28 +1806,52 @@ output_vtable_inherit (vars)
assemble_vtable_inherit (child_rtx, parent_rtx);
}
+/* If necessary, write out the vtables for the dynamic class CTYPE.
+ Returns nonzero if any vtables were emitted. */
+
static int
-finish_vtable_vardecl (t, data)
- tree *t;
- void *data ATTRIBUTE_UNUSED;
+maybe_emit_vtables (tree ctype)
{
- tree vars = *t;
- tree ctype = DECL_CONTEXT (vars);
+ tree vtbl;
+ tree primary_vtbl;
+
+ /* If the vtables for this class have already been emitted there is
+ nothing more to do. */
+ primary_vtbl = CLASSTYPE_VTABLES (ctype);
+ if (TREE_ASM_WRITTEN (primary_vtbl))
+ return 0;
+ /* Ignore dummy vtables made by get_vtable_decl. */
+ if (TREE_TYPE (primary_vtbl) == void_type_node)
+ return 0;
+
import_export_class (ctype);
- import_export_vtable (vars, ctype, 1);
+ import_export_vtable (primary_vtbl, ctype, 1);
- if (! DECL_EXTERNAL (vars)
- && DECL_NEEDED_P (vars)
- && ! TREE_ASM_WRITTEN (vars))
+ /* See if any of the vtables are needed. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+ break;
+
+ if (!vtbl)
+ {
+ /* If the references to this class' vtables are optimized away,
+ still emit the appropriate debugging information. See
+ dfs_debug_mark. */
+ if (DECL_COMDAT (primary_vtbl)
+ && CLASSTYPE_DEBUG_REQUESTED (ctype))
+ note_debug_info_needed (ctype);
+ return 0;
+ }
+
+ /* The ABI requires that we emit all of the vtables if we emit any
+ of them. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
- if (TREE_TYPE (vars) == void_type_node)
- /* It is a dummy vtable made by get_vtable_decl. Ignore it. */
- return 0;
-
/* Write it out. */
- mark_vtable_entries (vars);
- if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
- store_init_value (vars, DECL_INITIAL (vars));
+ import_export_vtable (vtbl, ctype, 1);
+ mark_vtable_entries (vtbl);
+ if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
+ store_init_value (vtbl, DECL_INITIAL (vtbl));
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
@@ -2447,45 +1876,28 @@ finish_vtable_vardecl (t, data)
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
- DECL_IGNORED_P (vars) = 1;
+ DECL_IGNORED_P (vtbl) = 1;
}
/* Always make vtables weak. */
if (flag_weak)
- comdat_linkage (vars);
+ comdat_linkage (vtbl);
- rest_of_decl_compilation (vars, NULL, 1, 1);
+ rest_of_decl_compilation (vtbl, NULL, 1, 1);
if (flag_vtable_gc)
- output_vtable_inherit (vars);
+ output_vtable_inherit (vtbl);
/* Because we're only doing syntax-checking, we'll never end up
actually marking the variable as written. */
if (flag_syntax_only)
- TREE_ASM_WRITTEN (vars) = 1;
-
- /* Since we're writing out the vtable here, also write the debug
- info. */
- note_debug_info_needed (ctype);
-
- return 1;
+ TREE_ASM_WRITTEN (vtbl) = 1;
}
- /* If the references to this class' vtables were optimized away, still
- emit the appropriate debugging information. See dfs_debug_mark. */
- if (DECL_COMDAT (vars)
- && CLASSTYPE_DEBUG_REQUESTED (ctype))
- note_debug_info_needed (ctype);
+ /* Since we're writing out the vtable here, also write the debug
+ info. */
+ note_debug_info_needed (ctype);
- return 0;
-}
-
-static int
-prune_vtable_vardecl (t, data)
- tree *t;
- void *data ATTRIBUTE_UNUSED;
-{
- *t = TREE_CHAIN (*t);
return 1;
}
@@ -2556,7 +1968,7 @@ import_export_decl (decl)
}
/* Here, we only decide whether or not the tinfo node should be
- emitted with the vtable. IS_IN_LIBRARY is non-zero iff the
+ emitted with the vtable. IS_IN_LIBRARY is nonzero iff the
typeinfo for TYPE should be in the runtime library. */
void
@@ -2587,7 +1999,7 @@ import_export_tinfo (decl, type, is_in_library)
DECL_COMDAT (decl) = 1;
}
- /* Now override some cases. */
+ /* Now override some cases. */
if (flag_weak)
DECL_COMDAT (decl) = 1;
else if (is_in_library)
@@ -2596,6 +2008,10 @@ import_export_tinfo (decl, type, is_in_library)
DECL_INTERFACE_KNOWN (decl) = 1;
}
+/* Return an expression that performs the destruction of DECL, which
+ must be a VAR_DECL whose type has a non-trivial destructor, or is
+ an array whose (innermost) elements have a non-trivial destructor. */
+
tree
build_cleanup (decl)
tree decl;
@@ -2603,11 +2019,19 @@ build_cleanup (decl)
tree temp;
tree type = TREE_TYPE (decl);
+ /* This function should only be called for declarations that really
+ require cleanups. */
+ my_friendly_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type), 20030106);
+
+ /* Treat all objects with destructors as used; the destructor may do
+ something substantive. */
+ mark_used (decl);
+
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
{
- mark_addressable (decl);
+ cxx_mark_addressable (decl);
temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
}
temp = build_delete (TREE_TYPE (temp), temp,
@@ -2637,7 +2061,7 @@ get_guard (decl)
guard_type = long_long_integer_type_node;
guard = build_decl (VAR_DECL, sname, guard_type);
- /* The guard should have the same linkage as what it guards. */
+ /* The guard should have the same linkage as what it guards. */
TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
@@ -2647,8 +2071,7 @@ get_guard (decl)
DECL_ARTIFICIAL (guard) = 1;
TREE_USED (guard) = 1;
- pushdecl_top_level (guard);
- cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
+ pushdecl_top_level_and_finish (guard, NULL_TREE);
}
return guard;
}
@@ -2754,7 +2177,7 @@ start_objects (method_type, initp)
DECL_GLOBAL_CTOR_P (current_function_decl) = 1;
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
- GLOBAL_INIT_PRIORITY (current_function_decl) = initp;
+ DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
body = begin_compound_stmt (/*has_no_scope=*/0);
@@ -2810,17 +2233,17 @@ finish_objects (method_type, initp, body)
#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
/* The declaration for the __INITIALIZE_P argument. */
-static tree initialize_p_decl;
+static GTY(()) tree initialize_p_decl;
/* The declaration for the __PRIORITY argument. */
-static tree priority_decl;
+static GTY(()) tree priority_decl;
/* The declaration for the static storage duration function. */
-static tree ssdf_decl;
+static GTY(()) tree ssdf_decl;
/* All the static storage duration functions created in this
translation unit. */
-static varray_type ssdf_decls;
+static GTY(()) varray_type ssdf_decls;
/* A map from priority levels to information about that priority
level. There may be many such levels, so efficient lookup is
@@ -2831,7 +2254,7 @@ static splay_tree priority_info_map;
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
+ nonzero, it performs initializations. Otherwise, it performs
destructions. It only performs those initializations or
destructions with the indicated __PRIORITY. The generated function
returns no value.
@@ -2880,7 +2303,7 @@ start_static_storage_duration_function ()
VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
/* Take this opportunity to initialize the map from priority
- numbers to information about that priority level. */
+ numbers to information about that priority level. */
priority_info_map = splay_tree_new (splay_tree_compare_ints,
/*delete_key_fn=*/0,
/*delete_value_fn=*/
@@ -2896,16 +2319,13 @@ start_static_storage_duration_function ()
VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
/* Create the argument list. */
- initialize_p_decl = build_decl (PARM_DECL,
- get_identifier (INITIALIZE_P_IDENTIFIER),
- integer_type_node);
+ initialize_p_decl = cp_build_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);
+ priority_decl = cp_build_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;
@@ -2981,7 +2401,7 @@ get_priority_info (priority)
}
/* Set up to handle the initialization or destruction of DECL. If
- INITP is non-zero, we are initializing the variable. Otherwise, we
+ INITP is nonzero, we are initializing the variable. Otherwise, we
are destroying it. */
static tree
@@ -3121,34 +2541,24 @@ finish_static_initialization_or_destruction (guard_if_stmt)
DECL_STATIC_FUNCTION_P (current_function_decl) = 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, GUARD is the guard variable to
- check. PRIORITY is the priority for the initialization. */
+/* Generate code to do the initialization of DECL, a VAR_DECL with
+ static storage duration. The initialization is INIT. */
static void
do_static_initialization (decl, init)
tree decl;
tree init;
{
- tree expr;
tree guard_if_stmt;
/* Set up for the initialization. */
guard_if_stmt
= start_static_initialization_or_destruction (decl,
/*initp=*/1);
-
- /* Do the initialization itself. */
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expr = build_aggr_init (decl, init, 0);
- else
- {
- expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- TREE_SIDE_EFFECTS (expr) = 1;
- }
- finish_expr_stmt (expr);
+
+ /* Perform the initialization. */
+ if (init)
+ finish_expr_stmt (init);
/* If we're using __cxa_atexit, register a a function that calls the
destructor for the object. */
@@ -3180,7 +2590,7 @@ do_static_destruction (decl)
/* Actually do the destruction. */
guard_if_stmt = start_static_initialization_or_destruction (decl,
- /*initp=*/0);
+ /*initp=*/0);
finish_expr_stmt (build_cleanup (decl));
finish_static_initialization_or_destruction (guard_if_stmt);
}
@@ -3195,21 +2605,23 @@ do_static_destruction (decl)
static tree
prune_vars_needing_no_initialization (vars)
- tree vars;
+ tree *vars;
{
- tree var;
- tree result;
+ tree *var = vars;
+ tree result = NULL_TREE;
- for (var = vars, result = NULL_TREE;
- var;
- var = TREE_CHAIN (var))
+ while (*var)
{
- tree decl = TREE_VALUE (var);
- tree init = TREE_PURPOSE (var);
+ tree t = *var;
+ tree decl = TREE_VALUE (t);
+ tree init = TREE_PURPOSE (t);
/* Deal gracefully with error. */
if (decl == error_mark_node)
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* The only things that can be initialized are variables. */
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
@@ -3217,17 +2629,25 @@ prune_vars_needing_no_initialization (vars)
/* If this object is not defined, we don't need to do anything
here. */
if (DECL_EXTERNAL (decl))
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* 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))
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* This variable is going to need initialization and/or
finalization, so we add it to the list. */
- result = tree_cons (init, decl, result);
+ *var = TREE_CHAIN (t);
+ TREE_CHAIN (t) = result;
+ result = t;
}
return result;
@@ -3273,15 +2693,16 @@ generate_ctor_or_dtor_function (constructor_p, priority)
/* Call the static storage duration function with appropriate
arguments. */
- for (i = 0; i < ssdf_decls->elements_used; ++i)
- {
- arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
- NULL_TREE);
- arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
- arguments);
- finish_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
- arguments));
- }
+ if (ssdf_decls)
+ for (i = 0; i < ssdf_decls->elements_used; ++i)
+ {
+ arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
+ NULL_TREE);
+ arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
+ arguments);
+ finish_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
+ arguments));
+ }
/* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
calls to any functions marked with attributes indicating that
@@ -3289,7 +2710,7 @@ generate_ctor_or_dtor_function (constructor_p, priority)
if (priority == DEFAULT_INIT_PRIORITY)
{
tree fns;
-
+
for (fns = constructor_p ? static_ctors : static_dtors;
fns;
fns = TREE_CHAIN (fns))
@@ -3364,7 +2785,7 @@ finish_file ()
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
+ generating the initializer for an object may cause templates to be
instantiated, etc., etc. */
timevar_push (TV_VARCONST);
@@ -3373,6 +2794,8 @@ finish_file ()
do
{
+ tree t;
+
reconsider = 0;
/* If there are templates that we've put off instantiating, do
@@ -3380,12 +2803,36 @@ finish_file ()
instantiate_pending_templates ();
/* Write out 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 (walk_globals (vtable_decl_p,
- finish_vtable_vardecl,
- /*data=*/0))
- reconsider = 1;
+ the virtual table for a template class may cause the
+ instantiation of members of that class. If we write out
+ vtables then we remove the class from our list so we don't
+ have to look at it again. */
+
+ while (keyed_classes != NULL_TREE
+ && maybe_emit_vtables (TREE_VALUE (keyed_classes)))
+ {
+ reconsider = 1;
+ keyed_classes = TREE_CHAIN (keyed_classes);
+ }
+
+ t = keyed_classes;
+ if (t != NULL_TREE)
+ {
+ tree next = TREE_CHAIN (t);
+
+ while (next)
+ {
+ if (maybe_emit_vtables (TREE_VALUE (next)))
+ {
+ reconsider = 1;
+ TREE_CHAIN (t) = TREE_CHAIN (next);
+ }
+ else
+ t = next;
+
+ next = TREE_CHAIN (t);
+ }
+ }
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
@@ -3397,8 +2844,7 @@ finish_file ()
aggregates added during the initialization of these will be
initialized in the correct order when we next come around the
loop. */
- vars = prune_vars_needing_no_initialization (static_aggregates);
- static_aggregates = NULL_TREE;
+ vars = prune_vars_needing_no_initialization (&static_aggregates);
if (vars)
{
@@ -3446,12 +2892,11 @@ finish_file ()
reconsider = 1;
}
- /* Go through the various inline functions, and see if any need
- synthesizing. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
- import_export_decl (decl);
+
+ /* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
@@ -3466,30 +2911,32 @@ finish_file ()
pop_from_top_level ();
reconsider = 1;
}
- }
- /* 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 unnecessarily. But, we must stop lying
- when the functions are referenced, or if they are not comdat
- since they need to be put out now.
- This is done in a separate for cycle, because if some deferred
- function is contained in another deferred function later in
- deferred_fns varray, rest_of_compilation would skip this
- function and we really cannot expand the same function twice. */
- for (i = 0; i < deferred_fns_used; ++i)
- {
- tree decl = VARRAY_TREE (deferred_fns, i);
-
+ /* If the function has no body, avoid calling
+ import_export_decl. On a system without weak symbols,
+ calling import_export_decl will make an inline template
+ instantiation "static", which will result in errors about
+ the use of undefined functions if there is no body for
+ the function. */
+ if (!DECL_SAVED_TREE (decl))
+ continue;
+
+ import_export_decl (decl);
+
+ /* 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 unnecessarily. But, we must
+ stop lying when the functions are referenced, or if they
+ are not comdat since they need to be put out now. This
+ is done in a separate for cycle, because if some deferred
+ function is contained in another deferred function later
+ in deferred_fns varray, rest_of_compilation would skip
+ this function and we really cannot expand the same
+ function twice. */
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& DECL_NEEDED_P (decl))
DECL_EXTERNAL (decl) = 0;
- }
-
- for (i = 0; i < deferred_fns_used; ++i)
- {
- tree decl = VARRAY_TREE (deferred_fns, i);
/* If we're going to need to write this function out, and
there's already a body for it, create RTL for it now.
@@ -3545,6 +2992,20 @@ finish_file ()
}
while (reconsider);
+ /* All used inline functions must have a definition at this point. */
+ for (i = 0; i < deferred_fns_used; ++i)
+ {
+ tree decl = VARRAY_TREE (deferred_fns, i);
+
+ if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
+ && !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)
+ /* An explicit instantiation can be used to specify
+ that the body is in another unit. It will have
+ already verified there was a definition. */
+ || DECL_EXPLICIT_INSTANTIATION (decl)))
+ cp_warning_at ("inline function `%D' used but never defined", decl);
+ }
+
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
@@ -3554,6 +3015,15 @@ finish_file ()
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/0);
+ else
+ {
+ if (static_ctors)
+ generate_ctor_or_dtor_function (/*constructor_p=*/true,
+ DEFAULT_INIT_PRIORITY);
+ if (static_dtors)
+ generate_ctor_or_dtor_function (/*constructor_p=*/false,
+ DEFAULT_INIT_PRIORITY);
+ }
/* We're done with the splay-tree now. */
if (priority_info_map)
@@ -3563,13 +3033,6 @@ finish_file ()
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. We don't do this if we're just doing semantic
- analysis, and not code-generation. */
- if (!flag_syntax_only)
- walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
-
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
@@ -3580,7 +3043,7 @@ finish_file ()
finish_repo ();
/* The entire file is now complete. If requested, dump everything
- to a file. */
+ to a file. */
{
int flags;
FILE *stream = dump_begin (TDI_all, &flags);
@@ -3621,14 +3084,7 @@ reparse_absdcl_as_expr (type, decl)
/* recurse */
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)
- || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
- decl = require_complete_type (decl);
-
- return decl;
+ return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
@@ -3681,7 +3137,8 @@ reparse_absdcl_as_casts (decl, expr)
return expr;
}
-/* Given plain tree nodes for an expression, build up the full semantics. */
+/* T is the parse tree for an expression. Return the expression after
+ performing semantic analysis. */
tree
build_expr_from_tree (t)
@@ -3697,14 +3154,37 @@ build_expr_from_tree (t)
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
- return do_scoped_id (TREE_OPERAND (t, 0), 0);
+ {
+ tree token = TREE_OPERAND (t, 0);
+ return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
+ }
else
return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
- return (lookup_template_function
- (build_expr_from_tree (TREE_OPERAND (t, 0)),
- build_expr_from_tree (TREE_OPERAND (t, 1))));
+ {
+ tree template;
+ tree args;
+ tree object;
+
+ template = build_expr_from_tree (TREE_OPERAND (t, 0));
+ args = build_expr_from_tree (TREE_OPERAND (t, 1));
+
+ if (TREE_CODE (template) == COMPONENT_REF)
+ {
+ object = TREE_OPERAND (template, 0);
+ template = TREE_OPERAND (template, 1);
+ }
+ else
+ object = NULL_TREE;
+
+ template = lookup_template_function (template, args);
+ if (object)
+ return build (COMPONENT_REF, TREE_TYPE (template),
+ object, template);
+ else
+ return template;
+ }
case INDIRECT_REF:
return build_x_indirect_ref
@@ -3803,8 +3283,10 @@ build_expr_from_tree (t)
case ALIGNOF_EXPR:
{
tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
- return (TREE_CODE (t) == SIZEOF_EXPR
- ? finish_sizeof (r) : finish_alignof (r));
+ if (!TYPE_P (r))
+ return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
+ else
+ return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
case MODOP_EXPR:
@@ -3884,16 +3366,18 @@ build_expr_from_tree (t)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
+ tree fn, scope, args;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
-
- return build_member_call
- (build_expr_from_tree (TREE_OPERAND (ref, 0)),
- name,
- build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+ scope = build_expr_from_tree (TREE_OPERAND (ref, 0));
+ args = build_expr_from_tree (TREE_OPERAND (t, 1));
+ fn = resolve_scoped_fn_name (scope, name);
+
+ return build_call_from_tree (fn, args, 1);
}
else
{
@@ -3906,13 +3390,22 @@ build_expr_from_tree (t)
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, 0)))
{
- /* Do Koenig lookup if there are no class members. */
+ /* Do Koenig lookup if there are no class members. */
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
- || ! really_overloaded_fn (name))
+ || ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
- return build_x_function_call (name, args, current_class_ref);
+
+ if (TREE_CODE (name) == OFFSET_REF)
+ return build_offset_ref_call_from_tree (name, args);
+ if (TREE_CODE (name) == COMPONENT_REF)
+ return finish_object_call_expr (TREE_OPERAND (name, 1),
+ TREE_OPERAND (name, 0),
+ args);
+ name = convert_from_reference (name);
+ return build_call_from_tree (name, args,
+ /*disallow_virtual=*/false);
}
case COND_EXPR:
@@ -3949,18 +3442,8 @@ build_expr_from_tree (t)
case COMPONENT_REF:
{
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);
+ return finish_class_member_access_expr (object,
+ TREE_OPERAND (t, 1));
}
case THROW_EXPR:
@@ -4018,6 +3501,108 @@ build_expr_from_tree (t)
}
}
+/* FN is an OFFSET_REF indicating the function to call in parse-tree
+ form; it has not yet been semantically analyzed. ARGS are the
+ arguments to the function. They have already been semantically
+ analzyed. */
+
+tree
+build_offset_ref_call_from_tree (tree fn, tree args)
+{
+ tree object_addr;
+
+ my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
+
+ /* A qualified name corresponding to a non-static member
+ function or a pointer-to-member is represented as an
+ OFFSET_REF.
+
+ For both of these function calls, FN will be an OFFSET_REF.
+
+ struct A { void f(); };
+ void A::f() { (A::f) (); }
+
+ struct B { void g(); };
+ void (B::*p)();
+ void B::g() { (this->*p)(); } */
+
+ /* This code is not really correct (for example, it does not
+ handle the case that `A::f' is overloaded), but it is
+ historically how we have handled this situation. */
+ if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
+ fn = resolve_offset_ref (fn);
+ else
+ {
+ object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
+ fn = TREE_OPERAND (fn, 1);
+ fn = get_member_function_from_ptrfunc (&object_addr, fn);
+ args = tree_cons (NULL_TREE, object_addr, args);
+ }
+ return build_function_call (fn, args);
+}
+
+/* FN indicates the function to call. Name resolution has been
+ performed on FN. ARGS are the arguments to the function. They
+ have already been semantically analyzed. DISALLOW_VIRTUAL is true
+ if the function call should be determined at compile time, even if
+ FN is virtual. */
+
+tree
+build_call_from_tree (tree fn, tree args, bool disallow_virtual)
+{
+ tree template_args;
+ tree template_id;
+ tree f;
+
+ /* Check to see that name lookup has already been performed. */
+ my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
+ my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
+
+ /* In the future all of this should be eliminated. Instead,
+ name-lookup for a member function should simply return a
+ baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or
+ TEMPLATE_ID_EXPR. */
+
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ {
+ template_id = fn;
+ template_args = TREE_OPERAND (fn, 1);
+ fn = TREE_OPERAND (fn, 0);
+ }
+ else
+ {
+ template_id = NULL_TREE;
+ template_args = NULL_TREE;
+ }
+
+ f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
+ /* Make sure we have a baselink (rather than simply a
+ FUNCTION_DECL) for a member function. */
+ if (current_class_type
+ && ((TREE_CODE (f) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (f))
+ || (DECL_FUNCTION_TEMPLATE_P (f)
+ && DECL_FUNCTION_MEMBER_P (f))))
+ {
+ f = lookup_member (current_class_type, DECL_NAME (f),
+ /*protect=*/1, /*want_type=*/0);
+ if (f)
+ fn = f;
+ }
+
+ if (template_id)
+ {
+ if (BASELINK_P (fn))
+ BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fn),
+ template_args);
+ else
+ fn = template_id;
+ }
+
+ return finish_call_expr (fn, args, disallow_virtual);
+}
+
/* This is something of the form `int (*a)++' that has turned out to be an
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by
@@ -4076,32 +3661,51 @@ finish_decl_parsing (decl)
}
}
-/* Return 1 if root encloses child. */
+/* Returns true if ROOT (a namespace, class, or function) encloses
+ CHILD. CHILD may be either a class type or a namespace. */
-static int
-is_namespace_ancestor (root, child)
- tree root, child;
+bool
+is_ancestor (tree root, tree child)
{
- if (root == child)
- return 1;
+ my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (root)), 20030307);
+ my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (child)),
+ 20030307);
+
+ /* The global namespace encloses everything. */
if (root == global_namespace)
- return 1;
- if (child == global_namespace)
- return 0;
- return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
+ return true;
+
+ while (true)
+ {
+ /* If we've run out of scopes, stop. */
+ if (!child)
+ return false;
+ /* If we've reached the ROOT, it encloses CHILD. */
+ if (root == child)
+ return true;
+ /* Go out one level. */
+ if (TYPE_P (child))
+ child = TYPE_NAME (child);
+ child = DECL_CONTEXT (child);
+ }
}
-
/* Return the namespace that is the common ancestor
- of two given namespaces. */
+ of two given namespaces. */
tree
namespace_ancestor (ns1, ns2)
tree ns1, ns2;
{
- if (is_namespace_ancestor (ns1, ns2))
- return ns1;
- return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2);
+ timevar_push (TV_NAME_LOOKUP);
+ if (is_ancestor (ns1, ns2))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
/* Insert used into the using list of user. Set indirect_flag if this
@@ -4114,40 +3718,42 @@ add_using_namespace (user, used, indirect)
int indirect;
{
tree t;
- /* Using oneself is a no-op. */
+ timevar_push (TV_NAME_LOOKUP);
+ /* Using oneself is a no-op. */
if (user == used)
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
- /* Check if we already have this. */
+ /* Check if we already have this. */
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
{
if (!indirect)
- /* Promote to direct usage. */
+ /* Promote to direct usage. */
TREE_INDIRECT_USING (t) = 0;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
- /* Add used to the user's using list. */
+ /* Add used to the user's using list. */
DECL_NAMESPACE_USING (user)
= tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
- /* Add user to the used's users list. */
+ /* Add user to the used's users list. */
DECL_NAMESPACE_USERS (used)
= tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
- /* Recursively add all namespaces used. */
+ /* Recursively add all namespaces used. */
for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
/* indirect usage */
add_using_namespace (user, TREE_PURPOSE (t), 1);
- /* Tell everyone using us about the new used namespaces. */
+ /* Tell everyone using us about the new used namespaces. */
for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
add_using_namespace (TREE_PURPOSE (t), used, 1);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
@@ -4196,23 +3802,19 @@ merge_functions (s1, s2)
XXX In what way should I treat extern declarations?
XXX I don't want to repeat the entire duplicate_decls here */
-static tree
-ambiguous_decl (name, old, new, flags)
- tree name;
- tree old;
- tree new;
- int flags;
+static cxx_binding *
+ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
{
tree val, type;
- my_friendly_assert (old != NULL_TREE, 393);
- /* Copy the value. */
+ my_friendly_assert (old != NULL, 393);
+ /* Copy the value. */
val = BINDING_VALUE (new);
if (val)
switch (TREE_CODE (val))
{
case TEMPLATE_DECL:
/* If we expect types or namespaces, and not templates,
- or this is not a template class. */
+ or this is not a template class. */
if (LOOKUP_QUALIFIERS_ONLY (flags)
&& !DECL_CLASS_TEMPLATE_P (val))
val = NULL_TREE;
@@ -4247,7 +3849,7 @@ ambiguous_decl (name, old, new, flags)
}
else
{
- /* Some declarations are functions, some are not. */
+ /* Some declarations are functions, some are not. */
if (flags & LOOKUP_COMPLAIN)
{
/* If we've already given this error for this lookup,
@@ -4264,7 +3866,7 @@ ambiguous_decl (name, old, new, flags)
BINDING_VALUE (old) = error_mark_node;
}
}
- /* ... and copy the type. */
+ /* ... and copy the type. */
type = BINDING_TYPE (new);
if (LOOKUP_NAMESPACES_ONLY (flags))
type = NULL_TREE;
@@ -4287,60 +3889,64 @@ ambiguous_decl (name, old, new, flags)
We are currently looking for names in namespace SCOPE, so we
look through USINGS for using-directives of namespaces
which have SCOPE as a common ancestor with the current scope.
- Returns zero on errors. */
+ Returns zero on errors. */
-int
-lookup_using_namespace (name, val, usings, scope, flags, spacesp)
- tree name, val, usings, scope;
- int flags;
- tree *spacesp;
+bool
+lookup_using_namespace (tree name, cxx_binding *val, tree usings,
+ tree scope, int flags, tree *spacesp)
{
tree iter;
- tree val1;
+ cxx_binding *val1;
+ timevar_push (TV_NAME_LOOKUP);
/* Iterate over all used namespaces in current, searching for using
- directives of scope. */
+ directives of scope. */
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
if (spacesp)
*spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE,
*spacesp);
- val1 = binding_for_name (name, TREE_PURPOSE (iter));
- /* Resolve ambiguities. */
- val = ambiguous_decl (name, val, val1, flags);
+ val1 = cxx_scope_find_binding_for_name (TREE_PURPOSE (iter), name);
+ /* Resolve possible ambiguities. */
+ if (val1)
+ val = ambiguous_decl (name, val, val1, flags);
}
- return BINDING_VALUE (val) != error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ BINDING_VALUE (val) != error_mark_node);
}
/* [namespace.qual]
Accepts the NAME to lookup and its qualifying SCOPE.
- Returns the name/type pair found into the CPLUS_BINDING RESULT,
- or 0 on error. */
+ Returns the name/type pair found into the cxx_binding *RESULT,
+ or 0 on error. */
-int
-qualified_lookup_using_namespace (name, scope, result, flags)
- tree name;
- tree scope;
- tree result;
- int flags;
+bool
+qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
+ int flags)
{
- /* Maintain a list of namespaces visited... */
+ /* Maintain a list of namespaces visited... */
tree seen = NULL_TREE;
- /* ... and a list of namespace yet to see. */
+ /* ... and a list of namespace yet to see. */
tree todo = NULL_TREE;
tree usings;
+ timevar_push (TV_NAME_LOOKUP);
/* Look through namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
- while (scope && (result != error_mark_node))
+ while (scope && result->value != error_mark_node)
{
- seen = tree_cons (scope, NULL_TREE, seen);
- result = ambiguous_decl (name, result,
- binding_for_name (name, scope), flags);
+ cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
+ /* Record SCOPE and resolve declaration ambiguities if NAME was
+ bound in SCOPE. */
+ if (b)
+ {
+ seen = tree_cons (scope, NULL_TREE, seen);
+ result = ambiguous_decl (name, result, b, flags);
+ }
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
- /* Consider using directives. */
+ /* Consider using directives. */
for (usings = DECL_NAMESPACE_USING (scope); usings;
usings = TREE_CHAIN (usings))
- /* If this was a real directive, and we have not seen it. */
+ /* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
@@ -4350,15 +3956,15 @@ qualified_lookup_using_namespace (name, scope, result, flags)
todo = TREE_CHAIN (todo);
}
else
- scope = NULL_TREE; /* If there never was a todo list. */
+ scope = NULL_TREE; /* If there never was a todo list. */
}
- return result != error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
}
/* [namespace.memdef]/2 */
/* Set the context of a declaration to scope. Complain if we are not
- outside scope. */
+ outside scope. */
void
set_decl_namespace (decl, scope, friendp)
@@ -4368,20 +3974,20 @@ set_decl_namespace (decl, scope, friendp)
{
tree old;
- /* Get rid of namespace aliases. */
+ /* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
/* It is ok for friends to be qualified in parallel space. */
- if (!friendp && !is_namespace_ancestor (current_namespace, scope))
+ if (!friendp && !is_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
- /* See whether this has been declared in the namespace. */
+ /* See whether this has been declared in the namespace. */
old = namespace_binding (DECL_NAME (decl), scope);
if (!old)
- /* No old declaration at all. */
+ /* No old declaration at all. */
goto complain;
/* A template can be explicitly specialized in any namespace. */
if (processing_explicit_instantiation)
@@ -4391,7 +3997,7 @@ set_decl_namespace (decl, scope, friendp)
since it can't check for the correct constness at this
point. pushdecl will find those errors later. */
return;
- /* Since decl is a function, old should contain a function decl. */
+ /* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
if (processing_template_decl || processing_specialization)
@@ -4411,34 +4017,35 @@ set_decl_namespace (decl, scope, friendp)
decl, scope);
}
-/* Compute the namespace where a declaration is defined. */
+/* Compute the namespace where a declaration is defined. */
static tree
decl_namespace (decl)
tree decl;
{
+ timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
- return global_namespace;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
-/* Return the namespace where the current declaration is declared. */
+/* Return the namespace where the current declaration is declared. */
tree
current_decl_namespace ()
{
tree result;
- /* If we have been pushed into a different namespace, use it. */
+ /* If we have been pushed into a different namespace, use it. */
if (decl_namespace_list)
return TREE_PURPOSE (decl_namespace_list);
@@ -4451,7 +4058,7 @@ current_decl_namespace ()
return result;
}
-/* Temporarily set the namespace for the current declaration. */
+/* Temporarily set the namespace for the current declaration. */
void
push_decl_namespace (decl)
@@ -4469,7 +4076,7 @@ pop_decl_namespace ()
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
-/* Enter a class or namespace scope. */
+/* Enter a class or namespace scope. */
void
push_scope (t)
@@ -4477,11 +4084,11 @@ push_scope (t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
- else
+ else if (CLASS_TYPE_P (t))
pushclass (t, 2);
}
-/* Leave scope pushed by push_scope. */
+/* Leave scope pushed by push_scope. */
void
pop_scope (t)
@@ -4489,13 +4096,12 @@ pop_scope (t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
pop_decl_namespace ();
- else
+ else if (CLASS_TYPE_P (t))
popclass ();
}
/* [basic.lookup.koenig] */
-/* A non-zero return value in the functions below indicates an error.
- All nodes allocated in the procedure are on the scratch obstack. */
+/* A nonzero return value in the functions below indicates an error. */
struct arg_lookup
{
@@ -4528,7 +4134,7 @@ add_function (k, fn)
total number of functions being compared, which should usually be the
case. */
- /* We must find only functions, or exactly one non-function. */
+ /* We must find only functions, or exactly one non-function. */
if (!k->functions)
k->functions = fn;
else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
@@ -4642,21 +4248,21 @@ arg_assoc_class (k, type)
if (arg_assoc_namespace (k, context))
return 1;
- /* Process baseclasses. */
+ /* Process baseclasses. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
return 1;
- /* Process friends. */
+ /* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == TREE_PURPOSE (list))
for (friends = TREE_VALUE (list); friends;
friends = TREE_CHAIN (friends))
/* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
+ (i.e. unqualified) declarations. */
if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
- && decl_namespace (TREE_VALUE (friends)) == context)
+ && CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return 1;
@@ -4701,7 +4307,7 @@ arg_assoc_type (k, type)
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
case OFFSET_TYPE:
- /* Pointer to member: associate class type and value type. */
+ /* Pointer to member: associate class type and value type. */
if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type)))
return 1;
return arg_assoc_type (k, TREE_TYPE (type));
@@ -4709,10 +4315,10 @@ arg_assoc_type (k, type)
/* The basetype is referenced in the first arg type, so just
fall through. */
case FUNCTION_TYPE:
- /* Associate the parameter types. */
+ /* Associate the parameter types. */
if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
return 1;
- /* Associate the return type. */
+ /* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -4766,6 +4372,8 @@ arg_assoc (k, n)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
+ if (TREE_CODE (n) == BASELINK)
+ n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
@@ -4819,7 +4427,7 @@ arg_assoc (k, n)
}
/* Performs Koenig lookup depending on arguments, where fns
- are the functions found in normal lookup. */
+ are the functions found in normal lookup. */
tree
lookup_arg_dependent (name, fns, args)
@@ -4830,6 +4438,10 @@ lookup_arg_dependent (name, fns, args)
struct arg_lookup k;
tree fn = NULL_TREE;
+ if (fns == error_mark_node)
+ fns = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
k.name = name;
k.functions = fns;
k.classes = NULL_TREE;
@@ -4844,10 +4456,10 @@ lookup_arg_dependent (name, fns, args)
unqualified_namespace_lookup (name, 0, &k.namespaces);
arg_assoc_args (&k, args);
- return k.functions;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
}
-/* Process a namespace-alias declaration. */
+/* Process a namespace-alias declaration. */
void
do_namespace_alias (alias, namespace)
@@ -4855,21 +4467,21 @@ do_namespace_alias (alias, namespace)
{
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
- /* The parser did not find it, so it's not there. */
+ /* The parser did not find it, so it's not there. */
error ("unknown namespace `%D'", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
- /* Build the alias. */
+ /* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
pushdecl (alias);
}
/* Check a non-member using-declaration. Return the name and scope
- being used, and the USING_DECL, or NULL_TREE on failure. */
+ being used, and the USING_DECL, or NULL_TREE on failure. */
static tree
validate_nonmember_using_decl (decl, scope, name)
@@ -4922,11 +4534,11 @@ validate_nonmember_using_decl (decl, scope, name)
abort ();
if (DECL_P (*name))
*name = DECL_NAME (*name);
- /* Make a USING_DECL. */
+ /* Make a USING_DECL. */
return push_using_decl (*scope, *name);
}
-/* Process local and global using-declarations. */
+/* Process local and global using-declarations. */
static void
do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
@@ -4934,33 +4546,34 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
tree oldval, oldtype;
tree *newval, *newtype;
{
- tree decls;
+ cxx_binding decls;
*newval = *newtype = NULL_TREE;
- decls = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, scope, decls, 0))
+ cxx_binding_clear (&decls);
+ if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
/* Lookup error */
return;
- if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls))
+ if (!decls.value && !decls.type)
{
error ("`%D' not declared", name);
return;
}
- /* Check for using functions. */
- if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
+ /* Check for using functions. */
+ if (decls.value && is_overloaded_fn (decls.value))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
- duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
+ if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
+ error ("`%D' is already declared in this scope", name);
oldval = NULL_TREE;
}
*newval = oldval;
- for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
+ for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
@@ -4982,21 +4595,27 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
- /* If this using declaration introduces a function
- recognized as a built-in, no longer mark it as
- anticipated in this scope. */
- if (DECL_ANTICIPATED (old_fn))
- {
- DECL_ANTICIPATED (old_fn) = 0;
- break;
- }
-
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
- if (!decls_match (new_fn, old_fn))
- error ("`%D' is already declared in this scope", name);
- break;
+ if (decls_match (new_fn, old_fn))
+ {
+ /* If the OLD_FN was a builtin, there is now a
+ real declaration. */
+ if (DECL_ANTICIPATED (old_fn))
+ DECL_ANTICIPATED (old_fn) = 0;
+ break;
+ }
+ else if (!DECL_ANTICIPATED (old_fn))
+ {
+ /* If the OLD_FN was really declared, the
+ declarations don't match. */
+ error ("`%D' is already declared in this scope", name);
+ break;
+ }
+
+ /* If the OLD_FN was not really there, just ignore
+ it and keep going. */
}
}
@@ -5014,13 +4633,13 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
}
else
{
- *newval = BINDING_VALUE (decls);
- if (oldval)
- duplicate_decls (*newval, oldval);
+ *newval = decls.value;
+ if (oldval && !decls_match (*newval, oldval))
+ error ("`%D' is already declared in this scope", name);
}
- *newtype = BINDING_TYPE (decls);
- if (oldtype && *newtype && oldtype != *newtype)
+ *newtype = decls.type;
+ if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
{
error ("using declaration `%D' introduced ambiguous type `%T'",
name, oldtype);
@@ -5028,19 +4647,22 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
}
}
-/* Process a using-declaration not appearing in class or local scope. */
+/* Process a using-declaration not appearing in class or local scope. */
void
do_toplevel_using_decl (decl)
tree decl;
{
- tree scope, name, binding;
+ tree scope, name;
tree oldval, oldtype, newval, newtype;
+ cxx_binding *binding;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
-
+
+ /* A multiple using-declaration is valid, so we call binding_for_name,
+ not just cxx_binding_make. */
binding = binding_for_name (name, current_namespace);
oldval = BINDING_VALUE (binding);
@@ -5048,7 +4670,7 @@ do_toplevel_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
- /* Copy declarations found. */
+ /* Copy declarations found. */
if (newval)
BINDING_VALUE (binding) = newval;
if (newtype)
@@ -5130,6 +4752,13 @@ do_class_using_decl (decl)
}
if (TREE_CODE (name) == TYPE_DECL || TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
+ else if (BASELINK_P (name))
+ {
+ name = BASELINK_FUNCTIONS (name);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (name, 0);
+ name = DECL_NAME (get_first_fn (name));
+ }
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
@@ -5138,7 +4767,7 @@ do_class_using_decl (decl)
return value;
}
-/* Process a using-directive. */
+/* Process a using-directive. */
void
do_using_directive (namespace)
@@ -5152,7 +4781,7 @@ do_using_directive (namespace)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
{
- /* Lookup in lexer did not find a namespace. */
+ /* Lookup in lexer did not find a namespace. */
if (!processing_template_decl)
error ("namespace `%T' undeclared", namespace);
return;
@@ -5195,10 +4824,15 @@ mark_used (decl)
tree decl;
{
TREE_USED (decl) = 1;
- if (processing_template_decl)
+ if (processing_template_decl || skip_evaluation)
return;
- if (!skip_evaluation)
- assemble_external (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
+ && !TREE_ASM_WRITTEN (decl))
+ /* Remember it, so we can check it was defined. */
+ defer_fn (decl);
+
+ assemble_external (decl);
/* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL
@@ -5222,21 +4856,48 @@ mark_used (decl)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
- instantiate_decl (decl, /*defer_ok=*/1);
+ {
+ bool defer;
+
+ /* Normally, we put off instantiating functions in order to
+ improve compile times. Maintaining a stack of active
+ functions is expensive, and the inliner knows to
+ instantiate any functions it might need.
+
+ However, if instantiating this function might help us mark
+ the current function TREE_NOTHROW, we go ahead and
+ instantiate it now. */
+ defer = (!flag_exceptions
+ || TREE_CODE (decl) != FUNCTION_DECL
+ /* If the called function can't throw, we don't need to
+ generate its body to find that out. */
+ || TREE_NOTHROW (decl)
+ || !cfun
+ /* If we already know the current function can't throw,
+ then we don't need to work hard to prove it. */
+ || TREE_NOTHROW (current_function_decl)
+ /* If we already know that the current function *can*
+ throw, there's no point in gathering more
+ information. */
+ || cp_function_chain->can_throw);
+
+ instantiate_decl (decl, defer);
+ }
}
/* Helper function for class_head_decl and class_head_defn
nonterminals. AGGR is the class, union or struct tag. SCOPE is the
explicit scope used (NULL for no scope resolution). ID is the
name. DEFN_P is true, if this is a definition of the class and
- NEW_TYPE_P is set to non-zero, if we push into the scope containing
+ NEW_TYPE_P is set to nonzero, if we push into the scope containing
the to be defined aggregate.
Return a TYPE_DECL for the type declared by ID in SCOPE. */
tree
-handle_class_head (aggr, scope, id, defn_p, new_type_p)
- tree aggr, scope, id;
+handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p)
+ enum tag_types tag_kind;
+ tree scope, id, attributes;
int defn_p;
int *new_type_p;
{
@@ -5286,7 +4947,10 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
if (!decl)
{
- decl = TYPE_MAIN_DECL (xref_tag (aggr, id, !defn_p));
+ decl = xref_tag (tag_kind, id, attributes, !defn_p);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ decl = TYPE_MAIN_DECL (decl);
xrefd_p = true;
}
@@ -5319,6 +4983,18 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
is different to the current scope. */
tree context = CP_DECL_CONTEXT (decl);
+ if (IMPLICIT_TYPENAME_P (context))
+ context = TREE_TYPE (context);
+
+ /* If that scope does not contain the scope in which the
+ class was originally declared, the program is invalid. */
+ if (current && !is_ancestor (current, context))
+ {
+ error ("declaration of `%D' in `%D' which does not "
+ "enclose `%D'", decl, current, CP_DECL_CONTEXT (decl));
+ return NULL_TREE;
+ }
+
*new_type_p = (current != context
&& TREE_CODE (context) != TEMPLATE_TYPE_PARM
&& TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
@@ -5326,27 +5002,79 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
push_scope (context);
if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
- /* It is legal to define a class with a different class key,
+ /* It is valid to define a class with a different class key,
and this changes the default member access. */
CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
- = aggr == class_type_node;
+ = (tag_kind == class_type);
if (!xrefd_p && PROCESSING_REAL_TEMPLATE_DECL_P ())
decl = push_template_decl (decl);
}
+ else
+ {
+ /* For elaborated type specifier in declaration like
+
+ class A::B *a;
+
+ we get an implicit typename here. Let's remove its
+ implicitness so that we don't issue any implicit
+ typename warning later. Note that when defn_p is true,
+ implicitness is still required by begin_class_definition. */
+ if (IMPLICIT_TYPENAME_P (type))
+ decl = TYPE_STUB_DECL (build_typename_type (TYPE_CONTEXT (type),
+ TYPE_IDENTIFIER (type),
+ TYPENAME_TYPE_FULLNAME (type),
+ NULL_TREE));
+ }
return decl;
}
-/* Initialize decl2.c. */
+/* Like handle_class_head but for a definition of a class specialization.
+ DECL is a TYPE_DECL node representing the class. NEW_TYPE_P is set to
+ nonzero, if we push into the scope containing the to be defined
+ aggregate.
-void
-init_decl2 ()
+ Return a TYPE_DECL for the type declared by ID in SCOPE. */
+
+tree
+handle_class_head_apparent_template (decl, new_type_p)
+ tree decl;
+ int *new_type_p;
{
- ggc_add_tree_varray_root (&deferred_fns, 1);
- ggc_add_tree_varray_root (&pending_statics, 1);
- ggc_add_tree_varray_root (&ssdf_decls, 1);
- ggc_add_tree_root (&ssdf_decl, 1);
- ggc_add_tree_root (&priority_decl, 1);
- ggc_add_tree_root (&initialize_p_decl, 1);
+ tree context;
+ tree current;
+
+ if (decl == error_mark_node)
+ return decl;
+
+ current = current_scope ();
+ if (current == NULL_TREE)
+ current = current_namespace;
+
+ *new_type_p = 0;
+
+ /* For a definition, we want to enter the containing scope
+ before looking up any base classes etc. Only do so, if this
+ is different to the current scope. */
+ context = CP_DECL_CONTEXT (decl);
+
+ if (IMPLICIT_TYPENAME_P (context))
+ context = TREE_TYPE (context);
+
+ *new_type_p = (current != context
+ && TREE_CODE (context) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
+ if (*new_type_p)
+ push_scope (context);
+
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key. */
+ CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
+ = (current_aggr == class_type_node);
+
+ return decl;
}
+
+#include "gt-cp-decl2.h"
diff --git a/contrib/gcc/cp/dump.c b/contrib/gcc/cp/dump.c
index 6dd60ba..39e72dc 100644
--- a/contrib/gcc/cp/dump.c
+++ b/contrib/gcc/cp/dump.c
@@ -48,8 +48,7 @@ dump_access (di, t)
}
/* Dump a representation of the specific operator for an overloaded
- operator associated with node t.
-*/
+ operator associated with node t. */
static void
dump_op (di, t)
@@ -264,6 +263,14 @@ cp_dump_tree (dump_info, t)
return 1;
}
+ /* Is it a type used as a base? */
+ if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
+ && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
+ {
+ dump_child ("bfld", TYPE_CONTEXT (t));
+ return 1;
+ }
+
dump_child ("vfld", TYPE_VFIELD (t));
if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t))
dump_string(di, "spec");
@@ -324,7 +331,6 @@ cp_dump_tree (dump_info, t)
dump_string (di, "global init");
if (DECL_GLOBAL_DTOR_P (t))
dump_string (di, "global fini");
- dump_int (di, "prio", GLOBAL_INIT_PRIORITY (t));
}
if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t))
dump_string (di, "pseudo tmpl");
@@ -390,15 +396,6 @@ cp_dump_tree (dump_info, t)
dump_child ("decl", TREE_OPERAND (t, 2));
break;
- case CTOR_STMT:
- dump_stmt (di, t);
- if (CTOR_BEGIN_P (t))
- dump_string (di, "begn");
- else
- dump_string (di, "end");
- dump_next_stmt (di, t);
- break;
-
case HANDLER:
dump_stmt (di, t);
dump_child ("parm", HANDLER_PARMS (t));
@@ -412,12 +409,6 @@ cp_dump_tree (dump_info, t)
dump_next_stmt (di, t);
break;
- case SUBOBJECT:
- dump_stmt (di, t);
- dump_child ("clnp", TREE_OPERAND (t, 0));
- dump_next_stmt (di, t);
- break;
-
case USING_STMT:
dump_stmt (di, t);
dump_child ("nmsp", USING_STMT_NAMESPACE (t));
@@ -428,6 +419,5 @@ cp_dump_tree (dump_info, t)
break;
}
- return 0;
+ return c_dump_tree (di, t);
}
-
diff --git a/contrib/gcc/cp/error.c b/contrib/gcc/cp/error.c
index a0217ae..804c918 100644
--- a/contrib/gcc/cp/error.c
+++ b/contrib/gcc/cp/error.c
@@ -24,10 +24,10 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "cp-tree.h"
#include "real.h"
-#include "obstack.h"
#include "toplev.h"
#include "flags.h"
#include "diagnostic.h"
+#include "langhooks-def.h"
enum pad { none, before, after };
@@ -44,11 +44,6 @@ enum pad { none, before, after };
print_non_consecutive_character ((BUFFER), '<')
#define print_template_argument_list_end(BUFFER) \
print_non_consecutive_character ((BUFFER), '>')
-#define print_whitespace(BUFFER, TFI) \
- do { \
- output_add_space (BUFFER); \
- put_whitespace (TFI) = none; \
- } while (0)
#define print_tree_identifier(BUFFER, TID) \
output_add_string ((BUFFER), IDENTIFIER_POINTER (TID))
#define print_identifier(BUFFER, ID) output_add_string ((BUFFER), (ID))
@@ -104,20 +99,19 @@ static void dump_scope PARAMS ((tree, int));
static void dump_template_parms PARAMS ((tree, int, int));
static const char *function_category PARAMS ((tree));
-static void lang_print_error_function PARAMS ((diagnostic_context *,
- const char *));
-static void maybe_print_instantiation_context PARAMS ((output_buffer *));
-static void print_instantiation_full_context PARAMS ((output_buffer *));
-static void print_instantiation_partial_context PARAMS ((output_buffer *, tree,
+static void maybe_print_instantiation_context PARAMS ((diagnostic_context *));
+static void print_instantiation_full_context PARAMS ((diagnostic_context *));
+static void print_instantiation_partial_context PARAMS ((diagnostic_context *,
+ tree,
const char *, int));
-static void cp_diagnostic_starter PARAMS ((output_buffer *,
- diagnostic_context *));
-static void cp_diagnostic_finalizer PARAMS ((output_buffer *,
- diagnostic_context *));
-static void cp_print_error_function PARAMS ((output_buffer *,
- diagnostic_context *));
-
-static int cp_printer PARAMS ((output_buffer *));
+static void cp_diagnostic_starter PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+static void cp_diagnostic_finalizer PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+static void cp_print_error_function PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+
+static bool cp_printer PARAMS ((output_buffer *, text_info *));
static void print_non_consecutive_character PARAMS ((output_buffer *, int));
static void print_integer PARAMS ((output_buffer *, HOST_WIDE_INT));
static tree locate_error PARAMS ((const char *, va_list));
@@ -125,7 +119,6 @@ static tree locate_error PARAMS ((const char *, va_list));
void
init_error ()
{
- print_error_function = lang_print_error_function;
diagnostic_starter (global_dc) = cp_diagnostic_starter;
diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
diagnostic_format_decoder (global_dc) = cp_printer;
@@ -322,8 +315,8 @@ dump_template_bindings (parms, args)
}
}
-/* Dump into the obstack a human-readable equivalent of TYPE. FLAGS
- controls the format. */
+/* Dump a human-readable equivalent of TYPE. FLAGS controls the
+ format. */
static void
dump_type (t, flags)
@@ -387,7 +380,7 @@ dump_type (t, flags)
which has no name and is not very useful for diagnostics. So
look up the equivalent C type and print its name. */
tree elt = TREE_TYPE (t);
- elt = type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
+ elt = c_common_type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
dump_type (elt, flags);
}
break;
@@ -417,7 +410,7 @@ dump_type (t, flags)
break;
case TEMPLATE_TEMPLATE_PARM:
- /* For parameters inside template signature. */
+ /* For parameters inside template signature. */
if (TYPE_IDENTIFIER (t))
print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
else
@@ -459,7 +452,7 @@ dump_type (t, flags)
break;
}
case TYPENAME_TYPE:
- if (IMPLICIT_TYPENAME_P (t))
+ if (!IMPLICIT_TYPENAME_P (t))
output_add_string (scratch_buffer, "typename ");
dump_typename (t, flags);
break;
@@ -479,7 +472,7 @@ dump_type (t, flags)
default:
sorry_for_unsupported_tree (t);
- /* Fall through to error. */
+ /* Fall through to error. */
case ERROR_MARK:
print_identifier (scratch_buffer, "<type error>");
@@ -692,6 +685,7 @@ dump_type_prefix (t, flags)
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
+ case TYPEOF_TYPE:
dump_type (t, flags);
padding = before;
break;
@@ -788,6 +782,7 @@ dump_type_suffix (t, flags)
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
+ case TYPEOF_TYPE:
break;
default:
@@ -855,7 +850,7 @@ dump_decl (t, flags)
{
if ((flags & TFF_DECL_SPECIFIERS)
&& TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
- /* Say `class T' not just `T'. */
+ /* Say `class T' not just `T'. */
output_add_string (scratch_buffer, "class ");
dump_type (TREE_TYPE (t), flags);
@@ -1013,7 +1008,11 @@ dump_decl (t, flags)
output_add_string (scratch_buffer, "using ");
dump_type (DECL_INITIAL (t), flags);
print_scope_operator (scratch_buffer);
- print_tree_identifier (scratch_buffer, DECL_NAME (t));
+ dump_decl (DECL_NAME (t), flags);
+ break;
+
+ case BASELINK:
+ dump_decl (BASELINK_FUNCTIONS (t), flags);
break;
default:
@@ -1065,7 +1064,7 @@ dump_template_decl (t, flags)
nreverse(orig_parms);
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
- /* Say `template<arg> class TT' not just `template<arg> TT'. */
+ /* Say `template<arg> class TT' not just `template<arg> TT'. */
output_add_string (scratch_buffer, "class ");
}
@@ -1085,7 +1084,7 @@ dump_template_decl (t, flags)
dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
break;
default:
- /* This case can occur with some illegal code. */
+ /* This case can occur with some invalid code. */
dump_type (TREE_TYPE (t),
(flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0));
@@ -1095,7 +1094,7 @@ dump_template_decl (t, flags)
/* Pretty print a function decl. There are several ways we want to print a
function declaration. The TFF_ bits in FLAGS tells us how to behave.
As 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. */
+ is %D which doesn't print the throw specs, and %F which does. */
static void
dump_function_decl (t, flags)
@@ -1189,7 +1188,7 @@ dump_function_decl (t, flags)
/* Print a parameter list. If this is for a member function, the
member object ptr (and any other hidden args) should have
- already been removed. */
+ already been removed. */
static void
dump_parameters (parmtypes, flags)
@@ -1223,7 +1222,7 @@ dump_parameters (parmtypes, flags)
print_right_paren (scratch_buffer);
}
-/* Print an exception specification. T is the exception specification. */
+/* Print an exception specification. T is the exception specification. */
static void
dump_exception_spec (t, flags)
@@ -1256,6 +1255,9 @@ dump_function_name (t, flags)
{
tree name = DECL_NAME (t);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ t = DECL_TEMPLATE_RESULT (t);
+
/* Don't let the user see __comp_ctor et al. */
if (DECL_CONSTRUCTOR_P (t)
|| DECL_DESTRUCTOR_P (t))
@@ -1436,16 +1438,16 @@ dump_expr_list (l, flags)
}
}
-/* Print out an expression E under control of FLAGS. */
+/* Print out an expression E under control of FLAGS. */
static void
dump_expr (t, flags)
tree t;
int flags;
{
- if (t == 0)
- return;
-
+ if (t == 0)
+ return;
+
switch (TREE_CODE (t))
{
case VAR_DECL:
@@ -1534,17 +1536,8 @@ dump_expr (t, flags)
break;
case REAL_CST:
-#ifndef REAL_IS_NOT_DOUBLE
- sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
-#else
- {
- const unsigned char *p = (const unsigned char *) &TREE_REAL_CST (t);
- size_t i;
- strcpy (digit_buffer, "0x");
- for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
- sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
- }
-#endif
+ real_to_decimal (digit_buffer, &TREE_REAL_CST (t),
+ sizeof (digit_buffer), 0, 1);
output_add_string (scratch_buffer, digit_buffer);
break;
@@ -1657,6 +1650,7 @@ dump_expr (t, flags)
case NEW_EXPR:
{
tree type = TREE_OPERAND (t, 1);
+ tree init = TREE_OPERAND (t, 2);
if (NEW_EXPR_USE_GLOBAL (t))
print_scope_operator (scratch_buffer);
output_add_string (scratch_buffer, "new ");
@@ -1673,10 +1667,17 @@ dump_expr (t, flags)
TREE_OPERAND (type, 1),
integer_one_node))));
dump_type (type, flags);
- if (TREE_OPERAND (t, 2))
+ if (init)
{
print_left_paren (scratch_buffer);
- dump_expr_list (TREE_OPERAND (t, 2), flags);
+ if (TREE_CODE (init) == TREE_LIST)
+ dump_expr_list (init, flags);
+ else if (init == void_zero_node)
+ /* This representation indicates an empty initializer,
+ e.g.: "new int()". */
+ ;
+ else
+ dump_expr (init, flags);
print_right_paren (scratch_buffer);
}
}
@@ -1860,7 +1861,7 @@ dump_expr (t, flags)
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
{
- tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
if (integer_zerop (idx))
{
@@ -1898,9 +1899,19 @@ dump_expr (t, flags)
}
}
}
- output_add_character (scratch_buffer, '{');
- dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
- output_add_character (scratch_buffer, '}');
+ /* We've gotten an rvalue of the form 'T()'. */
+ else if (TREE_TYPE (t))
+ {
+ dump_type (TREE_TYPE (t), flags);
+ print_left_paren (scratch_buffer);
+ print_right_paren (scratch_buffer);
+ }
+ else
+ {
+ output_add_character (scratch_buffer, '{');
+ dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
+ output_add_character (scratch_buffer, '}');
+ }
break;
case OFFSET_REF:
@@ -1913,7 +1924,8 @@ dump_expr (t, flags)
/* A::f */
dump_expr (t, flags | TFF_EXPR_IN_PARENS);
else if (BASELINK_P (t))
- dump_expr (OVL_CURRENT (TREE_VALUE (t)), flags | TFF_EXPR_IN_PARENS);
+ dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
+ flags | TFF_EXPR_IN_PARENS);
else
dump_decl (t, flags);
}
@@ -2056,6 +2068,10 @@ dump_expr (t, flags)
output_add_string (scratch_buffer, ") break; ");
break;
+ case BASELINK:
+ print_tree_identifier (scratch_buffer, DECL_NAME (get_first_fn (t)));
+ break;
+
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -2159,7 +2175,7 @@ context_as_string (context, flags)
return output_finalize_message (scratch_buffer);
}
-/* Generate the three forms of printable names for lang_printable_name. */
+/* Generate the three forms of printable names for cxx_printable_name. */
const char *
lang_decl_name (decl, v)
@@ -2238,7 +2254,7 @@ decl_to_string (decl, verbose)
|| TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
flags = TFF_CLASS_KEY_OR_ENUM;
if (verbose)
- flags |= TFF_DECL_SPECIFIERS | TFF_FUNCTION_DEFAULT_ARGUMENTS;
+ flags |= TFF_DECL_SPECIFIERS;
else if (TREE_CODE (decl) == FUNCTION_DECL)
flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
flags |= TFF_TEMPLATE_HEADER;
@@ -2405,70 +2421,63 @@ cv_to_string (p, v)
return output_finalize_message (scratch_buffer);
}
-static void
-lang_print_error_function (context, file)
+/* Langhook for print_error_function. */
+void
+cxx_print_error_function (context, file)
diagnostic_context *context;
const char *file;
{
- output_state os;
-
- default_print_error_function (context, file);
- os = output_buffer_state (context);
- output_set_prefix ((output_buffer *)context, file);
- maybe_print_instantiation_context ((output_buffer *)context);
- output_buffer_state (context) = os;
+ lhd_print_error_function (context, file);
+ output_set_prefix (&context->buffer, file);
+ maybe_print_instantiation_context (context);
}
static void
-cp_diagnostic_starter (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc;
+cp_diagnostic_starter (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- report_problematic_module (buffer);
- cp_print_error_function (buffer, dc);
- maybe_print_instantiation_context (buffer);
- output_set_prefix (buffer,
- context_as_prefix (diagnostic_file_location (dc),
- diagnostic_line_location (dc),
- diagnostic_is_warning (dc)));
+ diagnostic_report_current_module (context);
+ cp_print_error_function (context, diagnostic);
+ maybe_print_instantiation_context (context);
+ output_set_prefix (&context->buffer, diagnostic_build_prefix (diagnostic));
}
static void
-cp_diagnostic_finalizer (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc __attribute__ ((__unused__));
+cp_diagnostic_finalizer (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic __attribute__((unused));
{
- output_destroy_prefix (buffer);
+ output_destroy_prefix (&context->buffer);
}
/* Print current function onto BUFFER, in the process of reporting
a diagnostic message. Called from cp_diagnostic_starter. */
static void
-cp_print_error_function (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc;
+cp_print_error_function (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- if (error_function_changed ())
+ if (diagnostic_last_function_changed (context))
{
- char *prefix = diagnostic_file_location (dc)
- ? file_name_as_prefix (diagnostic_file_location (dc))
+ const char *old_prefix = output_prefix (&context->buffer);
+ char *new_prefix = diagnostic->location.file
+ ? file_name_as_prefix (diagnostic->location.file)
: NULL;
- output_state os;
- os = output_buffer_state (buffer);
- output_set_prefix (buffer, prefix);
+ output_set_prefix (&context->buffer, new_prefix);
if (current_function_decl == NULL)
- output_add_string (buffer, "At global scope:");
+ output_add_string (&context->buffer, "At global scope:");
else
- output_printf
- (buffer, "In %s `%s':", function_category (current_function_decl),
- (*decl_printable_name) (current_function_decl, 2));
- output_add_newline (buffer);
-
- record_last_error_function ();
- output_destroy_prefix (buffer);
- output_buffer_state (buffer) = os;
+ output_printf (&context->buffer, "In %s `%s':",
+ function_category (current_function_decl),
+ cxx_printable_name (current_function_decl, 2));
+ output_add_newline (&context->buffer);
+
+ diagnostic_set_last_function (context);
+ output_destroy_prefix (&context->buffer);
+ context->buffer.state.prefix = old_prefix;
}
}
@@ -2497,8 +2506,8 @@ function_category (fn)
/* Report the full context of a current template instantiation,
onto BUFFER. */
static void
-print_instantiation_full_context (buffer)
- output_buffer *buffer;
+print_instantiation_full_context (context)
+ diagnostic_context *context;
{
tree p = current_instantiation ();
int line = lineno;
@@ -2517,7 +2526,8 @@ print_instantiation_full_context (buffer)
if (current_function_decl == TINST_DECL (p))
/* Avoid redundancy with the the "In function" line. */;
else
- output_verbatim (buffer, "%s: In instantiation of `%s':\n", file,
+ output_verbatim (&context->buffer,
+ "%s: In instantiation of `%s':\n", file,
decl_as_string (TINST_DECL (p),
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
@@ -2527,13 +2537,13 @@ print_instantiation_full_context (buffer)
}
}
- print_instantiation_partial_context (buffer, p, file, line);
+ print_instantiation_partial_context (context, p, file, line);
}
/* Same as above but less verbose. */
static void
-print_instantiation_partial_context (buffer, t, file, line)
- output_buffer *buffer;
+print_instantiation_partial_context (context, t, file, line)
+ diagnostic_context *context;
tree t;
const char *file;
int line;
@@ -2541,24 +2551,24 @@ print_instantiation_partial_context (buffer, t, file, line)
for (; t; t = TREE_CHAIN (t))
{
output_verbatim
- (buffer, "%s:%d: instantiated from `%s'\n", file, line,
+ (&context->buffer, "%s:%d: instantiated from `%s'\n", file, line,
decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
line = TINST_LINE (t);
file = TINST_FILE (t);
}
- output_verbatim (buffer, "%s:%d: instantiated from here\n", file, line);
+ output_verbatim (&context->buffer, "%s:%d: instantiated from here\n", file, line);
}
/* Called from cp_thing to print the template context for an error. */
static void
-maybe_print_instantiation_context (buffer)
- output_buffer *buffer;
+maybe_print_instantiation_context (context)
+ diagnostic_context *context;
{
if (!problematic_instantiation_changed () || current_instantiation () == 0)
return;
record_last_problematic_instantiation ();
- print_instantiation_full_context (buffer);
+ print_instantiation_full_context (context);
}
/* Report the bare minimum context of a template instantiation. */
@@ -2566,8 +2576,8 @@ void
print_instantiation_context ()
{
print_instantiation_partial_context
- (diagnostic_buffer, current_instantiation (), input_filename, lineno);
- flush_diagnostic_buffer ();
+ (global_dc, current_instantiation (), input_filename, lineno);
+ diagnostic_flush_buffer (global_dc);
}
/* Called from output_format -- during diagnostic message processing --
@@ -2583,26 +2593,27 @@ print_instantiation_context ()
%Q assignment operator.
%T type.
%V cv-qualifier. */
-static int
-cp_printer (buffer)
+static bool
+cp_printer (buffer, text)
output_buffer *buffer;
+ text_info *text;
{
int verbose = 0;
const char *result;
-#define next_tree va_arg (output_buffer_format_args (buffer), tree)
-#define next_tcode va_arg (output_buffer_format_args (buffer), enum tree_code)
-#define next_lang va_arg (output_buffer_format_args (buffer), enum languages)
-#define next_int va_arg (output_buffer_format_args (buffer), int)
-
- if (*output_buffer_text_cursor (buffer) == '+')
- ++output_buffer_text_cursor (buffer);
- if (*output_buffer_text_cursor (buffer) == '#')
+#define next_tree va_arg (*text->args_ptr, tree)
+#define next_tcode va_arg (*text->args_ptr, enum tree_code)
+#define next_lang va_arg (*text->args_ptr, enum languages)
+#define next_int va_arg (*text->args_ptr, int)
+
+ if (*text->format_spec == '+')
+ ++text->format_spec;
+ if (*text->format_spec == '#')
{
verbose = 1;
- ++output_buffer_text_cursor (buffer);
+ ++text->format_spec;
}
- switch (*output_buffer_text_cursor (buffer))
+ switch (*text->format_spec)
{
case 'A': result = args_to_string (next_tree, verbose); break;
case 'C': result = code_to_string (next_tcode, verbose); break;
@@ -2617,11 +2628,11 @@ cp_printer (buffer)
case 'V': result = cv_to_string (next_tree, verbose); break;
default:
- return 0;
+ return false;
}
output_add_string (buffer, result);
- return 1;
+ return true;
#undef next_tree
#undef next_tcode
#undef next_lang
@@ -2715,7 +2726,7 @@ void
cp_error_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2725,10 +2736,9 @@ cp_error_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here), /* warning = */ 0);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here), DK_ERROR);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
@@ -2736,7 +2746,7 @@ void
cp_warning_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2746,10 +2756,9 @@ cp_warning_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here), /* warning = */ 1);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here), DK_WARNING);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
@@ -2757,7 +2766,7 @@ void
cp_pedwarn_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2767,10 +2776,9 @@ cp_pedwarn_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here),
- /* warning = */ !flag_pedantic_errors);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here),
+ pedantic_error_kind());
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index 5de9f4c..747cc1a 100644
--- a/contrib/gcc/cp/except.c
+++ b/contrib/gcc/cp/except.c
@@ -31,10 +31,10 @@ Boston, MA 02111-1307, USA. */
#include "libfuncs.h"
#include "cp-tree.h"
#include "flags.h"
-#include "obstack.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "tree-inline.h"
static void push_eh_cleanup PARAMS ((tree));
static tree prepare_eh_type PARAMS ((tree));
@@ -46,15 +46,14 @@ static void push_eh_cleanup PARAMS ((tree));
static bool decl_is_java_type PARAMS ((tree decl, int err));
static void initialize_handler_parm PARAMS ((tree, tree));
static tree do_allocate_exception PARAMS ((tree));
+static tree stabilize_throw_expr PARAMS ((tree, tree *));
+static tree wrap_cleanups_r PARAMS ((tree *, int *, void *));
static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
static bool is_admissible_throw_operand PARAMS ((tree));
static int can_convert_eh PARAMS ((tree, tree));
static void check_handlers_1 PARAMS ((tree, tree));
static tree cp_protect_cleanup_actions PARAMS ((void));
-#include "decl.h"
-#include "obstack.h"
-
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@@ -118,7 +117,7 @@ prepare_eh_type (type)
}
/* Build the address of a typeinfo decl for use in the runtime
- matching field of the exception model. */
+ matching field of the exception model. */
static tree
build_eh_type_type (type)
@@ -175,17 +174,13 @@ static int
dtor_nothrow (type)
tree type;
{
- tree fn;
-
if (type == NULL_TREE)
return 0;
if (! TYPE_HAS_DESTRUCTOR (type))
return 1;
- fn = lookup_member (type, dtor_identifier, 0, 0);
- fn = TREE_VALUE (fn);
- return TREE_NOTHROW (fn);
+ return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
/* Build up a call to __cxa_end_catch, to destroy the exception object
@@ -518,7 +513,7 @@ do_allocate_exception (type)
#if 0
/* Call __cxa_free_exception from a cleanup. This is never invoked
- directly. */
+ directly, but see the comment for stabilize_throw_expr. */
static tree
do_free_exception (ptr)
@@ -540,6 +535,92 @@ do_free_exception (ptr)
}
#endif
+/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
+ Called from build_throw via walk_tree_without_duplicates. */
+
+static tree
+wrap_cleanups_r (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *data ATTRIBUTE_UNUSED;
+{
+ tree exp = *tp;
+ tree cleanup;
+
+ /* Don't walk into types. */
+ if (TYPE_P (exp))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ if (TREE_CODE (exp) != TARGET_EXPR)
+ return NULL_TREE;
+
+ cleanup = TARGET_EXPR_CLEANUP (exp);
+ if (cleanup)
+ {
+ cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup);
+ TARGET_EXPR_CLEANUP (exp) = cleanup;
+ }
+
+ /* Keep iterating. */
+ return NULL_TREE;
+}
+
+/* Like stabilize_expr, but specifically for a thrown expression. When
+ throwing a temporary class object, we want to construct it directly into
+ the thrown exception, so we look past the TARGET_EXPR and stabilize the
+ arguments of the call instead.
+
+ The case where EXP is a call to a function returning a class is a bit of
+ a grey area in the standard; it's unclear whether or not it should be
+ allowed to throw. I'm going to say no, as that allows us to optimize
+ this case without worrying about deallocating the exception object if it
+ does. The alternatives would be either not optimizing this case, or
+ wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception
+ rather than in a MUST_NOT_THROW_EXPR, for this case only. */
+
+static tree
+stabilize_throw_expr (exp, initp)
+ tree exp;
+ tree *initp;
+{
+ tree init_expr;
+
+ if (TREE_CODE (exp) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR
+ && flag_elide_constructors)
+ {
+ tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp));
+ tree args = TREE_OPERAND (aggr_init, 1);
+ tree newargs = NULL_TREE;
+ tree *p = &newargs;
+
+ init_expr = void_zero_node;
+ for (; args; args = TREE_CHAIN (args))
+ {
+ tree arg = TREE_VALUE (args);
+ tree arg_init_expr;
+
+ arg = stabilize_expr (arg, &arg_init_expr);
+
+ if (TREE_SIDE_EFFECTS (arg_init_expr))
+ init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
+ arg_init_expr);
+ *p = tree_cons (NULL_TREE, arg, NULL_TREE);
+ p = &TREE_CHAIN (*p);
+ }
+ TREE_OPERAND (aggr_init, 1) = newargs;
+ }
+ else
+ {
+ exp = stabilize_expr (exp, &init_expr);
+ }
+
+ *initp = init_expr;
+ return exp;
+}
+
/* Build a throw expression. */
tree
@@ -585,10 +666,9 @@ build_throw (exp)
{
tree throw_type;
tree cleanup;
- tree stmt_expr;
- tree compound_stmt;
tree object, ptr;
tree tmp;
+ tree temp_expr, allocate_expr;
fn = get_identifier ("__cxa_throw");
if (IDENTIFIER_GLOBAL_VALUE (fn))
@@ -614,8 +694,6 @@ build_throw (exp)
fn = push_throw_library_fn (fn, tmp);
}
- begin_init_stmts (&stmt_expr, &compound_stmt);
-
/* throw expression */
/* First, decay it. */
exp = decay_conversion (exp);
@@ -633,37 +711,40 @@ build_throw (exp)
the call to __cxa_allocate_exception first (which doesn't
matter, since it can't throw). */
- my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
-
- /* Store the throw expression into a temp. This can be less
- efficient than storing it into the allocated space directly, but
- if we allocated the space first we would have to deal with
- cleaning it up if evaluating this expression throws. */
- if (TREE_SIDE_EFFECTS (exp))
- {
- tmp = create_temporary_var (TREE_TYPE (exp));
- DECL_INITIAL (tmp) = exp;
- cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
- exp = tmp;
- }
+ /* Pre-evaluate the thrown expression first, since if we allocated
+ the space first we would have to deal with cleaning it up if
+ evaluating this expression throws. */
+ exp = stabilize_throw_expr (exp, &temp_expr);
/* Allocate the space for the exception. */
- ptr = create_temporary_var (ptr_type_node);
- DECL_REGISTER (ptr) = 1;
- cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
- tmp = do_allocate_exception (TREE_TYPE (exp));
- tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
- finish_expr_stmt (tmp);
-
+ allocate_expr = do_allocate_exception (TREE_TYPE (exp));
+ allocate_expr = get_target_expr (allocate_expr);
+ ptr = TARGET_EXPR_SLOT (allocate_expr);
object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
object = build_indirect_ref (object, NULL);
- exp = build_modify_expr (object, INIT_EXPR, exp);
+ /* And initialize the exception object. */
+ exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
if (exp == error_mark_node)
- error (" in thrown expression");
+ {
+ error (" in thrown expression");
+ return error_mark_node;
+ }
exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
- finish_expr_stmt (exp);
+ /* Prepend the allocation. */
+ exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
+ if (temp_expr != void_zero_node)
+ {
+ /* Prepend the calculation of the throw expression. Also, force
+ any cleanups from the expression to be evaluated here so that
+ we don't have to do them during unwinding. But first wrap
+ them in MUST_NOT_THROW_EXPR, since they are run after the
+ exception object is initialized. */
+ walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
+ exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ }
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
@@ -671,9 +752,9 @@ build_throw (exp)
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
- cleanup = TREE_VALUE (cleanup);
+ cleanup = BASELINK_FUNCTIONS (cleanup);
mark_used (cleanup);
- mark_addressable (cleanup);
+ cxx_mark_addressable (cleanup);
/* Pretend it's a normal function. */
cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
}
@@ -686,13 +767,11 @@ build_throw (exp)
tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
tmp = tree_cons (NULL_TREE, throw_type, tmp);
tmp = tree_cons (NULL_TREE, ptr, tmp);
- tmp = build_function_call (fn, tmp);
-
/* ??? Indicate that this function call throws throw_type. */
+ tmp = build_function_call (fn, tmp);
- finish_expr_stmt (tmp);
-
- exp = finish_init_stmts (stmt_expr, compound_stmt);
+ /* Tack on the initialization stuff. */
+ exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
}
else
{
@@ -708,6 +787,8 @@ build_throw (exp)
(fn, build_function_type (void_type_node, void_list_node));
}
+ /* ??? Indicate that this function call allows exceptions of the type
+ of the enclosing catch block (if known). */
exp = build_function_call (fn, NULL_TREE);
}
@@ -718,7 +799,7 @@ build_throw (exp)
/* Make sure TYPE is complete, pointer to complete, reference to
complete, or pointer to cv void. Issue diagnostic on failure.
- Return the zero on failure and non-zero on success. FROM can be
+ Return the zero on failure and nonzero on success. FROM can be
the expr or decl from whence TYPE came, if available. */
static int
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c
index 34f779e..cc9dae9 100644
--- a/contrib/gcc/cp/expr.c
+++ b/contrib/gcc/cp/expr.c
@@ -32,9 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "tm_p.h"
-static rtx cplus_expand_expr PARAMS ((tree, rtx, enum machine_mode,
- enum expand_modifier));
-
/* Hook used by output_constant to expand language-specific
constants. */
@@ -79,12 +76,12 @@ cplus_expand_constant (cst)
/* Hook used by expand_expr to expand language-specific tree codes. */
-static rtx
-cplus_expand_expr (exp, target, tmode, modifier)
+rtx
+cxx_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
enum machine_mode tmode;
- enum expand_modifier modifier;
+ int modifier; /* Actually an enum expand_modifier. */
{
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
@@ -105,13 +102,13 @@ cplus_expand_expr (exp, target, tmode, modifier)
target, tmode, modifier);
case OFFSET_REF:
- /* Offset refs should not make it through to here. */
+ /* Offset refs should not make it through to here. */
abort ();
return const0_rtx;
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
- return NULL;
+ return const0_rtx;
case MUST_NOT_THROW_EXPR:
expand_eh_region_start ();
@@ -130,17 +127,3 @@ cplus_expand_expr (exp, target, tmode, modifier)
/* NOTREACHED */
return NULL;
}
-
-void
-init_cplus_expand ()
-{
- lang_expand_expr = cplus_expand_expr;
-}
-
-int
-extract_init (decl, init)
- tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
-{
- return 0;
-}
-
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c
index 441be67..9280a09 100644
--- a/contrib/gcc/cp/friend.c
+++ b/contrib/gcc/cp/friend.c
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* Friend data structures are described in cp-tree.h. */
-/* Returns non-zero if SUPPLICANT is a friend of TYPE. */
+/* Returns nonzero if SUPPLICANT is a friend of TYPE. */
int
is_friend (type, supplicant)
@@ -64,6 +64,10 @@ is_friend (type, supplicant)
if (supplicant == TREE_VALUE (friends))
return 1;
+ /* We haven't completed the instantiation yet. */
+ if (TREE_CODE (supplicant) == TEMPLATE_DECL)
+ return 1;
+
/* Temporarily, we are more lenient to deal with
nested friend functions, for which there can be
more than one FUNCTION_DECL, despite being the
@@ -114,7 +118,7 @@ is_friend (type, supplicant)
else
context = NULL_TREE;
- /* A namespace is not friend to anybody. */
+ /* A namespace is not friend to anybody. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
@@ -159,6 +163,9 @@ add_friend (type, decl)
return;
}
}
+
+ maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
TREE_VALUE (list) = tree_cons (error_mark_node, decl,
TREE_VALUE (list));
return;
@@ -166,6 +173,8 @@ add_friend (type, decl)
list = TREE_CHAIN (list);
}
+ maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
DECL_FRIENDLIST (typedecl));
@@ -198,24 +207,25 @@ make_friend_class (type, 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. */
- 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;
+ {
+ 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. */
+ error ("partial specialization `%T' declared `friend'",
+ friend_type);
+ return;
+ }
+
+ is_template_friend = 1;
+ }
else if (same_type_p (type, friend_type))
{
pedwarn ("class `%T' is implicitly friends with itself",
@@ -230,7 +240,7 @@ make_friend_class (type, friend_type)
A friend of a class or class template can be a function or
class template, a specialization of a function template or
class template, or an ordinary (nontemplate) function or
- class. */
+ class. */
if (!is_template_friend)
;/* ok */
else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
@@ -267,6 +277,8 @@ make_friend_class (type, friend_type)
TREE_VALUE (classes), type);
else
{
+ maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
+
CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
if (is_template_friend)
@@ -396,14 +408,14 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
/* This must be a local class, so pushdecl will be ok, and
insert an unqualified friend into the local scope
(rather than the containing namespace scope, which the
- next choice will do). */
+ next choice will do). */
decl = pushdecl (decl);
else
{
/* We can't use pushdecl, as we might be in a template
class specialization, and pushdecl will insert an
unqualified friend decl into the template parameter
- scope, rather than the namespace containing it. */
+ scope, rather than the namespace containing it. */
tree ns = decl_namespace_context (decl);
push_nested_namespace (ns);
diff --git a/contrib/gcc/cp/g++spec.c b/contrib/gcc/cp/g++spec.c
index c0e5c73..af30f1c 100644
--- a/contrib/gcc/cp/g++spec.c
+++ b/contrib/gcc/cp/g++spec.c
@@ -51,10 +51,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
{
int i, j;
- /* If non-zero, the user gave us the `-p' or `-pg' flag. */
+ /* If nonzero, the user gave us the `-p' or `-pg' flag. */
int saw_profile_flag = 0;
- /* If non-zero, the user gave us the `-v' flag. */
+ /* If nonzero, the user gave us the `-v' flag. */
int saw_verbose_flag = 0;
/* This will be 0 if we encounter a situation where we should not
@@ -73,7 +73,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* The new argument list will be contained in this. */
const char **arglist;
- /* Non-zero if we saw a `-xfoo' language specification on the
+ /* Nonzero if we saw a `-xfoo' language specification on the
command line. Used to avoid adding our own -xc++ if the user
already gave a language for the file. */
int saw_speclang = 0;
@@ -178,6 +178,8 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
else if (strcmp (argv[i], "-static-libgcc") == 0
|| strcmp (argv[i], "-static") == 0)
shared_libgcc = 0;
+ else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
+ i++;
else
/* Pass other options through. */
continue;
@@ -272,6 +274,13 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
{
arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
added_libraries++;
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+# ifndef LIBUNWIND
+# define LIBUNWIND "-lunwind"
+# endif
+ arglist[j++] = LIBUNWIND;
+ added_libraries++;
+#endif
}
if (saw_math)
arglist[j++] = saw_math;
@@ -292,11 +301,17 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
*in_added_libraries = added_libraries;
}
-/* Called before linking. Returns 0 on success and -1 on failure. */
-int lang_specific_pre_link () /* Not used for C++. */
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link () /* Not used for C++. */
{
return 0;
}
-/* Number of extra output files that lang_specific_pre_link may generate. */
-int lang_specific_extra_outfiles = 0; /* Not used for C++. */
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for C++. */
+
+/* Table of language-specific spec functions. */
+const struct spec_function lang_specific_spec_functions[] =
+{
+ { 0, 0 }
+};
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 1e08908..279e3b1 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -1,6 +1,6 @@
/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -34,48 +34,26 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
-static void expand_aggr_vbase_init_1 PARAMS ((tree, tree, tree, tree));
-static void construct_virtual_bases PARAMS ((tree, tree, tree, tree, tree));
+static void construct_virtual_base (tree, tree);
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind, int));
-static void perform_member_init PARAMS ((tree, tree, int));
-static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
+static void perform_member_init (tree, tree);
static tree build_builtin_delete_call PARAMS ((tree));
static int member_init_ok_or_else PARAMS ((tree, tree, tree));
static void expand_virtual_init PARAMS ((tree, tree));
-static tree sort_member_init PARAMS ((tree, tree));
+static tree sort_mem_initializers (tree, tree);
static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
-static tree build_default_init PARAMS ((tree));
+static tree build_default_init PARAMS ((tree, tree));
static tree build_new_1 PARAMS ((tree));
static tree get_cookie_size PARAMS ((tree));
static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
static tree build_field_list PARAMS ((tree, tree, int *));
static tree build_vtbl_address PARAMS ((tree));
-/* Set up local variable for this file. MUST BE CALLED AFTER
- INIT_DECL_PROCESSING. */
-
-static tree BI_header_type;
-
-void init_init_processing ()
-{
- tree fields[1];
-
- /* Define the structure that holds header information for
- arrays allocated via operator new. */
- BI_header_type = make_aggr_type (RECORD_TYPE);
- fields[0] = build_decl (FIELD_DECL, nelts_identifier, sizetype);
-
- finish_builtin_type (BI_header_type, "__new_cookie", fields,
- 0, double_type_node);
-
- ggc_add_tree_root (&BI_header_type, 1);
-}
-
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
to include conditionals, loops, and other such statement-level
@@ -167,7 +145,7 @@ initialize_vtbl_ptrs (addr)
list = build_tree_list (type, addr);
/* Walk through the hierarchy, initializing the vptr in each base
- class. We do these in pre-order because can't find the virtual
+ class. We do these in pre-order because we can't find the virtual
bases for a class until we've initialized the vtbl for that
class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
@@ -176,86 +154,194 @@ initialize_vtbl_ptrs (addr)
dfs_marked_real_bases_queue_p, type);
}
-/* Types containing pointers to data members cannot be
- zero-initialized with zeros, because the NULL value for such
- pointers is -1.
-
- TYPE is a type that requires such zero initialization. The
- returned value is the initializer. */
+/* Return an expression for the zero-initialization of an object with
+ type T. This expression will either be a constant (in the case
+ that T is a scalar), or a CONSTRUCTOR (in the case that T is an
+ aggregate). In either case, the value can be used as DECL_INITIAL
+ for a decl of the indicated TYPE; it is a valid static initializer.
+ If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS is the
+ number of elements in the array. If STATIC_STORAGE_P is TRUE,
+ initializers are only generated for entities for which
+ zero-initialization does not simply mean filling the storage with
+ zero bytes. */
tree
-build_forced_zero_init (type)
- tree type;
+build_zero_init (tree type, tree nelts, bool static_storage_p)
{
- tree init = NULL;
+ tree init = NULL_TREE;
+
+ /* [dcl.init]
+
+ To zero-initialization storage for an object of type T means:
+
+ -- if T is a scalar type, the storage is set to the value of zero
+ converted to T.
+
+ -- if T is a non-union class type, the storage for each nonstatic
+ data member and each base-class subobject is zero-initialized.
+
+ -- if T is a union type, the storage for its first data member is
+ zero-initialized.
+
+ -- if T is an array type, the storage for each element is
+ zero-initialized.
- if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
+ -- if T is a reference type, no initialization is performed. */
+
+ my_friendly_assert (nelts == NULL_TREE || TREE_CODE (nelts) == INTEGER_CST,
+ 20030618);
+
+ if (type == error_mark_node)
+ ;
+ else if (static_storage_p && zero_init_p (type))
+ /* In order to save space, we do not explicitly build initializers
+ for items that do not need them. GCC's semantics are that
+ items with static storage duration that are not otherwise
+ initialized are initialized to zero. */
+ ;
+ else if (SCALAR_TYPE_P (type))
+ init = convert (type, integer_zero_node);
+ else if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the fields, building initializations. */
+ inits = NULL_TREE;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ /* Note that for class types there will be FIELD_DECLs
+ corresponding to base classes as well. Thus, iterating
+ over TYPE_FIELDs will result in correct initialization of
+ all of the subobjects. */
+ if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
+ inits = tree_cons (field,
+ build_zero_init (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
+ static_storage_p),
+ inits);
+
+ /* For unions, only the first field is initialized. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ }
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* This is a default initialization of an aggregate, but not one of
- non-POD class type. We cleverly notice that the initialization
- rules in such a case are the same as for initialization with an
- empty brace-initialization list. */
- init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ tree index;
+ tree max_index;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the array elements, building initializations. */
+ inits = NULL_TREE;
+ max_index = nelts ? nelts : array_type_nelts (type);
+ my_friendly_assert (TREE_CODE (max_index) == INTEGER_CST, 20030618);
+
+ for (index = size_zero_node;
+ !tree_int_cst_lt (max_index, index);
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ inits = tree_cons (index,
+ build_zero_init (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
+ static_storage_p),
+ inits);
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
- /* --if T is a reference type, no initialization is performed. */
- return NULL_TREE;
+ ;
else
- {
- init = integer_zero_node;
-
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- /* We must make enumeral types the right type. */
- init = fold (build1 (NOP_EXPR, type, init));
- }
+ abort ();
- init = digest_init (type, init, 0);
+ /* In all cases, the initializer is a constant. */
+ if (init)
+ TREE_CONSTANT (init) = 1;
return init;
}
-/* [dcl.init]:
+/* Build an expression for the default-initialization of an object of
+ the indicated TYPE. If NELTS is non-NULL, and TYPE is an
+ ARRAY_TYPE, NELTS is the number of elements in the array. If
+ initialization of TYPE requires calling constructors, this function
+ returns NULL_TREE; the caller is responsible for arranging for the
+ constructors to be called. */
- To default-initialize an object of type T means:
+static tree
+build_default_init (type, nelts)
+ tree type;
+ tree nelts;
+{
+ /* [dcl.init]:
- --if T is a non-POD class type (clause _class_), the default construc-
- tor for T is called (and the initialization is ill-formed if T has
- no accessible default constructor);
+ To default-initialize an object of type T means:
- --if T is an array type, each element is default-initialized;
+ --if T is a non-POD class type (clause _class_), the default construc-
+ tor for T is called (and the initialization is ill-formed if T has
+ no accessible default constructor);
- --otherwise, the storage for the object is zero-initialized.
+ --if T is an array type, each element is default-initialized;
- A program that calls for default-initialization of an entity of refer-
- ence type is ill-formed. */
+ --otherwise, the storage for the object is zero-initialized.
-static tree
-build_default_init (type)
- tree type;
-{
- tree init = NULL_TREE;
+ A program that calls for default-initialization of an entity of refer-
+ ence type is ill-formed. */
- if (TYPE_NEEDS_CONSTRUCTING (type))
- /* Other code will handle running the default constructor. We can't do
- anything with a CONSTRUCTOR for arrays here, as that would imply
- copy-initialization. */
- return NULL_TREE;
+ /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
+ performing the initialization. This is confusing in that some
+ non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example,
+ a class with a pointer-to-data member as a non-static data member
+ does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up
+ passing non-PODs to build_zero_init below, which is contrary to
+ the semantics quoted above from [dcl.init].
- return build_forced_zero_init (type);
+ It happens, however, that the behavior of the constructor the
+ standard says we should have generated would be precisely the
+ same as that obtained by calling build_zero_init below, so things
+ work out OK. */
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ || (nelts && TREE_CODE (nelts) != INTEGER_CST))
+ return NULL_TREE;
+
+ /* At this point, TYPE is either a POD class type, an array of POD
+ classes, or something even more inoccuous. */
+ return build_zero_init (type, nelts, /*static_storage_p=*/false);
}
-/* Subroutine of emit_base_init. */
+/* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
+ arguments. If TREE_LIST is void_type_node, an empty initializer
+ list was given; if NULL_TREE no initializer was given. */
static void
-perform_member_init (member, init, explicit)
- tree member, init;
- int explicit;
+perform_member_init (tree member, tree init)
{
tree decl;
tree type = TREE_TYPE (member);
+ bool explicit;
+
+ explicit = (init != NULL_TREE);
- decl = build_component_ref (current_class_ref, member, NULL_TREE, explicit);
+ /* Effective C++ rule 12 requires that all data members be
+ initialized. */
+ if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE)
+ warning ("`%D' should be initialized in the member initialization "
+ "list",
+ member);
+ if (init == void_type_node)
+ init = NULL_TREE;
+
+ /* Get an lvalue for the data member. */
+ decl = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/true);
if (decl == error_mark_node)
return;
@@ -273,11 +359,6 @@ perform_member_init (member, init, explicit)
else if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
{
- /* Since `init' is already a TREE_LIST on the member_init_list,
- only build it into one if we aren't already a list. */
- if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
- init = build_tree_list (NULL_TREE, init);
-
if (explicit
&& TREE_CODE (type) == ARRAY_TYPE
&& init != NULL_TREE
@@ -285,7 +366,8 @@ perform_member_init (member, init, explicit)
&& TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
{
/* Initialization of one array from another. */
- finish_expr_stmt (build_vec_init (decl, TREE_VALUE (init), 1));
+ finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
+ /* from_array=*/1));
}
else
finish_expr_stmt (build_aggr_init (decl, init, 0));
@@ -296,7 +378,7 @@ perform_member_init (member, init, explicit)
{
if (explicit)
{
- init = build_default_init (type);
+ init = build_default_init (type, /*nelts=*/NULL_TREE);
if (TREE_CODE (type) == REFERENCE_TYPE)
warning
("default-initialization of `%#D', which has reference type",
@@ -327,13 +409,14 @@ perform_member_init (member, init, explicit)
{
tree expr;
- expr = build_component_ref (current_class_ref, member, NULL_TREE,
- explicit);
+ expr = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
expr = build_delete (type, expr, sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
- finish_subobject (expr);
+ finish_eh_cleanup (expr);
}
}
@@ -357,7 +440,7 @@ build_field_list (t, list, uses_unions_p)
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
/* Keep track of whether or not any fields are unions. */
@@ -384,79 +467,107 @@ build_field_list (t, list, uses_unions_p)
return list;
}
-/* The MEMBER_INIT_LIST is a TREE_LIST. The TREE_PURPOSE of each list
- gives a FIELD_DECL in T that needs initialization. The TREE_VALUE
- gives the initializer, or list of initializer arguments. Sort the
- MEMBER_INIT_LIST, returning a version that contains the same
- information but in the order that the fields should actually be
- initialized. Perform error-checking in the process. */
+/* The MEM_INITS are a TREE_LIST. The TREE_PURPOSE of each list gives
+ a FIELD_DECL or BINFO in T that needs initialization. The
+ TREE_VALUE gives the initializer, or list of initializer arguments.
+
+ Return a TREE_LIST containing all of the initializations required
+ for T, in the order in which they should be performed. The output
+ list has the same format as the input. */
static tree
-sort_member_init (t, member_init_list)
- tree t;
- tree member_init_list;
+sort_mem_initializers (tree t, tree mem_inits)
{
- tree init_list;
- tree last_field;
tree init;
+ tree base;
+ tree sorted_inits;
+ tree next_subobject;
+ int i;
int uses_unions_p;
- /* Build up a list of the various fields, in sorted order. */
- init_list = nreverse (build_field_list (t, NULL_TREE, &uses_unions_p));
-
- /* Go through the explicit initializers, adding them to the
- INIT_LIST. */
- last_field = init_list;
- for (init = member_init_list; init; init = TREE_CHAIN (init))
- {
- tree f;
- tree initialized_field;
-
- initialized_field = TREE_PURPOSE (init);
- my_friendly_assert (TREE_CODE (initialized_field) == FIELD_DECL,
- 20000516);
-
- /* If the explicit initializers are in sorted order, then the
- INITIALIZED_FIELD will be for a field following the
- LAST_FIELD. */
- for (f = last_field; f; f = TREE_CHAIN (f))
- if (TREE_PURPOSE (f) == initialized_field)
+ /* Build up a list of initializations. The TREE_PURPOSE of entry
+ will be the subobject (a FIELD_DECL or BINFO) to initialize. The
+ TREE_VALUE will be the constructor arguments, or NULL if no
+ explicit initialization was provided. */
+ sorted_inits = NULL_TREE;
+ /* Process the virtual bases. */
+ for (base = CLASSTYPE_VBASECLASSES (t); base; base = TREE_CHAIN (base))
+ sorted_inits = tree_cons (TREE_VALUE (base), NULL_TREE, sorted_inits);
+ /* Process the direct bases. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ {
+ base = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ if (!TREE_VIA_VIRTUAL (base))
+ sorted_inits = tree_cons (base, NULL_TREE, sorted_inits);
+ }
+ /* Process the non-static data members. */
+ sorted_inits = build_field_list (t, sorted_inits, &uses_unions_p);
+ /* Reverse the entire list of initializations, so that they are in
+ the order that they will actually be performed. */
+ sorted_inits = nreverse (sorted_inits);
+
+ /* If the user presented the initializers in an order different from
+ that in which they will actually occur, we issue a warning. Keep
+ track of the next subobject which can be explicitly initialized
+ without issuing a warning. */
+ next_subobject = sorted_inits;
+
+ /* Go through the explicit initializers, filling in TREE_PURPOSE in
+ the SORTED_INITS. */
+ for (init = mem_inits; init; init = TREE_CHAIN (init))
+ {
+ tree subobject;
+ tree subobject_init;
+
+ subobject = TREE_PURPOSE (init);
+
+ /* If the explicit initializers are in sorted order, then
+ SUBOBJECT will be NEXT_SUBOBJECT, or something following
+ it. */
+ for (subobject_init = next_subobject;
+ subobject_init;
+ subobject_init = TREE_CHAIN (subobject_init))
+ if (TREE_PURPOSE (subobject_init) == subobject)
break;
- /* Give a warning, if appropriate. */
- if (warn_reorder && !f)
+ /* Issue a warning if the explicit initializer order does not
+ match that which will actually occur. */
+ if (warn_reorder && !subobject_init)
{
- cp_warning_at ("member initializers for `%#D'",
- TREE_PURPOSE (last_field));
- cp_warning_at (" and `%#D'", initialized_field);
- warning (" will be re-ordered to match declaration order");
+ if (TREE_CODE (TREE_PURPOSE (next_subobject)) == FIELD_DECL)
+ cp_warning_at ("`%D' will be initialized after",
+ TREE_PURPOSE (next_subobject));
+ else
+ warning ("base `%T' will be initialized after",
+ TREE_PURPOSE (next_subobject));
+ if (TREE_CODE (subobject) == FIELD_DECL)
+ cp_warning_at (" `%#D'", subobject);
+ else
+ warning (" base `%T'", subobject);
}
- /* Look again, from the beginning of the list. We must find the
- field on this loop. */
- if (!f)
+ /* Look again, from the beginning of the list. */
+ if (!subobject_init)
{
- f = init_list;
- while (TREE_PURPOSE (f) != initialized_field)
- f = TREE_CHAIN (f);
+ subobject_init = sorted_inits;
+ while (TREE_PURPOSE (subobject_init) != subobject)
+ subobject_init = TREE_CHAIN (subobject_init);
}
-
- /* If there was already an explicit initializer for this field,
- issue an error. */
- if (TREE_TYPE (f))
- error ("multiple initializations given for member `%D'",
- initialized_field);
- else
+
+ /* It is invalid to initialize the same subobject more than
+ once. */
+ if (TREE_VALUE (subobject_init))
{
- /* Mark the field as explicitly initialized. */
- TREE_TYPE (f) = error_mark_node;
- /* And insert the initializer. */
- TREE_VALUE (f) = TREE_VALUE (init);
+ if (TREE_CODE (subobject) == FIELD_DECL)
+ error ("multiple initializations given for `%D'", subobject);
+ else
+ error ("multiple initializations given for base `%T'",
+ subobject);
}
- /* Remember the location of the last explicitly initialized
- field. */
- last_field = f;
+ /* Record the initialization. */
+ TREE_VALUE (subobject_init) = TREE_VALUE (init);
+ next_subobject = subobject_init;
}
/* [class.base.init]
@@ -466,15 +577,16 @@ sort_member_init (t, member_init_list)
anonymous unions), the ctor-initializer is ill-formed. */
if (uses_unions_p)
{
- last_field = NULL_TREE;
- for (init = init_list; init; init = TREE_CHAIN (init))
+ tree last_field = NULL_TREE;
+ for (init = sorted_inits; init; init = TREE_CHAIN (init))
{
tree field;
tree field_type;
int done;
- /* Skip uninitialized members. */
- if (!TREE_TYPE (init))
+ /* Skip uninitialized members and base classes. */
+ if (!TREE_VALUE (init)
+ || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL)
continue;
/* See if this field is a member of a union, or a member of a
structure contained in a union, etc. */
@@ -541,231 +653,76 @@ sort_member_init (t, member_init_list)
}
}
- return init_list;
+ return sorted_inits;
}
-/* Like sort_member_init, but used for initializers of base classes.
- *RBASE_PTR is filled in with the initializers for non-virtual bases;
- vbase_ptr gets the virtual bases. */
-
-static void
-sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
- tree t;
- tree base_init_list;
- tree *rbase_ptr, *vbase_ptr;
-{
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- int i;
- tree x;
- tree last;
-
- /* For warn_reorder. */
- int last_pos = 0;
- tree last_base = NULL_TREE;
-
- tree rbases = NULL_TREE;
- tree vbases = NULL_TREE;
-
- /* First walk through and splice out vbase and invalid initializers.
- Also replace types with binfos. */
-
- last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
- for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
- {
- tree basetype = TREE_PURPOSE (x);
- tree binfo = (TREE_CODE (basetype) == TREE_VEC
- ? basetype : binfo_or_else (basetype, t));
-
- if (binfo == NULL_TREE)
- /* BASETYPE might be an inaccessible direct base (because it
- is also an indirect base). */
- continue;
-
- if (TREE_VIA_VIRTUAL (binfo))
- {
- /* Virtual base classes are special cases. Their
- initializers are recorded with this constructor, and they
- are used when this constructor is the top-level
- constructor called. */
- tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
- vbases = tree_cons (v, TREE_VALUE (x), vbases);
- }
- else
- {
- /* Otherwise, it must be an immediate base class. */
- my_friendly_assert
- (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
- t), 20011113);
-
- TREE_PURPOSE (x) = binfo;
- TREE_CHAIN (last) = x;
- last = x;
- }
- }
- TREE_CHAIN (last) = NULL_TREE;
-
- /* Now walk through our regular bases and make sure they're initialized. */
-
- for (i = 0; i < n_baseclasses; ++i)
- {
- /* The base for which we're currently initializing. */
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- /* The initializer for BASE_BINFO. */
- tree init;
- int pos;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- /* We haven't found the BASE_BINFO yet. */
- init = NULL_TREE;
- /* Loop through all the explicitly initialized bases, looking
- for an appropriate initializer. */
- for (x = base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
- {
- tree binfo = TREE_PURPOSE (x);
-
- if (binfo == base_binfo && !init)
- {
- if (warn_reorder)
- {
- if (pos < last_pos)
- {
- cp_warning_at ("base initializers for `%#T'", last_base);
- cp_warning_at (" and `%#T'", BINFO_TYPE (binfo));
- warning (" will be re-ordered to match inheritance order");
- }
- last_pos = pos;
- last_base = BINFO_TYPE (binfo);
- }
-
- /* Make sure we won't try to work on this init again. */
- TREE_PURPOSE (x) = NULL_TREE;
- init = build_tree_list (binfo, TREE_VALUE (x));
- }
- else if (binfo == base_binfo)
- {
- error ("base class `%T' already initialized",
- BINFO_TYPE (binfo));
- break;
- }
- }
-
- /* If we didn't find BASE_BINFO in the list, create a dummy entry
- so the two lists (RBASES and the list of bases) will be
- symmetrical. */
- if (!init)
- init = build_tree_list (NULL_TREE, NULL_TREE);
- rbases = chainon (rbases, init);
- }
-
- *rbase_ptr = rbases;
- *vbase_ptr = vbases;
-}
-
-/* Perform whatever initializations have yet to be done on the base
- class, and non-static data members, of the CURRENT_CLASS_TYPE.
- These actions are given by the BASE_INIT_LIST and MEM_INIT_LIST,
- respectively.
-
- If there is a need for a call to a constructor, we must surround
- that call with a pushlevel/poplevel pair, since we are technically
- at the PARM level of scope. */
+/* Initialize all bases and members of CURRENT_CLASS_TYPE. MEM_INITS
+ is a TREE_LIST giving the explicit mem-initializer-list for the
+ constructor. The TREE_PURPOSE of each entry is a subobject (a
+ FIELD_DECL or a BINFO) of the CURRENT_CLASS_TYPE. The TREE_VALUE
+ is a TREE_LIST giving the arguments to the constructor or
+ void_type_node for an empty list of arguments. */
void
-emit_base_init (mem_init_list, base_init_list)
- tree mem_init_list;
- tree base_init_list;
+emit_mem_initializers (tree mem_inits)
{
- tree member;
- tree rbase_init_list, vbase_init_list;
- tree t = current_class_type;
- tree t_binfo = TYPE_BINFO (t);
- tree binfos = BINFO_BASETYPES (t_binfo);
- int i;
- int n_baseclasses = BINFO_N_BASETYPES (t_binfo);
-
- mem_init_list = sort_member_init (t, mem_init_list);
- sort_base_init (t, base_init_list, &rbase_init_list, &vbase_init_list);
-
- /* 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));
- construct_virtual_bases (t, current_class_ref, current_class_ptr,
- vbase_init_list, first_arg);
- }
-
- /* Now, perform initialization of non-virtual base classes. */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree init = void_list_node;
+ /* Sort the mem-initializers into the order in which the
+ initializations should be performed. */
+ mem_inits = sort_mem_initializers (current_class_type, mem_inits);
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo,
- 999);
-
- if (TREE_PURPOSE (rbase_init_list))
- init = TREE_VALUE (rbase_init_list);
- else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
- {
- init = NULL_TREE;
- if (extra_warnings
- && DECL_COPY_CONSTRUCTOR_P (current_function_decl))
- warning ("base class `%#T' should be explicitly initialized in the copy constructor",
- BINFO_TYPE (base_binfo));
- }
-
- if (init != void_list_node)
+ in_base_initializer = 1;
+
+ /* Initialize base classes. */
+ while (mem_inits
+ && TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
+ {
+ tree subobject = TREE_PURPOSE (mem_inits);
+ tree arguments = TREE_VALUE (mem_inits);
+
+ /* If these initializations are taking place in a copy
+ constructor, the base class should probably be explicitly
+ initialized. */
+ if (extra_warnings && !arguments
+ && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
+ && TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (subobject)))
+ warning ("base class `%#T' should be explicitly initialized in the "
+ "copy constructor",
+ BINFO_TYPE (subobject));
+
+ /* If an explicit -- but empty -- initializer list was present,
+ treat it just like default initialization at this point. */
+ if (arguments == void_type_node)
+ arguments = NULL_TREE;
+
+ /* Initialize the base. */
+ if (TREE_VIA_VIRTUAL (subobject))
+ construct_virtual_base (subobject, arguments);
+ else
{
- member = build_base_path (PLUS_EXPR, current_class_ptr,
- base_binfo, 1);
- expand_aggr_init_1 (base_binfo, NULL_TREE,
- build_indirect_ref (member, NULL), init,
+ tree base_addr;
+
+ base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
+ subobject, 1);
+ expand_aggr_init_1 (subobject, NULL_TREE,
+ build_indirect_ref (base_addr, NULL),
+ arguments,
LOOKUP_NORMAL);
+ expand_cleanup_for_base (subobject, NULL_TREE);
}
- expand_cleanup_for_base (base_binfo, NULL_TREE);
- rbase_init_list = TREE_CHAIN (rbase_init_list);
+ mem_inits = TREE_CHAIN (mem_inits);
}
+ in_base_initializer = 0;
- /* Initialize the vtable pointers for the class. */
+ /* Initialize the vptrs. */
initialize_vtbl_ptrs (current_class_ptr);
-
- while (mem_init_list)
+
+ /* Initialize the data members. */
+ while (mem_inits)
{
- tree init;
- tree member;
- int from_init_list;
-
- member = TREE_PURPOSE (mem_init_list);
-
- /* See if we had a user-specified member initialization. */
- if (TREE_TYPE (mem_init_list))
- {
- init = TREE_VALUE (mem_init_list);
- from_init_list = 1;
- }
- else
- {
- init = DECL_INITIAL (member);
- from_init_list = 0;
-
- /* Effective C++ rule 12. */
- if (warn_ecpp && init == NULL_TREE
- && !DECL_ARTIFICIAL (member)
- && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)
- warning ("`%D' should be initialized in the member initialization list", member);
- }
-
- perform_member_init (member, init, from_init_list);
- mem_init_list = TREE_CHAIN (mem_init_list);
+ perform_member_init (TREE_PURPOSE (mem_inits),
+ TREE_VALUE (mem_inits));
+ mem_inits = TREE_CHAIN (mem_inits);
}
}
@@ -862,7 +819,7 @@ expand_virtual_init (binfo, decl)
/* 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
+ it is a DECL which is nonzero when this base needs to be
destroyed. */
static void
@@ -876,99 +833,70 @@ expand_cleanup_for_base (binfo, flag)
return;
/* Call the destructor. */
- expr = (build_scoped_method_call
- (current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE,
+ binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
if (flag)
expr = fold (build (COND_EXPR, void_type_node,
- truthvalue_conversion (flag),
+ c_common_truthvalue_conversion (flag),
expr, integer_zero_node));
- finish_subobject (expr);
+ finish_eh_cleanup (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. */
+/* Construct the virtual base-class VBASE passing the ARGUMENTS to its
+ constructor. */
static void
-expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
- tree binfo, exp, addr, init_list;
+construct_virtual_base (tree vbase, tree arguments)
{
- tree init = purpose_member (binfo, init_list);
- tree ref = build_indirect_ref (addr, NULL);
-
- if (init)
- init = TREE_VALUE (init);
- /* Call constructors, but don't set up vtables. */
- expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
-}
-
-/* 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 initializations for constructors to perform. */
-
-static void
-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 vbases;
-
- /* If there are no virtual baseclasses, we shouldn't even be here. */
- my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
-
- /* Now, run through the baseclasses, initializing each. */
- for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree inner_if_stmt;
- tree compound_stmt;
- tree exp;
- tree vbase;
-
- /* 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. */
- inner_if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (flag, inner_if_stmt);
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
-
- /* Compute the location of the virtual base. If we're
- constructing virtual bases, then we must be the most derived
- class. Therefore, we don't have to look up the virtual base;
- we already know where it is. */
- vbase = TREE_VALUE (vbases);
- exp = build (PLUS_EXPR,
- TREE_TYPE (this_ptr),
- this_ptr,
- fold (build1 (NOP_EXPR, TREE_TYPE (this_ptr),
- BINFO_OFFSET (vbase))));
- exp = build1 (NOP_EXPR,
- build_pointer_type (BINFO_TYPE (vbase)),
- exp);
-
- expand_aggr_vbase_init_1 (vbase, this_ref, exp, init_list);
- finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
- finish_then_clause (inner_if_stmt);
- finish_if_stmt ();
-
- expand_cleanup_for_base (vbase, flag);
- }
+ tree inner_if_stmt;
+ tree compound_stmt;
+ tree exp;
+ tree flag;
+
+ /* 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. */
+ flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
+ inner_if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (flag, inner_if_stmt);
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
+
+ /* Compute the location of the virtual base. If we're
+ constructing virtual bases, then we must be the most derived
+ class. Therefore, we don't have to look up the virtual base;
+ we already know where it is. */
+ exp = build (PLUS_EXPR,
+ TREE_TYPE (current_class_ptr),
+ current_class_ptr,
+ fold (build1 (NOP_EXPR, TREE_TYPE (current_class_ptr),
+ BINFO_OFFSET (vbase))));
+ exp = build1 (NOP_EXPR,
+ build_pointer_type (BINFO_TYPE (vbase)),
+ exp);
+ exp = build1 (INDIRECT_REF, BINFO_TYPE (vbase), exp);
+
+ expand_aggr_init_1 (vbase, current_class_ref, exp,
+ arguments, LOOKUP_COMPLAIN);
+ finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+ finish_then_clause (inner_if_stmt);
+ finish_if_stmt ();
+
+ expand_cleanup_for_base (vbase, flag);
}
/* Find the context in which this FIELD can be initialized. */
@@ -1017,46 +945,40 @@ member_init_ok_or_else (field, type, member_name)
return 1;
}
-/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
- which names a field, or it is a _TYPE node or TYPE_DECL which names
- a base for that type. INIT is a parameter list for that field's or
- base's constructor. Check the validity of NAME, and return a
- TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
- only to get its type. If NAME is invalid, return NULL_TREE and
- issue a diagnostic.
+/* NAME is a FIELD_DECL, an IDENTIFIER_NODE which names a field, or it
+ is a _TYPE node or TYPE_DECL which names a base for that type.
+ Check the validity of NAME, and return either the base _TYPE, base
+ binfo, or the FIELD_DECL of the member. If NAME is invalid, return
+ NULL_TREE and issue a diagnostic.
An old style unnamed direct single base construction is permitted,
where NAME is NULL. */
tree
-expand_member_init (exp, name, init)
- tree exp, name, init;
+expand_member_init (tree name)
{
- tree basetype = NULL_TREE, field;
- tree type;
+ tree basetype;
+ tree field;
- if (exp == NULL_TREE)
+ if (!current_class_ref)
return NULL_TREE;
- type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
- my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
-
if (!name)
{
/* This is an obsolete unnamed base class initializer. The
parser will already have warned about its use. */
- switch (CLASSTYPE_N_BASECLASSES (type))
+ switch (CLASSTYPE_N_BASECLASSES (current_class_type))
{
case 0:
error ("unnamed initializer for `%T', which has no base classes",
- type);
+ current_class_type);
return NULL_TREE;
case 1:
- basetype = TYPE_BINFO_BASETYPE (type, 0);
+ basetype = TYPE_BINFO_BASETYPE (current_class_type, 0);
break;
default:
error ("unnamed initializer for `%T', which uses multiple inheritance",
- type);
+ current_class_type);
return NULL_TREE;
}
}
@@ -1067,47 +989,52 @@ expand_member_init (exp, name, init)
}
else if (TREE_CODE (name) == TYPE_DECL)
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
-
- my_friendly_assert (init != NULL_TREE, 0);
-
- if (init == void_type_node)
- init = NULL_TREE;
+ else
+ basetype = NULL_TREE;
if (basetype)
{
+ tree binfo;
+
if (current_template_parms)
- ;
- else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
- /* A direct base. */;
- else if (binfo_for_vbase (basetype, type))
- /* A virtual base. */;
- else
+ return basetype;
+
+ binfo = lookup_base (current_class_type, basetype,
+ ba_ignore, NULL);
+ if (binfo)
{
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+ if (TREE_VIA_VIRTUAL (binfo))
+ binfo = binfo_for_vbase (basetype, current_class_type);
+ else if (BINFO_INHERITANCE_CHAIN (binfo)
+ != TYPE_BINFO (current_class_type))
+ binfo = NULL_TREE;
+ }
+ if (!binfo)
+ {
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
error ("type `%D' is not a direct or virtual base of `%T'",
- name, type);
+ name, current_class_type);
else
error ("type `%D' is not a direct base of `%T'",
- name, type);
+ name, current_class_type);
return NULL_TREE;
}
- init = build_tree_list (basetype, init);
+ if (binfo)
+ return binfo;
}
else
{
if (TREE_CODE (name) == IDENTIFIER_NODE)
- field = lookup_field (type, name, 1, 0);
+ field = lookup_field (current_class_type, name, 1, 0);
else
field = name;
- if (! member_init_ok_or_else (field, type, name))
- return NULL_TREE;
-
- init = build_tree_list (field, init);
+ if (member_init_ok_or_else (field, current_class_type, name))
+ return field;
}
- return init;
+ return NULL_TREE;
}
/* This is like `expand_member_init', only it stores one aggregate
@@ -1131,8 +1058,6 @@ expand_member_init (exp, name, init)
The virtual function table pointer cannot be set up here, because
we do not really know its type.
- Virtual baseclass pointers are also set up here.
-
This never calls operator=().
When initializing, nothing is CONST.
@@ -1191,7 +1116,7 @@ build_aggr_init (exp, init, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
- stmt_expr = build_vec_init (exp, init,
+ stmt_expr = build_vec_init (exp, NULL_TREE, init,
init && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const;
@@ -1221,6 +1146,24 @@ build_aggr_init (exp, init, flags)
return stmt_expr;
}
+/* Like build_aggr_init, but not just for aggregates. */
+
+tree
+build_init (decl, init, flags)
+ tree decl, init;
+ int flags;
+{
+ tree expr;
+
+ if (IS_AGGR_TYPE (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ expr = build_aggr_init (decl, init, flags);
+ else
+ expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
+
+ return expr;
+}
+
static void
expand_default_init (binfo, true_exp, exp, init, flags)
tree binfo;
@@ -1253,10 +1196,13 @@ expand_default_init (binfo, true_exp, exp, init, flags)
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 if (TREE_CODE (init) == CONSTRUCTOR)
- /* A brace-enclosed initializer has whatever type is
- required. There's no need to convert it. */
- ;
+ else if (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
+ {
+ /* A brace-enclosed initializer for an aggregate. */
+ my_friendly_assert (CP_AGGREGATE_TYPE_P (type), 20021016);
+ init = digest_init (type, init, (tree *)NULL);
+ }
else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
@@ -1289,7 +1235,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
else
ctor_name = base_ctor_identifier;
- rval = build_method_call (exp, ctor_name, parms, binfo, flags);
+ rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval))
{
if (building_stmt_tree ())
@@ -1329,6 +1275,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
tree type = TREE_TYPE (exp);
my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
+ my_friendly_assert (building_stmt_tree (), 20021010);
/* Use a function returning the desired type to initialize EXP for us.
If the function is a constructor, and its first argument is
@@ -1343,12 +1290,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
/* If store_init_value returns NULL_TREE, the INIT has been
record in the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
- if (!store_init_value (exp, init))
- {
- if (!building_stmt_tree ())
- expand_decl_init (exp);
- }
- else
+ if (store_init_value (exp, init))
finish_expr_stmt (build (INIT_EXPR, type, exp, init));
return;
}
@@ -1438,6 +1380,7 @@ build_member_call (type, name, parmlist)
{
tree t;
tree method_name;
+ tree fns;
int dtor = 0;
tree basetype_path, decl;
@@ -1458,15 +1401,16 @@ build_member_call (type, name, parmlist)
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);
+ return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
}
if (DECL_P (name))
name = DECL_NAME (name);
if (TREE_CODE (type) == NAMESPACE_DECL)
- return build_x_function_call (lookup_namespace_name (type, name),
- parmlist, current_class_ref);
+ return finish_call_expr (lookup_namespace_name (type, name),
+ parmlist,
+ /*disallow_virtual=*/true);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
@@ -1493,10 +1437,9 @@ build_member_call (type, name, parmlist)
{
tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
- {
- return build_x_function_call (build_offset_ref (type, name),
- parmlist, current_class_ref);
- }
+ return finish_call_expr (lookup_namespace_name (ns, name),
+ parmlist,
+ /*disallow_virtual=*/true);
}
if (type == NULL_TREE || ! is_aggr_type (type, 1))
@@ -1515,30 +1458,34 @@ build_member_call (type, name, parmlist)
decl = maybe_dummy_object (type, &basetype_path);
+ fns = lookup_fnfields (basetype_path, method_name, 0);
+ if (fns)
+ {
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ BASELINK_FUNCTIONS (fns) = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fns),
+ TREE_OPERAND (name, 1));
+ return build_new_method_call (decl, fns, parmlist,
+ /*conversion_path=*/NULL_TREE,
+ LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
+ }
+
/* Convert 'this' to the specified type to disambiguate conversion
to the function's context. */
if (decl == current_class_ref
+ /* ??? this is wrong, but if this conversion is invalid we need to
+ defer it until we know whether we are calling a static or
+ non-static member function. Be conservative for now. */
&& 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_qualified_type (type, TYPE_QUALS (oldtype));
- decl = convert_force (build_pointer_type (newtype), olddecl, 0);
- decl = build_indirect_ref (decl, NULL);
- }
+ basetype_path = NULL_TREE;
+ decl = build_scoped_ref (decl, type, &basetype_path);
+ if (decl == error_mark_node)
+ return error_mark_node;
}
- if (method_name == constructor_name (type)
- || method_name == constructor_name_full (type))
+ if (constructor_name_p (method_name, type))
return build_functional_cast (type, parmlist);
- if (lookup_fnfields (basetype_path, method_name, 0))
- return build_method_call (decl,
- TREE_CODE (name) == TEMPLATE_ID_EXPR
- ? name : method_name,
- parmlist, basetype_path,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
{
@@ -1667,17 +1614,22 @@ build_offset_ref (type, name)
decl = maybe_dummy_object (type, &basebinfo);
- member = lookup_member (basebinfo, name, 1, 0);
-
- if (member == error_mark_node)
- return error_mark_node;
+ if (BASELINK_P (name) || DECL_P (name))
+ member = name;
+ else
+ {
+ member = lookup_member (basebinfo, name, 1, 0);
+
+ if (member == error_mark_node)
+ return error_mark_node;
+ }
/* A lot of this logic is now handled in lookup_member. */
if (member && BASELINK_P (member))
{
/* Go from the TREE_BASELINK to the member function info. */
tree fnfields = member;
- t = TREE_VALUE (fnfields);
+ t = BASELINK_FUNCTIONS (fnfields);
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
{
@@ -1702,7 +1654,7 @@ build_offset_ref (type, name)
return t;
}
- if (!really_overloaded_fn (t))
+ if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
{
/* Get rid of a potential OVERLOAD around it */
t = OVL_CURRENT (t);
@@ -1748,7 +1700,7 @@ build_offset_ref (type, name)
if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t))
{
- error ("illegal pointer to bit-field `%D'", t);
+ error ("invalid pointer to bit-field `%D'", t);
return error_mark_node;
}
@@ -1814,7 +1766,7 @@ resolve_offset_ref (exp)
|| TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
{
/* These were static members. */
- if (mark_addressable (member) == 0)
+ if (!cxx_mark_addressable (member))
return error_mark_node;
return member;
}
@@ -1837,7 +1789,7 @@ resolve_offset_ref (exp)
if (TREE_CODE (member) == FIELD_DECL
&& (base == current_class_ref || is_dummy_object (base)))
{
- tree binfo = TYPE_BINFO (current_class_type);
+ tree binfo = NULL_TREE;
/* Try to get to basetype from 'this'; if that doesn't work,
nothing will. */
@@ -1845,15 +1797,11 @@ resolve_offset_ref (exp)
/* First convert to the intermediate base specified, if appropriate. */
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
- {
- binfo = binfo_or_else (TYPE_OFFSET_BASETYPE (type),
- current_class_type);
- if (!binfo)
- return error_mark_node;
- base = build_base_path (PLUS_EXPR, base, binfo, 1);
- }
+ base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
- return build_component_ref (base, member, binfo, 1);
+ return build_class_member_access_expr (base, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
}
/* Ensure that we have an object. */
@@ -2122,7 +2070,7 @@ build_new (placement, decl, init, use_global_new)
return rval;
}
-/* Given a Java class, return a decl for the corresponding java.lang.Class. */
+/* Given a Java class, return a decl for the corresponding java.lang.Class. */
tree
build_java_class_ref (type)
@@ -2205,6 +2153,7 @@ build_new_1 (exp)
tree placement, init;
tree type, true_type, size, rval, t;
tree full_type;
+ tree outer_nelts = NULL_TREE;
tree nelts = NULL_TREE;
tree alloc_call, alloc_expr, alloc_node;
tree alloc_fn;
@@ -2234,12 +2183,11 @@ build_new_1 (exp)
if (TREE_CODE (type) == ARRAY_REF)
{
has_array = 1;
- nelts = TREE_OPERAND (type, 1);
+ nelts = outer_nelts = TREE_OPERAND (type, 1);
type = TREE_OPERAND (type, 0);
- full_type = cp_build_binary_op (MINUS_EXPR, nelts, integer_one_node);
- full_type = build_index_type (full_type);
- full_type = build_cplus_array_type (type, full_type);
+ /* Use an incomplete array type to avoid VLA headaches. */
+ full_type = build_cplus_array_type (type, NULL_TREE);
}
else
full_type = type;
@@ -2341,7 +2289,8 @@ build_new_1 (exp)
args));
else
alloc_call = build_method_call (build_dummy_object (true_type),
- fnname, args, NULL_TREE,
+ fnname, args,
+ TYPE_BINFO (true_type),
LOOKUP_NORMAL);
}
@@ -2423,17 +2372,21 @@ build_new_1 (exp)
init_expr = build_indirect_ref (alloc_node, NULL);
if (init == void_zero_node)
- init = build_default_init (full_type);
+ init = build_default_init (full_type, nelts);
else if (init && pedantic && has_array)
pedwarn ("ISO C++ forbids initialization in array new");
if (has_array)
- init_expr = build_vec_init (init_expr, init, 0);
+ init_expr
+ = build_vec_init (init_expr,
+ cp_build_binary_op (MINUS_EXPR, outer_nelts,
+ integer_one_node),
+ init, /*from_array=*/0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
- init_expr = build_method_call (init_expr,
- complete_ctor_identifier,
- init, TYPE_BINFO (true_type),
- LOOKUP_NORMAL);
+ init_expr = build_special_member_call (init_expr,
+ complete_ctor_identifier,
+ init, TYPE_BINFO (true_type),
+ LOOKUP_NORMAL);
else
{
/* We are processing something like `new int (10)', which
@@ -2509,16 +2462,20 @@ build_new_1 (exp)
constructor, that would fix the nesting problem and we could
do away with this complexity. But that would complicate other
things; in particular, it would make it difficult to bail out
- if the allocation function returns null. */
+ if the allocation function returns null. Er, no, it wouldn't;
+ we just don't run the constructor. The standard says it's
+ unspecified whether or not the args are evaluated. */
if (cleanup)
{
tree end, sentry, begin;
begin = get_target_expr (boolean_true_node);
- sentry = TREE_OPERAND (begin, 0);
+ CLEANUP_EH_ONLY (begin) = 1;
+
+ sentry = TARGET_EXPR_SLOT (begin);
- TREE_OPERAND (begin, 2)
+ TARGET_EXPR_CLEANUP (begin)
= build (COND_EXPR, void_type_node, sentry,
cleanup, void_zero_node);
@@ -2552,8 +2509,12 @@ build_new_1 (exp)
{
if (check_new)
{
- tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
- integer_zero_node);
+ tree nullexp;
+ tree ifexp;
+
+ nullexp = convert (TREE_TYPE (alloc_node),
+ use_cookie ? cookie_size : size_zero_node);
+ ifexp = cp_build_binary_op (NE_EXPR, alloc_node, nullexp);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
@@ -2748,6 +2709,9 @@ get_temp_regvar (type, init)
initialization of a vector of aggregate types.
BASE is a reference to the vector, of ARRAY_TYPE.
+ MAXINDEX is the maximum index of the array (one less than the
+ number of elements). It is only used if
+ TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE.
INIT is the (possibly NULL) initializer.
FROM_ARRAY is 0 if we should init everything with INIT
@@ -2758,8 +2722,8 @@ get_temp_regvar (type, init)
but use assignment instead of initialization. */
tree
-build_vec_init (base, init, from_array)
- tree base, init;
+build_vec_init (base, maxindex, init, from_array)
+ tree base, init, maxindex;
int from_array;
{
tree rval;
@@ -2779,16 +2743,17 @@ build_vec_init (base, init, from_array)
tree try_block = NULL_TREE;
tree try_body = NULL_TREE;
int num_initialized_elts = 0;
- tree maxindex = array_type_nelts (TREE_TYPE (base));
- if (maxindex == error_mark_node)
+ if (TYPE_DOMAIN (atype))
+ maxindex = array_type_nelts (atype);
+
+ if (maxindex == NULL_TREE || maxindex == error_mark_node)
return error_mark_node;
- /* For g++.ext/arrnew.C. */
- if (init && TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == NULL_TREE)
- init = digest_init (atype, init, 0);
-
- if (init && !TYPE_NEEDS_CONSTRUCTING (type)
+ if (init
+ && (from_array == 2
+ ? (!CLASS_TYPE_P (type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+ : !TYPE_NEEDS_CONSTRUCTING (type))
&& ((TREE_CODE (init) == CONSTRUCTOR
/* Don't do this if the CONSTRUCTOR might contain something
that might throw and require us to clean up. */
@@ -2801,7 +2766,6 @@ build_vec_init (base, init, from_array)
store_constructor will handle the semantics for us. */
stmt_expr = build (INIT_EXPR, atype, base, init);
- TREE_SIDE_EFFECTS (stmt_expr) = 1;
return stmt_expr;
}
@@ -2973,7 +2937,7 @@ build_vec_init (base, init, from_array)
sorry
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
- 0, 0);
+ 0, 0, 0);
}
else
elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base),
@@ -3098,7 +3062,8 @@ build_dtor_call (exp, dtor_kind, flags)
default:
abort ();
}
- return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
+ return build_method_call (exp, name, NULL_TREE,
+ TYPE_BINFO (TREE_TYPE (exp)), flags);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -3132,11 +3097,18 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (!VOID_TYPE_P (type) && !complete_type_or_else (type, addr))
- return error_mark_node;
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
- if (! IS_AGGR_TYPE (type))
+
+ if (VOID_TYPE_P (type)
+ /* We don't want to warn about delete of void*, only other
+ incomplete types. Deleting other incomplete types
+ invokes undefined behavior, but it is not ill-formed, so
+ compile to something that would even do The Right Thing
+ (TM) should the type have a trivial dtor and no delete
+ operator. */
+ || !complete_type_or_diagnostic (type, addr, 1)
+ || !IS_AGGR_TYPE (type))
{
/* Call the builtin operator delete. */
return build_builtin_delete_call (addr);
@@ -3150,8 +3122,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else if (TREE_CODE (type) == ARRAY_TYPE)
{
handle_array:
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
+
if (TYPE_DOMAIN (type) == NULL_TREE)
{
error ("unknown array size in delete");
@@ -3180,7 +3151,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return void_zero_node;
return build_op_delete_call
- (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
NULL_TREE);
}
@@ -3198,7 +3169,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
/* We will use ADDR multiple times so we must save it. */
addr = save_expr (addr);
- /* Delete the object. */
+ /* Delete the object. */
do_delete = build_builtin_delete_call (addr);
/* Otherwise, treat this like a complete object destructor
call. */
@@ -3215,7 +3186,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* Build the call. */
do_delete = build_op_delete_call (DELETE_EXPR,
addr,
- c_sizeof_nowarn (type),
+ cxx_sizeof_nowarn (type),
LOOKUP_NORMAL,
NULL_TREE);
/* Call the complete object destructor. */
@@ -3226,7 +3197,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
/* Make sure we have access to the member op delete, even though
we'll actually be calling it from the destructor. */
- build_op_delete_call (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
LOOKUP_NORMAL, NULL_TREE);
}
@@ -3250,65 +3221,18 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
}
}
-/* At the end of a destructor, call the destructors for our base classes
- and members.
+/* At the beginning of a destructor, push cleanups that will call the
+ destructors for our base classes and members.
- Called from finish_destructor_body. */
+ Called from begin_destructor_body. */
void
-perform_base_cleanups ()
+push_base_cleanups ()
{
tree binfos;
int i, n_baseclasses;
tree member;
tree expr;
- tree member_destructions = NULL;
- tree vbase_destructions = NULL;
-
- for (member = TYPE_FIELDS (current_class_type); member;
- member = TREE_CHAIN (member))
- {
- if (TREE_CODE (member) != FIELD_DECL)
- continue;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
- {
- tree this_member = (build_component_ref
- (current_class_ref, member,
- NULL_TREE, 0));
- tree this_type = TREE_TYPE (member);
- expr = build_delete (this_type, this_member,
- sfk_complete_destructor,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
- 0);
- if (!member_destructions)
- member_destructions = expr;
- else
- member_destructions = build (COMPOUND_EXPR,
- TREE_TYPE (member_destructions),
- expr,
- member_destructions);
- }
- }
- if (member_destructions)
- finish_expr_stmt (member_destructions);
-
- binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
- n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
- /* Take care of the remaining baseclasses. */
- for (i = n_baseclasses - 1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
- || TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- expr = build_scoped_method_call (current_class_ref, base_binfo,
- base_dtor_identifier,
- NULL_TREE);
-
- finish_expr_stmt (expr);
- }
/* Run destructors for all virtual baseclasses. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
@@ -3330,35 +3254,56 @@ perform_base_cleanups ()
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
- tree base_ptr_type = build_pointer_type (base_type);
- expr = current_class_ptr;
-
- /* Convert to the basetype here, as we know the layout is
- fixed. What is more, if we let build_method_call do it,
- it will use the vtable, which may have been clobbered
- by the deletion of our primary base. */
-
- expr = build1 (NOP_EXPR, base_ptr_type, expr);
- expr = build (PLUS_EXPR, base_ptr_type, expr,
- BINFO_OFFSET (vbase));
- expr = build_indirect_ref (expr, NULL);
- expr = build_method_call (expr, base_dtor_identifier,
- NULL_TREE, vbase,
- LOOKUP_NORMAL);
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE,
+ vbase,
+ (LOOKUP_NORMAL
+ | LOOKUP_NONVIRTUAL));
expr = build (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
- if (!vbase_destructions)
- vbase_destructions = expr;
- else
- vbase_destructions = build (COMPOUND_EXPR,
- TREE_TYPE (vbase_destructions),
- expr,
- vbase_destructions);
+ finish_decl_cleanup (NULL_TREE, expr);
}
}
}
- if (vbase_destructions)
- finish_expr_stmt (vbase_destructions);
+
+ binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
+ n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+ /* Take care of the remaining baseclasses. */
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
+ || TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE, base_binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
+ finish_decl_cleanup (NULL_TREE, expr);
+ }
+
+ for (member = TYPE_FIELDS (current_class_type); member;
+ member = TREE_CHAIN (member))
+ {
+ if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+ continue;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+ {
+ tree this_member = (build_class_member_access_expr
+ (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false));
+ tree this_type = TREE_TYPE (member);
+ expr = build_delete (this_type, this_member,
+ sfk_complete_destructor,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+ 0);
+ finish_decl_cleanup (NULL_TREE, expr);
+ }
+ }
}
/* For type TYPE, delete the virtual baseclass objects of DECL. */
@@ -3419,15 +3364,13 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
base = stabilize_reference (base);
- /* Since we can use base many times, save_expr it. */
- if (TREE_SIDE_EFFECTS (base))
- base = save_expr (base);
-
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Step back one from start of vector, and read dimension. */
tree cookie_addr;
+ if (TREE_SIDE_EFFECTS (base))
+ base = save_expr (base);
type = strip_array_types (TREE_TYPE (type));
cookie_addr = build (MINUS_EXPR,
build_pointer_type (sizetype),
@@ -3441,6 +3384,8 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
maxindex = array_type_nelts_total (type);
type = strip_array_types (type);
base = build_unary_op (ADDR_EXPR, base, 1);
+ if (TREE_SIDE_EFFECTS (base))
+ base = save_expr (base);
}
else
{
diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h
index 10daa40..d4748be 100644
--- a/contrib/gcc/cp/lang-options.h
+++ b/contrib/gcc/cp/lang-options.h
@@ -72,10 +72,10 @@ DEFINE_LANG_NAME ("C++")
N_("Export functions even if they can be inlined") },
{ "-fimplicit-templates", "" },
{ "-fno-implicit-templates",
- N_("Only emit explicit template instatiations") },
+ N_("Only emit explicit template instantiations") },
{ "-fimplicit-inline-templates", "" },
{ "-fno-implicit-inline-templates",
- N_("Only emit explicit instatiations of inline templates") },
+ N_("Only emit explicit instantiations of inline templates") },
{ "-finit-priority", "" },
{ "-fno-init-priority", "" },
{ "-fmemoize-lookups", "" },
diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h
index a2bdf90..f7de6d4 100644
--- a/contrib/gcc/cp/lang-specs.h
+++ b/contrib/gcc/cp/lang-specs.h
@@ -33,27 +33,14 @@ Boston, MA 02111-1307, USA. */
{".c++", "@c++", 0},
{".C", "@c++", 0},
{"@c++",
- /* cc1plus has an integrated ISO C preprocessor. We should invoke
- the external preprocessor if -save-temps is given. */
- "%{E|M|MM:cpp0 -lang-c++ %{!no-gcc:-D__GNUG__=%v1}\
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__ -trigraphs -$} %(cpp_options)}\
+ "%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{save-temps|no-integrated-cpp:cpp0 -lang-c++ \
- %{!no-gcc:-D__GNUG__=%v1}\
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__ -trigraphs -$}\
- %(cpp_options) %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
+ %{save-temps|no-integrated-cpp:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
cc1plus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
- %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)\
- %{!no-gcc:-D__GNUG__=%v1} \
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__}}}\
- %{ansi:-trigraphs -$}\
- %(cc1_options) %2 %{+e1*}\
+ %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options) %{!no-gcc:-D__GNUG__=%v1}}}\
+ %(cc1_options) %2 %{+e1*}\
%{!fsyntax-only:%(invoke_as)}}}}",
CPLUSPLUS_CPP_SPEC},
{".ii", "@c++-cpp-output", 0},
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index c40469c..6660c84 100644
--- a/contrib/gcc/cp/lex.c
+++ b/contrib/gcc/cp/lex.c
@@ -23,16 +23,12 @@ Boston, MA 02111-1307, USA. */
/* This file is the lexical analyzer for GNU C++. */
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
#include "config.h"
#include "system.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "c-lex.h"
#include "lex.h"
#include "parse.h"
#include "flags.h"
@@ -85,11 +81,6 @@ extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
-/* These flags are used by c-lex.c. In C++, they're always off and on,
- respectively. */
-int warn_traditional = 0;
-int flag_digraphs = 1;
-
/* the declaration found for the last IDENTIFIER token read in. yylex
must look this up to detect typedefs, which get token type
tTYPENAME, so it is left around in case the identifier is not a
@@ -206,37 +197,6 @@ int interface_only; /* whether or not current file is only for
int interface_unknown; /* whether or not we know this class
to behave according to #pragma interface. */
-/* Tree code classes. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static const char cplus_tree_code_type[] = {
- 'x',
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static const int cplus_tree_code_length[] = {
- 0,
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char *const cplus_tree_code_name[] = {
- "@@dummy",
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
/* Initialization before switch parsing. */
void
@@ -303,7 +263,8 @@ init_operators ()
: &operator_name_info[(int) CODE]); \
oni->identifier = identifier; \
oni->name = NAME; \
- oni->mangled_name = MANGLING;
+ oni->mangled_name = MANGLING; \
+ oni->arity = ARITY;
#include "operators.def"
#undef DEF_OPERATOR
@@ -363,7 +324,6 @@ struct resword
_true_. */
#define D_EXT 0x01 /* GCC extension */
#define D_ASM 0x02 /* in C99, but has a switch to turn it off */
-#define D_OPNAME 0x04 /* operator names */
CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
@@ -397,23 +357,19 @@ static const struct resword reswords[] =
{ "__restrict__", RID_RESTRICT, 0 },
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__volatile", RID_VOLATILE, 0 },
{ "__volatile__", RID_VOLATILE, 0 },
{ "asm", RID_ASM, D_ASM },
- { "and", RID_AND, D_OPNAME },
- { "and_eq", RID_AND_EQ, D_OPNAME },
{ "auto", RID_AUTO, 0 },
- { "bitand", RID_BITAND, D_OPNAME },
- { "bitor", RID_BITOR, D_OPNAME },
{ "bool", RID_BOOL, 0 },
{ "break", RID_BREAK, 0 },
{ "case", RID_CASE, 0 },
{ "catch", RID_CATCH, 0 },
{ "char", RID_CHAR, 0 },
{ "class", RID_CLASS, 0 },
- { "compl", RID_COMPL, D_OPNAME },
{ "const", RID_CONST, 0 },
{ "const_cast", RID_CONSTCAST, 0 },
{ "continue", RID_CONTINUE, 0 },
@@ -439,11 +395,7 @@ static const struct resword reswords[] =
{ "mutable", RID_MUTABLE, 0 },
{ "namespace", RID_NAMESPACE, 0 },
{ "new", RID_NEW, 0 },
- { "not", RID_NOT, D_OPNAME },
- { "not_eq", RID_NOT_EQ, D_OPNAME },
{ "operator", RID_OPERATOR, 0 },
- { "or", RID_OR, D_OPNAME },
- { "or_eq", RID_OR_EQ, D_OPNAME },
{ "private", RID_PRIVATE, 0 },
{ "protected", RID_PROTECTED, 0 },
{ "public", RID_PUBLIC, 0 },
@@ -474,11 +426,8 @@ static const struct resword reswords[] =
{ "volatile", RID_VOLATILE, 0 },
{ "wchar_t", RID_WCHAR, 0 },
{ "while", RID_WHILE, 0 },
- { "xor", RID_XOR, D_OPNAME },
- { "xor_eq", RID_XOR_EQ, D_OPNAME },
};
-#define N_reswords (sizeof reswords / sizeof (struct resword))
/* Table mapping from RID_* constants to yacc token numbers.
Unfortunately we have to have entries for all the keywords in all
@@ -503,6 +452,7 @@ const short rid_to_yy[RID_MAX] =
/* RID_BOUNDED */ 0,
/* RID_UNBOUNDED */ 0,
/* RID_COMPLEX */ TYPESPEC,
+ /* RID_THREAD */ SCSPEC,
/* C++ */
/* RID_FRIEND */ SCSPEC,
@@ -591,20 +541,7 @@ const short rid_to_yy[RID_MAX] =
/* RID_REINTCAST */ REINTERPRET_CAST,
/* RID_STATCAST */ STATIC_CAST,
- /* alternate spellings */
- /* RID_AND */ ANDAND,
- /* RID_AND_EQ */ ASSIGN,
- /* RID_NOT */ '!',
- /* RID_NOT_EQ */ EQCOMPARE,
- /* RID_OR */ OROR,
- /* RID_OR_EQ */ ASSIGN,
- /* RID_XOR */ '^',
- /* RID_XOR_EQ */ ASSIGN,
- /* RID_BITAND */ '&',
- /* RID_BITOR */ '|',
- /* RID_COMPL */ '~',
-
- /* Objective C */
+ /* Objective-C */
/* RID_ID */ 0,
/* RID_AT_ENCODE */ 0,
/* RID_AT_END */ 0,
@@ -625,15 +562,14 @@ init_reswords ()
{
unsigned int i;
tree id;
- int mask = ((flag_operator_names ? 0 : D_OPNAME)
- | (flag_no_asm ? D_ASM : 0)
+ int mask = ((flag_no_asm ? D_ASM : 0)
| (flag_no_gnu_keywords ? D_EXT : 0));
/* It is not necessary to register ridpointers as a GC root, because
all the trees it points to are permanently interned in the
get_identifier hash anyway. */
ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
- for (i = 0; i < N_reswords; i++)
+ for (i = 0; i < ARRAY_SIZE (reswords); i++)
{
id = get_identifier (reswords[i].word);
C_RID_CODE (id) = reswords[i].rid;
@@ -668,27 +604,12 @@ const char *
cxx_init (filename)
const char *filename;
{
- decl_printable_name = lang_printable_name;
input_filename = "<internal>";
init_reswords ();
init_spew ();
init_tree ();
- init_cplus_expand ();
init_cp_semantics ();
-
- add_c_tree_codes ();
-
- memcpy (tree_code_type + (int) LAST_C_TREE_CODE,
- cplus_tree_code_type,
- (int)LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE);
- memcpy (tree_code_length + (int) LAST_C_TREE_CODE,
- cplus_tree_code_length,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (int));
- memcpy (tree_code_name + (int) LAST_C_TREE_CODE,
- cplus_tree_code_name,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (char *));
-
init_operators ();
init_method ();
init_error ();
@@ -715,13 +636,15 @@ cxx_init (filename)
/* Create the built-in __null node. */
null_node = build_int_2 (0, 0);
- TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
ridpointers[RID_NULL] = null_node;
token_count = init_cpp_parse ();
interface_unknown = 1;
filename = c_common_init (filename);
+ if (filename == NULL)
+ return NULL;
init_cp_pragma ();
@@ -806,8 +729,8 @@ static int *reduce_count;
int *token_count;
#if 0
-#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
-#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
+#define REDUCE_LENGTH ARRAY_SIZE (yyr2)
+#define TOKEN_LENGTH (256 + ARRAY_SIZE (yytname))
#endif
#ifdef GATHER_STATISTICS
@@ -885,22 +808,6 @@ print_parse_statistics ()
#endif
}
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-
-void
-cxx_set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- extern int yydebug;
- yydebug = value;
-#else
- warning ("YYDEBUG not defined");
-#endif
-}
-
/* Helper function to load global variables with interface
information. */
@@ -1167,7 +1074,7 @@ do_pending_lang_change ()
pop_lang_context ();
}
-/* Return true if d is in a global scope. */
+/* Return true if d is in a global scope. */
static int
is_global (d)
@@ -1188,6 +1095,40 @@ is_global (d)
}
}
+/* Issue an error message indicating that the lookup of NAME (an
+ IDENTIFIER_NODE) failed. */
+
+void
+unqualified_name_lookup_error (tree name)
+{
+ if (IDENTIFIER_OPNAME_P (name))
+ {
+ if (name != ansi_opname (ERROR_MARK))
+ error ("`%D' not defined", name);
+ }
+ else if (current_function_decl == 0)
+ error ("`%D' was not declared in this scope", name);
+ else
+ {
+ if (IDENTIFIER_NAMESPACE_VALUE (name) != error_mark_node
+ || IDENTIFIER_ERROR_LOCUS (name) != current_function_decl)
+ {
+ static int undeclared_variable_notice;
+
+ error ("`%D' undeclared (first use this function)", name);
+
+ if (! undeclared_variable_notice)
+ {
+ error ("(Each undeclared identifier is reported only once for each function it appears in.)");
+ undeclared_variable_notice = 1;
+ }
+ }
+ /* Prevent repeated error messages. */
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
+ SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
+ }
+}
+
tree
do_identifier (token, parsing, args)
register tree token;
@@ -1197,6 +1138,7 @@ do_identifier (token, parsing, args)
register tree id;
int lexing = (parsing == 1 || parsing == 3);
+ timevar_push (TV_NAME_LOOKUP);
if (! lexing)
id = lookup_name (token, 0);
else
@@ -1227,86 +1169,27 @@ do_identifier (token, parsing, args)
being used as a declarator. So we call it again to get the error
message. */
id = lookup_name (token, 0);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
if (current_template_parms)
- return build_min_nt (LOOKUP_EXPR, token);
- else if (IDENTIFIER_OPNAME_P (token))
- {
- if (token != ansi_opname (ERROR_MARK))
- error ("`%D' not defined", token);
- id = error_mark_node;
- }
- else if (current_function_decl == 0)
- {
- error ("`%D' was not declared in this scope", token);
- id = error_mark_node;
- }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ build_min_nt (LOOKUP_EXPR, token));
+ else if (IDENTIFIER_TYPENAME_P (token))
+ /* A templated conversion operator might exist. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, token);
else
{
- if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node
- || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
- {
- static int undeclared_variable_notice;
-
- error ("`%D' undeclared (first use this function)", token);
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
- }
- id = error_mark_node;
- /* Prevent repeated error messages. */
- SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
- SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
+ unqualified_name_lookup_error (token);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
- if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
- {
- tree shadowed = DECL_SHADOWED_FOR_VAR (id);
- while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
- && DECL_DEAD_FOR_LOCAL (shadowed))
- shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
- if (!shadowed)
- shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id));
- if (shadowed)
- {
- if (!DECL_ERROR_REPORTED (id))
- {
- warning ("name lookup of `%s' changed",
- IDENTIFIER_POINTER (token));
- cp_warning_at (" matches this `%D' under ISO standard rules",
- shadowed);
- cp_warning_at (" matches this `%D' under old rules", id);
- DECL_ERROR_REPORTED (id) = 1;
- }
- id = shadowed;
- }
- else if (!DECL_ERROR_REPORTED (id))
- {
- DECL_ERROR_REPORTED (id) = 1;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (id)))
- {
- error ("name lookup of `%s' changed for new ISO `for' scoping",
- IDENTIFIER_POINTER (token));
- cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", id);
- id = error_mark_node;
- }
- else
- {
- pedwarn ("name lookup of `%s' changed for new ISO `for' scoping",
- IDENTIFIER_POINTER (token));
- cp_pedwarn_at (" using obsolete binding at `%D'", id);
- }
- }
- }
+ id = check_for_out_of_scope_variable (id);
+
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
@@ -1337,28 +1220,15 @@ do_identifier (token, parsing, args)
|| TREE_CODE (id) == USING_DECL))
id = build_min_nt (LOOKUP_EXPR, token);
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
tree
-do_scoped_id (token, parsing)
+do_scoped_id (token, id)
tree token;
- int parsing;
+ tree id;
{
- tree id;
- /* during parsing, this is ::name. Otherwise, it is black magic. */
- if (parsing)
- {
- id = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
- id = NULL_TREE;
- else
- id = BINDING_VALUE (id);
- }
- else
- id = IDENTIFIER_GLOBAL_VALUE (token);
- if (parsing && yychar == YYEMPTY)
- yychar = yylex ();
+ timevar_push (TV_NAME_LOOKUP);
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
@@ -1366,7 +1236,7 @@ do_scoped_id (token, parsing)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
error ("`::%D' undeclared (first use here)", token);
@@ -1397,11 +1267,11 @@ do_scoped_id (token, parsing)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
/* else just use the decl */
}
- return convert_from_reference (id);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, convert_from_reference (id));
}
tree
@@ -1495,6 +1365,12 @@ retrofit_lang_decl (t)
ld = (struct lang_decl *) ggc_alloc_cleared (size);
+ ld->decl_flags.can_be_full = CAN_HAVE_FULL_LANG_DECL_P (t) ? 1 : 0;
+ ld->decl_flags.u1sel = TREE_CODE (t) == NAMESPACE_DECL ? 1 : 0;
+ ld->decl_flags.u2sel = 0;
+ if (ld->decl_flags.can_be_full)
+ ld->u.f.u3sel = TREE_CODE (t) == FUNCTION_DECL ? 1 : 0;
+
DECL_LANG_SPECIFIC (t) = ld;
if (current_lang_name == lang_name_cplusplus)
SET_DECL_LANGUAGE (t, lang_cplusplus);
@@ -1511,7 +1387,7 @@ retrofit_lang_decl (t)
}
void
-copy_lang_decl (node)
+cxx_dup_lang_specific_decl (node)
tree node;
{
int size;
@@ -1543,7 +1419,7 @@ copy_decl (decl)
tree copy;
copy = copy_node (decl);
- copy_lang_decl (copy);
+ cxx_dup_lang_specific_decl (copy);
return copy;
}
@@ -1559,7 +1435,10 @@ copy_lang_type (node)
if (! TYPE_LANG_SPECIFIC (node))
return;
- size = sizeof (struct lang_type);
+ if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
+ size = sizeof (struct lang_type);
+ else
+ size = sizeof (struct lang_type_ptrmem);
lt = (struct lang_type *) ggc_alloc (size);
memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
TYPE_LANG_SPECIFIC (node) = lt;
@@ -1584,7 +1463,7 @@ copy_type (type)
}
tree
-cp_make_lang_type (code)
+cxx_make_type (code)
enum tree_code code;
{
register tree t = make_node (code);
@@ -1599,6 +1478,7 @@ cp_make_lang_type (code)
ggc_alloc_cleared (sizeof (struct lang_type)));
TYPE_LANG_SPECIFIC (t) = pi;
+ pi->u.c.h.is_lang_type_class = 1;
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_type] += 1;
@@ -1639,7 +1519,7 @@ tree
make_aggr_type (code)
enum tree_code code;
{
- tree t = cp_make_lang_type (code);
+ tree t = cxx_make_type (code);
if (IS_AGGR_TYPE_CODE (code))
SET_IS_AGGR_TYPE (t, 1);
@@ -1647,20 +1527,6 @@ make_aggr_type (code)
return t;
}
-void
-compiler_error VPARAMS ((const char *msg, ...))
-{
- char buf[1024];
-
- VA_OPEN (ap, msg);
- VA_FIXEDARG (ap, const char *, msg);
-
- vsprintf (buf, msg, ap);
- VA_CLOSE (ap);
-
- error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
-}
-
/* Return the type-qualifier corresponding to the identifier given by
RID. */
diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h
index 9f868337..15de168 100644
--- a/contrib/gcc/cp/lex.h
+++ b/contrib/gcc/cp/lex.h
@@ -68,15 +68,15 @@ typedef unsigned long RID_BIT_TYPE; /* assumed at least 32 bits */
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
used in a context which makes it a reference to a variable. */
-extern tree lastiddecl;
+extern GTY(()) tree lastiddecl;
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
extern int looking_for_template;
/* Tell the lexer where to look for names. */
-extern tree got_scope;
-extern tree got_object;
+extern GTY(()) tree got_scope;
+extern GTY(()) tree got_object;
/* Pending language change.
Positive is push count, negative is pop count. */
diff --git a/contrib/gcc/cp/mangle.c b/contrib/gcc/cp/mangle.c
index 10f2b62..7180648 100644
--- a/contrib/gcc/cp/mangle.c
+++ b/contrib/gcc/cp/mangle.c
@@ -1,5 +1,5 @@
/* Name mangling for the 3.0 C++ ABI.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Alex Samuel <sameul@codesourcery.com>
This file is part of GNU CC.
@@ -50,10 +50,13 @@
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "tm_p.h"
#include "cp-tree.h"
+#include "real.h"
#include "obstack.h"
#include "toplev.h"
#include "varray.h"
+#include "ggc.h"
/* Debugging support. */
@@ -74,15 +77,16 @@
# define MANGLE_TRACE_TREE(FN, NODE)
#endif
-/* Non-zero if NODE is a class template-id. We can't rely on
+/* Nonzero if NODE is a class template-id. We can't rely on
CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
that hard to distinguish A<T> from A, where A<T> is the type as
instantiated outside of the template, and A is the type used
without parameters inside the template. */
-#define CLASSTYPE_TEMPLATE_ID_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE) != NULL \
- && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
- && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
+#define CLASSTYPE_TEMPLATE_ID_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE) != NULL \
+ && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \
+ || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
+ && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
/* Things we only need one of. This module is not reentrant. */
static struct globals
@@ -122,7 +126,7 @@ static tree subst_identifiers[SUBID_MAX];
/* Single-letter codes for builtin integer types, defined in
<builtin-type>. These are indexed by integer_type_kind values. */
-static char
+static const char
integer_type_codes[itk_none] =
{
'c', /* itk_char */
@@ -159,11 +163,13 @@ static void write_nested_name PARAMS ((tree));
static void write_prefix PARAMS ((tree));
static void write_template_prefix PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
+static void write_conversion_operator_name (tree);
static void write_source_name PARAMS ((tree));
static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
unsigned int));
static void write_integer_cst PARAMS ((tree));
+static void write_real_cst PARAMS ((tree));
static void write_identifier PARAMS ((const char *));
static void write_special_name_constructor PARAMS ((tree));
static void write_special_name_destructor PARAMS ((tree));
@@ -193,11 +199,11 @@ static const char *mangle_decl_string PARAMS ((tree));
/* Control functions. */
-static inline void start_mangling PARAMS ((tree));
-static inline const char *finish_mangling PARAMS ((bool));
+static inline void start_mangling (tree);
+static inline const char *finish_mangling (bool);
static tree mangle_special_for_type PARAMS ((tree, const char *));
-/* Foreign language functions. */
+/* Foreign language functions. */
static void write_java_integer_type_codes PARAMS ((tree));
@@ -206,7 +212,7 @@ static void write_java_integer_type_codes PARAMS ((tree));
#define write_char(CHAR) \
obstack_1grow (&G.name_obstack, (CHAR))
-/* Append a sized buffer to the end of the mangled representation. */
+/* Append a sized buffer to the end of the mangled representation. */
#define write_chars(CHAR, LEN) \
obstack_grow (&G.name_obstack, (CHAR), (LEN))
@@ -215,12 +221,7 @@ static void write_java_integer_type_codes PARAMS ((tree));
#define write_string(STRING) \
obstack_grow (&G.name_obstack, (STRING), strlen (STRING))
-/* Return the position at which the next character will be appended to
- the mangled representation. */
-#define mangled_position() \
- obstack_object_size (&G.name_obstack)
-
-/* Non-zero if NODE1 and NODE2 are both TREE_LIST nodes and have the
+/* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the
same purpose (context, which may be a type) and value (template
decl). See write_template_prefix for more information on what this
is used for. */
@@ -232,15 +233,11 @@ static void write_java_integer_type_codes PARAMS ((tree));
|| TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2)) \
&& TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
-/* Write out a signed quantity in base 10. */
-#define write_signed_number(NUMBER) \
- write_number ((NUMBER), /*unsigned_p=*/0, 10)
-
/* Write out an unsigned quantity in base 10. */
#define write_unsigned_number(NUMBER) \
write_number ((NUMBER), /*unsigned_p=*/1, 10)
-/* If DECL is a template instance, return non-zero and, if
+/* If DECL is a template instance, return nonzero and, if
TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
Otherwise return zero. */
@@ -260,7 +257,7 @@ decl_is_template_id (decl, template_info)
if (template_info != NULL)
/* For a templated TYPE_DECL, the template info is hanging
off the type. */
- *template_info = CLASSTYPE_TEMPLATE_INFO (type);
+ *template_info = TYPE_TEMPLATE_INFO (type);
return 1;
}
}
@@ -380,7 +377,7 @@ add_substitution (node)
dump_substitution_candidates ();
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is a template-id with template
name of substitution_index[INDEX] in the ::std namespace. */
@@ -408,12 +405,12 @@ is_std_substitution (node, index)
return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
&& TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_TEMPLATE_INFO (type)
- && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
+ && TYPE_TEMPLATE_INFO (type)
+ && (DECL_NAME (TYPE_TI_TEMPLATE (type))
== subst_identifiers[index]));
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is the template-id
::std::identifier<char>, where identifier is
substitution_index[INDEX]. */
@@ -473,7 +470,7 @@ is_std_substitution_char (node, index)
candidates for entities appearing earlier in the same mangling
If a substitution is found, write its mangled representation and
- return non-zero. If none is found, just return zero. */
+ return nonzero. If none is found, just return zero. */
static int
find_substitution (node)
@@ -585,7 +582,7 @@ find_substitution (node)
}
/* Now check the list of available substitutions for this mangling
- operation. */
+ operation. */
for (i = 0; i < size; ++i)
{
tree candidate = VARRAY_TREE (G.substitutions, i);
@@ -657,7 +654,7 @@ write_encoding (decl)
tree fn_type;
if (decl_is_template_id (decl, NULL))
- fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
+ fn_type = get_mostly_instantiated_function_type (decl);
else
fn_type = TREE_TYPE (decl);
@@ -675,7 +672,7 @@ write_encoding (decl)
::= <nested-name>
::= <local-name>
- If IGNORE_LOCAL_SCOPE is non-zero, this production of <name> is
+ If IGNORE_LOCAL_SCOPE is nonzero, this production of <name> is
called from <local-name>, which mangles the enclosing scope
elsewhere and then uses this function to mangle just the part
underneath the function scope. So don't use the <local-name>
@@ -847,7 +844,8 @@ write_nested_name (decl)
write_char ('E');
}
-/* <prefix> ::= <prefix> <unqualified-name>>
+/* <prefix> ::= <prefix> <unqualified-name>
+ ::= <template-param>
::= <template-prefix> <template-args>
::= # empty
::= <substitution> */
@@ -870,7 +868,6 @@ write_prefix (node)
return;
if (DECL_P (node))
- /* Node is a decl. */
{
/* If this is a function decl, that means we've hit function
scope, so this prefix must be for a local name. In this
@@ -884,18 +881,22 @@ write_prefix (node)
decl_is_template_id (decl, &template_info);
}
else
- /* Node is a type. */
{
+ /* Node is a type. */
decl = TYPE_NAME (node);
if (CLASSTYPE_TEMPLATE_ID_P (node))
- template_info = CLASSTYPE_TEMPLATE_INFO (node);
+ template_info = TYPE_TEMPLATE_INFO (node);
}
/* In G++ 3.2, the name of the template parameter was used. */
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
+ if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+ && !abi_version_at_least (2))
G.need_abi_warning = true;
- if (template_info != NULL)
+ if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+ && abi_version_at_least (2))
+ write_template_param (node);
+ else if (template_info != NULL)
/* Templated. */
{
write_template_prefix (decl);
@@ -912,6 +913,7 @@ write_prefix (node)
}
/* <template-prefix> ::= <prefix> <template component>
+ ::= <template-param>
::= <substitution> */
static void
@@ -931,7 +933,7 @@ write_template_prefix (node)
if (decl_is_template_id (decl, &template_info))
template = TI_TEMPLATE (template_info);
else if (CLASSTYPE_TEMPLATE_ID_P (type))
- template = CLASSTYPE_TI_TEMPLATE (type);
+ template = TYPE_TI_TEMPLATE (type);
else
/* Oops, not a template. */
abort ();
@@ -967,11 +969,18 @@ write_template_prefix (node)
return;
/* In G++ 3.2, the name of the template template parameter was used. */
- if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+ && !abi_version_at_least (2))
G.need_abi_warning = true;
- write_prefix (context);
- write_unqualified_name (decl);
+ if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+ && abi_version_at_least (2))
+ write_template_param (TREE_TYPE (template));
+ else
+ {
+ write_prefix (context);
+ write_unqualified_name (decl);
+ }
add_substitution (substitution);
}
@@ -1000,14 +1009,12 @@ write_unqualified_name (decl)
tree type;
if (decl_is_template_id (decl, NULL))
{
- tree fn_type = get_mostly_instantiated_function_type (decl, NULL,
- NULL);
+ tree fn_type = get_mostly_instantiated_function_type (decl);
type = TREE_TYPE (fn_type);
}
else
- type = TREE_TYPE (DECL_NAME (decl));
- write_string ("cv");
- write_type (type);
+ type = DECL_CONV_FN_TYPE (decl);
+ write_conversion_operator_name (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
{
@@ -1023,6 +1030,15 @@ write_unqualified_name (decl)
write_source_name (DECL_NAME (decl));
}
+/* Write the unqualified-name for a conversion operator to TYPE. */
+
+static void
+write_conversion_operator_name (tree type)
+{
+ write_string ("cv");
+ write_type (type);
+}
+
/* Non-termial <source-name>. IDENTIFIER is an IDENTIFIER_NODE.
<source-name> ::= </length/ number> <identifier> */
@@ -1098,7 +1114,7 @@ write_number (number, unsigned_p, base)
/* Write out an integral CST in decimal. Most numbers are small, and
representable in a HOST_WIDE_INT. Occasionally we'll have numbers
- bigger than that, which we must deal with. */
+ bigger than that, which we must deal with. */
static inline void
write_integer_cst (cst)
@@ -1109,7 +1125,7 @@ write_integer_cst (cst)
if (TREE_INT_CST_HIGH (cst) + (sign < 0))
{
/* A bignum. We do this in chunks, each of which fits in a
- HOST_WIDE_INT. */
+ HOST_WIDE_INT. */
char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
unsigned HOST_WIDE_INT chunk;
unsigned chunk_digits;
@@ -1119,18 +1135,18 @@ write_integer_cst (cst)
int done;
/* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
- representable. */
+ representable. */
chunk = 1000000000;
chunk_digits = 9;
if (sizeof (HOST_WIDE_INT) >= 8)
{
- /* It is at least 64 bits, so 10^18 is representable. */
+ /* It is at least 64 bits, so 10^18 is representable. */
chunk_digits = 18;
chunk *= chunk;
}
- type = signed_or_unsigned_type (1, TREE_TYPE (cst));
+ type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
base = build_int_2 (chunk, 0);
n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
TREE_TYPE (n) = TREE_TYPE (base) = type;
@@ -1171,6 +1187,72 @@ write_integer_cst (cst)
}
}
+/* Write out a floating-point literal.
+
+ "Floating-point literals are encoded using the bit pattern of the
+ target processor's internal representation of that number, as a
+ fixed-length lowercase hexadecimal string, high-order bytes first
+ (even if the target processor would store low-order bytes first).
+ The "n" prefix is not used for floating-point literals; the sign
+ bit is encoded with the rest of the number.
+
+ Here are some examples, assuming the IEEE standard representation
+ for floating point numbers. (Spaces are for readability, not
+ part of the encoding.)
+
+ 1.0f Lf 3f80 0000 E
+ -1.0f Lf bf80 0000 E
+ 1.17549435e-38f Lf 0080 0000 E
+ 1.40129846e-45f Lf 0000 0001 E
+ 0.0f Lf 0000 0000 E"
+
+ Caller is responsible for the Lx and the E. */
+static void
+write_real_cst (value)
+ tree value;
+{
+ if (abi_version_at_least (2))
+ {
+ long target_real[4]; /* largest supported float */
+ char buffer[9]; /* eight hex digits in a 32-bit number */
+ int i, limit, dir;
+
+ tree type = TREE_TYPE (value);
+ int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
+
+ real_to_target (target_real, &TREE_REAL_CST (value),
+ TYPE_MODE (type));
+
+ /* The value in target_real is in the target word order,
+ so we must write it out backward if that happens to be
+ little-endian. write_number cannot be used, it will
+ produce uppercase. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ i = 0, limit = words, dir = 1;
+ else
+ i = words - 1, limit = -1, dir = -1;
+
+ for (; i != limit; i += dir)
+ {
+ sprintf (buffer, "%08lx", target_real[i]);
+ write_chars (buffer, 8);
+ }
+ }
+ else
+ {
+ /* In G++ 3.3 and before the REAL_VALUE_TYPE was written out
+ literally. Note that compatibility with 3.2 is impossible,
+ because the old floating-point emulator used a different
+ format for REAL_VALUE_TYPE. */
+ size_t i;
+ for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
+ write_number (((unsigned char *) &TREE_REAL_CST (value))[i],
+ /*unsigned_p*/ 1,
+ /*base*/ 16);
+ G.need_abi_warning = 1;
+ }
+}
+
/* Non-terminal <identifier>.
<identifier> ::= </unqualified source code identifier> */
@@ -1293,7 +1375,7 @@ static void
write_discriminator (discriminator)
int discriminator;
{
- /* If discriminator is zero, don't write anything. Otherwise... */
+ /* If discriminator is zero, don't write anything. Otherwise... */
if (discriminator > 0)
{
write_char ('_');
@@ -1359,7 +1441,7 @@ static void
write_type (type)
tree type;
{
- /* This gets set to non-zero if TYPE turns out to be a (possibly
+ /* This gets set to nonzero if TYPE turns out to be a (possibly
CV-qualified) builtin type. */
int is_builtin_type = 0;
@@ -1584,7 +1666,8 @@ write_builtin_type (type)
if (itk == itk_none)
{
- tree t = type_for_mode (TYPE_MODE (type), TREE_UNSIGNED (type));
+ tree t = c_common_type_for_mode (TYPE_MODE (type),
+ TREE_UNSIGNED (type));
if (type == t)
{
if (TYPE_PRECISION (type) == 128)
@@ -1662,7 +1745,7 @@ write_function_type (type)
}
/* Non-terminal <bare-function-type>. TYPE is a FUNCTION_TYPE or
- METHOD_TYPE. If INCLUDE_RETURN_TYPE is non-zero, the return value
+ METHOD_TYPE. If INCLUDE_RETURN_TYPE is nonzero, the return value
is mangled before the parameter types. If non-NULL, DECL is
FUNCTION_DECL for the function whose type is being emitted.
@@ -1687,7 +1770,7 @@ write_bare_function_type (type, include_return_type_p, decl)
}
/* Write the mangled representation of a method parameter list of
- types given in PARM_TYPES. If METHOD_P is non-zero, the function is
+ types given in PARM_TYPES. If METHOD_P is nonzero, the function is
considered a non-static method, and the this parameter is omitted.
If non-NULL, DECL is the FUNCTION_DECL for the function whose
parameters are being emitted. */
@@ -1769,24 +1852,37 @@ static void
write_template_args (args)
tree args;
{
- int i;
- int length = TREE_VEC_LENGTH (args);
-
MANGLE_TRACE_TREE ("template-args", args);
- my_friendly_assert (length > 0, 20000422);
+ write_char ('I');
+
+ if (TREE_CODE (args) == TREE_VEC)
+ {
+ int i;
+ int length = TREE_VEC_LENGTH (args);
+ my_friendly_assert (length > 0, 20000422);
- if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ {
+ /* We have nested template args. We want the innermost template
+ argument list. */
+ args = TREE_VEC_ELT (args, length - 1);
+ length = TREE_VEC_LENGTH (args);
+ }
+ for (i = 0; i < length; ++i)
+ write_template_arg (TREE_VEC_ELT (args, i));
+ }
+ else
{
- /* We have nested template args. We want the innermost template
- argument list. */
- args = TREE_VEC_ELT (args, length - 1);
- length = TREE_VEC_LENGTH (args);
+ my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014);
+
+ while (args)
+ {
+ write_template_arg (TREE_VALUE (args));
+ args = TREE_CHAIN (args);
+ }
}
- write_char ('I');
- for (i = 0; i < length; ++i)
- write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E');
}
@@ -1796,7 +1892,9 @@ write_template_args (args)
<expr-primary> ::= <template-param>
::= L <type> <value number> E # literal
- ::= L <mangled-name> E # external name */
+ ::= L <mangled-name> E # external name
+ ::= sr <type> <unqualified-name>
+ ::= sr <type> <unqualified-name> <template-args> */
static void
write_expression (expr)
@@ -1827,14 +1925,15 @@ write_expression (expr)
code = TREE_CODE (expr);
}
- /* Handle template parameters. */
+ /* Handle template parameters. */
if (code == TEMPLATE_TYPE_PARM
|| code == TEMPLATE_TEMPLATE_PARM
|| code == BOUND_TEMPLATE_TEMPLATE_PARM
|| code == TEMPLATE_PARM_INDEX)
write_template_param (expr);
/* Handle literals. */
- else if (TREE_CODE_CLASS (code) == 'c')
+ else if (TREE_CODE_CLASS (code) == 'c'
+ || (abi_version_at_least (2) && code == CONST_DECL))
write_template_arg_literal (expr);
else if (DECL_P (expr))
{
@@ -1852,6 +1951,75 @@ write_expression (expr)
write_string ("st");
write_type (TREE_OPERAND (expr, 0));
}
+ else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (expr, 0);
+ tree member = TREE_OPERAND (expr, 1);
+
+ /* If the MEMBER is a real declaration, then the qualifying
+ scope was not dependent. Ideally, we would not have a
+ SCOPE_REF in those cases, but sometimes we do. If the second
+ argument is a DECL, then the name must not have been
+ dependent. */
+ if (DECL_P (member))
+ write_expression (member);
+ else
+ {
+ tree template_args;
+
+ write_string ("sr");
+ write_type (scope);
+ /* If MEMBER is a template-id, separate the template
+ from the arguments. */
+ if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
+ {
+ template_args = TREE_OPERAND (member, 1);
+ member = TREE_OPERAND (member, 0);
+ if (TREE_CODE (member) == LOOKUP_EXPR)
+ member = TREE_OPERAND (member, 0);
+ }
+ else
+ template_args = NULL_TREE;
+ /* Write out the name of the MEMBER. */
+ if (IDENTIFIER_TYPENAME_P (member))
+ write_conversion_operator_name (TREE_TYPE (member));
+ else if (IDENTIFIER_OPNAME_P (member))
+ {
+ int i;
+ const char *mangled_name = NULL;
+
+ /* Unfortunately, there is no easy way to go from the
+ name of the operator back to the corresponding tree
+ code. */
+ for (i = 0; i < LAST_CPLUS_TREE_CODE; ++i)
+ if (operator_name_info[i].identifier == member)
+ {
+ /* The ABI says that we prefer binary operator
+ names to unary operator names. */
+ if (operator_name_info[i].arity == 2)
+ {
+ mangled_name = operator_name_info[i].mangled_name;
+ break;
+ }
+ else if (!mangled_name)
+ mangled_name = operator_name_info[i].mangled_name;
+ }
+ else if (assignment_operator_name_info[i].identifier
+ == member)
+ {
+ mangled_name
+ = assignment_operator_name_info[i].mangled_name;
+ break;
+ }
+ write_string (mangled_name);
+ }
+ else
+ write_source_name (member);
+ /* Write out the template arguments. */
+ if (template_args)
+ write_template_args (template_args);
+ }
+ }
else
{
int i;
@@ -1873,12 +2041,16 @@ write_expression (expr)
code = TREE_CODE (expr);
}
-
+
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
switch (code)
{
+ case CALL_EXPR:
+ sorry ("call_expr cannot be mangled due to a defect in the C++ ABI");
+ break;
+
case CAST_EXPR:
write_type (TREE_TYPE (expr));
write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
@@ -1917,11 +2089,7 @@ write_expression (expr)
"Literal arguments, e.g. "A<42L>", are encoded with their type
and value. Negative integer values are preceded with "n"; for
example, "A<-42L>" becomes "1AILln42EE". The bool value false is
- encoded as 0, true as 1. If floating-point arguments are accepted
- as an extension, their values should be encoded using a
- fixed-length lowercase hexadecimal string corresponding to the
- internal representation (IEEE on IA-64), high-order bytes first,
- without leading zeroes. For example: "Lfbff000000E" is -1.0f." */
+ encoded as 0, true as 1." */
static void
write_template_arg_literal (value)
@@ -1948,24 +2116,7 @@ write_template_arg_literal (value)
write_integer_cst (value);
}
else if (TREE_CODE (value) == REAL_CST)
- {
-#ifdef CROSS_COMPILE
- static int explained;
-
- if (!explained)
- {
- sorry ("real-valued template parameters when cross-compiling");
- explained = 1;
- }
-#else
- size_t i;
- for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
- write_number (((unsigned char *)
- &TREE_REAL_CST (value))[i],
- /*unsigned_p=*/1,
- 16);
-#endif
- }
+ write_real_cst (value);
else
abort ();
@@ -2005,6 +2156,9 @@ write_template_arg (node)
else if (code == TEMPLATE_DECL)
/* A template appearing as a template arg is a template template arg. */
write_template_template_arg (node);
+ else if ((TREE_CODE_CLASS (code) == 'c' && code != PTRMEM_CST)
+ || (abi_version_at_least (2) && code == CONST_DECL))
+ write_template_arg_literal (node);
else if (DECL_P (node))
{
/* G++ 3.2 incorrectly mangled non-type template arguments of
@@ -2016,8 +2170,6 @@ write_template_arg (node)
write_encoding (node);
write_char ('E');
}
- else if (TREE_CODE_CLASS (code) == 'c' && code != PTRMEM_CST)
- write_template_arg_literal (node);
else
{
/* Template arguments may be expressions. */
@@ -2098,13 +2250,22 @@ write_pointer_to_member_type (type)
TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
TEMPLATE_PARM_INDEX.
- <template-param> ::= T </parameter/ number> _ */
+ <template-param> ::= T </parameter/ number> _
+
+ If we are internally mangling then we distinguish level and, for
+ non-type parms, type too. The mangling appends
+
+ </level/ number> _ </non-type type/ type> _
+
+ This is used by mangle_conv_op_name_for_type. */
static void
write_template_param (parm)
tree parm;
{
int parm_index;
+ int parm_level;
+ tree parm_type = NULL_TREE;
MANGLE_TRACE_TREE ("template-parm", parm);
@@ -2114,10 +2275,13 @@ write_template_param (parm)
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
parm_index = TEMPLATE_TYPE_IDX (parm);
+ parm_level = TEMPLATE_TYPE_LEVEL (parm);
break;
case TEMPLATE_PARM_INDEX:
parm_index = TEMPLATE_PARM_IDX (parm);
+ parm_level = TEMPLATE_PARM_LEVEL (parm);
+ parm_type = TREE_TYPE (TEMPLATE_PARM_DECL (parm));
break;
default:
@@ -2177,17 +2341,20 @@ write_substitution (seq_id)
write_char ('_');
}
-/* Start mangling a new name or type. */
+/* Start mangling ENTITY. */
static inline void
start_mangling (tree entity)
{
G.entity = entity;
G.need_abi_warning = false;
+ VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
obstack_free (&G.name_obstack, obstack_base (&G.name_obstack));
}
-/* Done with mangling. Return the generated mangled name. */
+/* Done with mangling. Return the generated mangled name. If WARN is
+ true, and the name of G.entity will be mangled differently in a
+ future version of the ABI, issue a warning. */
static inline const char *
finish_mangling (bool warn)
@@ -2198,7 +2365,7 @@ finish_mangling (bool warn)
G.entity);
/* Clear all the substitutions. */
- VARRAY_POP_ALL (G.substitutions);
+ G.substitutions = 0;
/* Null-terminate the string. */
write_char ('\0');
@@ -2212,7 +2379,6 @@ void
init_mangle ()
{
gcc_obstack_init (&G.name_obstack);
- VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
/* Cache these identifiers for quick comparison when checking for
standard substitutions. */
@@ -2454,24 +2620,53 @@ mangle_thunk (fn_decl, offset, vcall_offset)
return get_identifier (result);
}
+/* This hash table maps TYPEs to the IDENTIFIER for a conversion
+ operator to TYPE. The nodes are TREE_LISTs whose TREE_PURPOSE is
+ the TYPE and whose TREE_VALUE is the IDENTIFIER. */
+
+static GTY ((param_is (union tree_node))) htab_t conv_type_names;
+
+/* Hash a node (VAL1) in the table. */
+
+static hashval_t
+hash_type (const void *val)
+{
+ return htab_hash_pointer (TREE_PURPOSE ((tree) val));
+}
+
+/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
+
+static int
+compare_type (const void *val1, const void *val2)
+{
+ return TREE_PURPOSE ((tree) val1) == (tree) val2;
+}
+
/* Return an identifier for the mangled unqualified name for a
conversion operator to TYPE. This mangling is not specified by the
ABI spec; it is only used internally. */
-
+
tree
-mangle_conv_op_name_for_type (type)
- tree type;
+mangle_conv_op_name_for_type (const tree type)
{
+ void **slot;
tree identifier;
-
- /* Build the mangling for TYPE. */
- const char *mangled_type = mangle_type_string (type);
- /* Allocate a temporary buffer for the complete name. */
- char *op_name = concat ("operator ", mangled_type, NULL);
- /* Find or create an identifier. */
- identifier = get_identifier (op_name);
- /* Done with the temporary buffer. */
- free (op_name);
+ char buffer[64];
+
+ if (conv_type_names == NULL)
+ conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);
+
+ slot = htab_find_slot_with_hash (conv_type_names, type,
+ htab_hash_pointer (type), INSERT);
+ if (*slot)
+ return TREE_VALUE ((tree) *slot);
+
+ /* Create a unique name corresponding to TYPE. */
+ sprintf (buffer, "operator %lu",
+ (unsigned long) htab_elements (conv_type_names));
+ identifier = get_identifier (buffer);
+ *slot = build_tree_list (type, identifier);
+
/* Set bits on the identifier so we know later it's a conversion. */
IDENTIFIER_OPNAME_P (identifier) = 1;
IDENTIFIER_TYPENAME_P (identifier) = 1;
@@ -2539,3 +2734,4 @@ write_java_integer_type_codes (type)
abort ();
}
+#include "gt-cp-mangle.h"
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index 5bb555d..16682af 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
-#include "obstack.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
@@ -35,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
+#include "target.h"
/* Various flags to control the mangling process. */
@@ -54,9 +54,6 @@ enum mangling_flags
typedef enum mangling_flags mangling_flags;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
static void do_build_assign_ref PARAMS ((tree));
static void do_build_copy_constructor PARAMS ((tree));
static tree synthesize_exception_spec PARAMS ((tree, tree (*) (tree, void *), void *));
@@ -165,12 +162,26 @@ hack_identifier (value, name)
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
+ if (processing_template_decl)
+ value = build_min_nt (COMPONENT_REF, current_class_ref, name);
+ else
+ {
+ tree access_type = current_class_type;
+
+ while (!DERIVED_FROM_P (context_for_name_lookup (value),
+ access_type))
+ {
+ access_type = TYPE_CONTEXT (access_type);
+ while (DECL_P (access_type))
+ access_type = DECL_CONTEXT (access_type);
+ }
- /* Mark so that if we are in a constructor, and then find that
- this field was initialized by a base initializer,
- we can emit an error message. */
- TREE_USED (value) = 1;
- value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
+ enforce_access (access_type, value);
+ value
+ = build_class_member_access_expr (current_class_ref, value,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
+ }
}
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
@@ -183,7 +194,7 @@ hack_identifier (value, name)
value = OVL_CURRENT (value);
decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
- value = build_component_ref (decl, name, NULL_TREE, 1);
+ value = finish_class_member_access_expr (decl, name);
}
else if (really_overloaded_fn (value))
;
@@ -267,10 +278,11 @@ make_thunk (function, delta, vcall_index)
{
tree thunk_id;
tree thunk;
- tree func_decl;
tree vcall_offset;
HOST_WIDE_INT d;
+ my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
+
/* Scale the VCALL_INDEX to be in terms of bytes. */
if (vcall_index)
vcall_offset
@@ -283,64 +295,66 @@ make_thunk (function, delta, vcall_index)
d = tree_low_cst (delta, 0);
- if (TREE_CODE (function) != ADDR_EXPR)
- abort ();
- func_decl = TREE_OPERAND (function, 0);
- if (TREE_CODE (func_decl) != FUNCTION_DECL)
- abort ();
+ /* See if we already have the thunk in question. */
+ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+ if (THUNK_DELTA (thunk) == d
+ && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE)
+ == (vcall_offset != NULL_TREE))
+ && (THUNK_VCALL_OFFSET (thunk)
+ ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk),
+ vcall_offset)
+ : true))
+ return thunk;
+
+ /* All thunks must be created before FUNCTION is actually emitted;
+ the ABI requires that all thunks be emitted together with the
+ function to which they transfer control. */
+ my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);
+
+ thunk_id = mangle_thunk (function, delta, vcall_offset);
+ thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function));
+ DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
+ cxx_dup_lang_specific_decl (function);
+ SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
+ DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
+ TREE_READONLY (thunk) = TREE_READONLY (function);
+ TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
+ TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+ if (flag_weak)
+ comdat_linkage (thunk);
+ SET_DECL_THUNK_P (thunk);
+ DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
+ THUNK_DELTA (thunk) = d;
+ THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+ /* The thunk itself is not a constructor or destructor, even if
+ the thing it is thunking to is. */
+ DECL_INTERFACE_KNOWN (thunk) = 1;
+ DECL_NOT_REALLY_EXTERN (thunk) = 1;
+ DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
+ DECL_DESTRUCTOR_P (thunk) = 0;
+ DECL_CONSTRUCTOR_P (thunk) = 0;
+ /* And neither is it a clone. */
+ DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
+ DECL_EXTERNAL (thunk) = 1;
+ DECL_ARTIFICIAL (thunk) = 1;
+ /* Even if this thunk is a member of a local class, we don't
+ need a static chain. */
+ DECL_NO_STATIC_CHAIN (thunk) = 1;
+ /* The THUNK is not a pending inline, even if the FUNCTION is. */
+ DECL_PENDING_INLINE_P (thunk) = 0;
+ DECL_INLINE (thunk) = 0;
+ DECL_DECLARED_INLINE_P (thunk) = 0;
+ /* Nor has it been deferred. */
+ DECL_DEFERRED_FN (thunk) = 0;
+ /* Add it to the list of thunks associated with FUNCTION. */
+ TREE_CHAIN (thunk) = DECL_THUNKS (function);
+ DECL_THUNKS (function) = thunk;
- thunk_id = mangle_thunk (TREE_OPERAND (function, 0),
- delta, vcall_offset);
- thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
- if (thunk && !DECL_THUNK_P (thunk))
- {
- error ("implementation-reserved name `%D' used", thunk_id);
- thunk = NULL_TREE;
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
- if (thunk == NULL_TREE)
- {
- thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
- copy_lang_decl (func_decl);
- SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
- DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
- TREE_READONLY (thunk) = TREE_READONLY (func_decl);
- TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
- TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl);
- if (flag_weak)
- comdat_linkage (thunk);
- SET_DECL_THUNK_P (thunk);
- DECL_INITIAL (thunk) = function;
- THUNK_DELTA (thunk) = d;
- THUNK_VCALL_OFFSET (thunk) = vcall_offset;
- /* The thunk itself is not a constructor or destructor, even if
- the thing it is thunking to is. */
- DECL_INTERFACE_KNOWN (thunk) = 1;
- DECL_NOT_REALLY_EXTERN (thunk) = 1;
- DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
- DECL_DESTRUCTOR_P (thunk) = 0;
- DECL_CONSTRUCTOR_P (thunk) = 0;
- /* And neither is it a clone. */
- DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
- DECL_EXTERNAL (thunk) = 1;
- DECL_ARTIFICIAL (thunk) = 1;
- /* Even if this thunk is a member of a local class, we don't
- need a static chain. */
- DECL_NO_STATIC_CHAIN (thunk) = 1;
- /* The THUNK is not a pending inline, even if the FUNC_DECL is. */
- DECL_PENDING_INLINE_P (thunk) = 0;
- /* Nor has it been deferred. */
- DECL_DEFERRED_FN (thunk) = 0;
- /* So that finish_file can write out any thunks that need to be: */
- pushdecl_top_level (thunk);
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
return thunk;
}
/* Emit the definition of a C++ multiple inheritance vtable thunk. If
- EMIT_P is non-zero, the thunk is emitted immediately. */
+ EMIT_P is nonzero, the thunk is emitted immediately. */
void
use_thunk (thunk_fndecl, emit_p)
@@ -350,7 +364,7 @@ use_thunk (thunk_fndecl, emit_p)
tree fnaddr;
tree function;
tree vcall_offset;
- HOST_WIDE_INT delta;
+ HOST_WIDE_INT delta, vcall_value;
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
@@ -376,6 +390,17 @@ use_thunk (thunk_fndecl, emit_p)
delta = THUNK_DELTA (thunk_fndecl);
vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
+ if (vcall_offset)
+ {
+ vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
+
+ /* It is expected that a value of zero means no vcall. */
+ if (!vcall_value)
+ abort ();
+ }
+ else
+ vcall_value = 0;
+
/* And, if we need to emit the thunk, it's used. */
mark_used (thunk_fndecl);
/* This thunk is actually defined. */
@@ -398,8 +423,8 @@ use_thunk (thunk_fndecl, emit_p)
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
-#ifdef ASM_OUTPUT_MI_THUNK
- if (!vcall_offset)
+ if (targetm.asm_out.can_output_mi_thunk (thunk_fndecl, delta,
+ vcall_value, function))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@@ -409,18 +434,23 @@ use_thunk (thunk_fndecl, emit_p)
init_function_start (thunk_fndecl, input_filename, lineno);
current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname);
- ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+
+ targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, delta,
+ vcall_value, function);
+
assemble_end_function (thunk_fndecl, fnname);
current_function_decl = 0;
cfun = 0;
+ /* Because init_function_start increments this, we must
+ decrement it. */
+ immediate_size_expand--;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
}
else
-#endif /* ASM_OUTPUT_MI_THUNK */
{
- /* If we don't have the necessary macro for efficient thunks, generate
- a thunk function that just makes a call to the real function.
- Unfortunately, this doesn't work for varargs. */
+ /* If we don't have the necessary code for efficient thunks,
+ generate a thunk function that just makes a call to the real
+ function. Unfortunately, this doesn't work for varargs. */
tree a, t;
@@ -526,7 +556,6 @@ do_build_copy_constructor (fndecl)
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
tree member_init_list = NULL_TREE;
- tree base_init_list = NULL_TREE;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
@@ -540,10 +569,12 @@ do_build_copy_constructor (fndecl)
{
tree binfo = TREE_VALUE (t);
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (i = 0; i < n_bases; ++i)
@@ -552,10 +583,12 @@ do_build_copy_constructor (fndecl)
if (TREE_VIA_VIRTUAL (binfo))
continue;
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (; fields; fields = TREE_CHAIN (fields))
@@ -599,9 +632,7 @@ do_build_copy_constructor (fndecl)
member_init_list
= tree_cons (field, init, member_init_list);
}
- member_init_list = nreverse (member_init_list);
- base_init_list = nreverse (base_init_list);
- emit_base_init (member_init_list, base_init_list);
+ finish_mem_initializers (member_init_list);
}
}
@@ -626,33 +657,39 @@ do_build_assign_ref (fndecl)
}
else
{
- tree fields = TYPE_FIELDS (current_class_type);
- int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
+ tree fields;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
- for (i = 0; i < n_bases; ++i)
+ /* Assign to each of thedirect base classes. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
{
- /* We must deal with the binfo's directly as a direct base
- might be inaccessible due to ambiguity. */
- tree binfo = TREE_VEC_ELT (binfos, i);
- tree src = build_base_path (PLUS_EXPR, parm, binfo, 1);
- tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1);
-
- tree expr = build_method_call (dst,
- ansi_assopname (NOP_EXPR),
- build_tree_list (NULL_TREE, src),
- binfo,
- LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
- finish_expr_stmt (expr);
+ tree binfo;
+ tree converted_parm;
+
+ binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i);
+ /* We must convert PARM directly to the base class
+ explicitly since the base class may be ambiguous. */
+ converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1);
+ /* Call the base class assignment operator. */
+ finish_expr_stmt
+ (build_special_member_call (current_class_ref,
+ ansi_assopname (NOP_EXPR),
+ build_tree_list (NULL_TREE,
+ converted_parm),
+ binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
}
- for (; fields; fields = TREE_CHAIN (fields))
+
+ /* Assign to each of the non-static data members. */
+ for (fields = TYPE_FIELDS (current_class_type);
+ fields;
+ fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
@@ -733,7 +770,7 @@ synthesize_method (fndecl)
during the generation of the implicit body points at the place
where the attempt to generate the function occurs, giving the
user a hint as to why we are attempting to generate the
- function. */
+ function. */
DECL_SOURCE_LINE (fndecl) = lineno;
DECL_SOURCE_FILE (fndecl) = input_filename;
@@ -808,7 +845,7 @@ synthesize_exception_spec (type, extractor, client)
tree type = TREE_TYPE (fields);
tree fn;
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
diff --git a/contrib/gcc/cp/operators.def b/contrib/gcc/cp/operators.def
index 05a5a39..42e4a47 100644
--- a/contrib/gcc/cp/operators.def
+++ b/contrib/gcc/cp/operators.def
@@ -5,7 +5,7 @@
non-overloadable operators (like the `?:' ternary operator).
Writtey by Mark Mitchell <mark@codesourcery.com>
- Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
ASSN_P
- A boolean value. If non-zero, this is an assignment operator.
+ A boolean value. If nonzero, this is an assignment operator.
Before including this file, you should define DEFOPERATOR
to take these arguments.
diff --git a/contrib/gcc/cp/optimize.c b/contrib/gcc/cp/optimize.c
index ac51cda..654d4cd 100644
--- a/contrib/gcc/cp/optimize.c
+++ b/contrib/gcc/cp/optimize.c
@@ -1,5 +1,5 @@
/* Perform optimizations on tree structure.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Mark Michell (mark@codesourcery.com).
This file is part of GNU CC.
@@ -41,7 +41,7 @@ static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
static void update_cloned_parm PARAMS ((tree, tree));
static void dump_function PARAMS ((enum tree_dump_index, tree));
-/* Optimize the body of FN. */
+/* Optimize the body of FN. */
void
optimize_function (fn)
@@ -64,7 +64,7 @@ optimize_function (fn)
/* We do not inline thunks, as (a) the backend tries to optimize
the call to the thunkee, (b) tree based inlining breaks that
optimization, (c) virtual functions are rarely inlineable,
- and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
+ and (d) TARGET_ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
&& !DECL_THUNK_P (fn))
{
optimize_inline_calls (fn);
@@ -93,9 +93,9 @@ calls_setjmp_r (tp, walk_subtrees, data)
return setjmp_call_p (*tp) ? *tp : NULL_TREE;
}
-/* Returns non-zero if FN calls `setjmp' or some other function that
+/* Returns nonzero if FN calls `setjmp' or some other function that
can return more than once. This function is conservative; it may
- occasionally return a non-zero value even when FN does not actually
+ occasionally return a nonzero value even when FN does not actually
call `setjmp'. */
int
@@ -119,22 +119,21 @@ update_cloned_parm (parm, cloned_parm)
{
DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
- /* We may have taken its address. */
+ /* We may have taken its address. */
TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
- /* The definition might have different constness. */
+ /* The definition might have different constness. */
TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
TREE_USED (cloned_parm) = TREE_USED (parm);
- /* The name may have changed from the declaration. */
+ /* The name may have changed from the declaration. */
DECL_NAME (cloned_parm) = DECL_NAME (parm);
- DECL_SOURCE_FILE (cloned_parm) = DECL_SOURCE_FILE (parm);
- DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm);
+ DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
}
/* FN is a function that has a complete body. Clone the body as
- necessary. Returns non-zero if there's no longer any need to
+ necessary. Returns nonzero if there's no longer any need to
process the main body. */
int
@@ -164,9 +163,9 @@ maybe_clone_body (fn)
splay_tree decl_map;
/* Update CLONE's source position information to match FN's. */
- DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
- DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
+ DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
DECL_INLINE (clone) = DECL_INLINE (fn);
+ DID_INLINE_FUNC (clone) = DID_INLINE_FUNC (fn);
DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
DECL_COMDAT (clone) = DECL_COMDAT (fn);
DECL_WEAK (clone) = DECL_WEAK (fn);
@@ -178,7 +177,7 @@ maybe_clone_body (fn)
DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
- /* Adjust the parameter names and locations. */
+ /* Adjust the parameter names and locations. */
parm = DECL_ARGUMENTS (fn);
clone_parm = DECL_ARGUMENTS (clone);
/* Update the `this' parameter, which is always first. */
@@ -196,7 +195,7 @@ maybe_clone_body (fn)
{
/* Update this parameter. */
update_cloned_parm (parm, clone_parm);
- /* We should only give unused information for one clone. */
+ /* We should only give unused information for one clone. */
if (!first)
TREE_USED (clone_parm) = 1;
}
@@ -266,6 +265,9 @@ maybe_clone_body (fn)
/* Clean up. */
splay_tree_delete (decl_map);
+ /* The clone can throw iff the original function can throw. */
+ cp_function_chain->can_throw = !TREE_NOTHROW (fn);
+
/* Now, expand this function into RTL, if appropriate. */
finish_function (0);
BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
@@ -277,7 +279,7 @@ maybe_clone_body (fn)
return 1;
}
-/* Dump FUNCTION_DECL FN as tree dump PHASE. */
+/* Dump FUNCTION_DECL FN as tree dump PHASE. */
static void
dump_function (phase, fn)
diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y
index e929ebe..46e5021 100644
--- a/contrib/gcc/cp/parse.y
+++ b/contrib/gcc/cp/parse.y
@@ -28,9 +28,6 @@ Boston, MA 02111-1307, USA. */
is given. Keep this in mind when reading the actions. */
%{
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
#include "config.h"
#include "system.h"
@@ -39,17 +36,59 @@ Boston, MA 02111-1307, USA. */
#include "input.h"
#include "flags.h"
#include "cp-tree.h"
+#include "decl.h"
#include "lex.h"
+#include "c-pragma.h" /* For YYDEBUG definition. */
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "ggc.h"
-extern struct obstack permanent_obstack;
-
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
+/* Like the default stack expander, except (1) use realloc when possible,
+ (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
+
+ Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
+ give malloced_yyvs its proper type. This is ok since all we need from
+ it is to be able to free it. */
+
+static short *malloced_yyss;
+static void *malloced_yyvs;
+
+#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ) \
+do { \
+ size_t newsize; \
+ short *newss; \
+ YYSTYPE *newvs; \
+ newsize = *(YYSSZ) *= 2; \
+ if (malloced_yyss) \
+ { \
+ newss = (short *) \
+ really_call_realloc (*(SS), newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) \
+ really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
+ } \
+ else \
+ { \
+ newss = (short *) really_call_malloc (newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+ if (newss) \
+ memcpy (newss, *(SS), (SSSIZE)); \
+ if (newvs) \
+ memcpy (newvs, *(VS), (VSSIZE)); \
+ } \
+ if (!newss || !newvs) \
+ { \
+ yyerror (MSG); \
+ return 2; \
+ } \
+ *(SS) = newss; \
+ *(VS) = newvs; \
+ malloced_yyss = newss; \
+ malloced_yyvs = (void *) newvs; \
+} while (0)
#define OP0(NODE) (TREE_OPERAND (NODE, 0))
#define OP1(NODE) (TREE_OPERAND (NODE, 1))
@@ -57,26 +96,22 @@ extern struct obstack permanent_obstack;
error message if the user supplies an empty conditional expression. */
static const char *cond_stmt_keyword;
-/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
-int have_extern_spec;
-int used_extern_spec;
-
/* List of types and structure classes of the current declaration. */
-static tree current_declspecs;
+static GTY(()) tree current_declspecs;
/* List of prefix attributes in effect.
Prefix attributes are parsed by the reserved_declspecs and declmods
rules. They create a list that contains *both* declspecs and attrs. */
/* ??? It is not clear yet that all cases where an attribute can now appear in
a declspec list have been updated. */
-static tree prefix_attributes;
+static GTY(()) tree prefix_attributes;
/* When defining an enumeration, this is the type of the enumeration. */
-static tree current_enum_type;
+static GTY(()) tree current_enum_type;
/* When parsing a conversion operator name, this is the scope of the
operator itself. */
-static tree saved_scopes;
+static GTY(()) tree saved_scopes;
static tree empty_parms PARAMS ((void));
static tree parse_decl0 PARAMS ((tree, tree, tree, tree, int));
@@ -89,6 +124,12 @@ static tree parse_bitfield PARAMS ((tree, tree, tree));
static tree parse_method PARAMS ((tree, tree, tree));
static void frob_specs PARAMS ((tree, tree));
static void check_class_key PARAMS ((tree, tree));
+static tree parse_scoped_id PARAMS ((tree));
+static tree parse_xref_tag (tree, tree, int);
+static tree parse_handle_class_head (tree, tree, tree, int, int *);
+static void parse_decl_instantiation (tree, tree, tree);
+static int parse_begin_function_definition (tree, tree);
+static tree parse_finish_call_expr (tree, tree, int);
/* Cons up an empty parameter list. */
static inline tree
@@ -97,7 +138,7 @@ empty_parms ()
tree parms;
#ifndef NO_IMPLICIT_EXTERN_C
- if (in_system_header && current_class_type == NULL
+ if (in_system_header && current_class_type == NULL
&& current_lang_name == lang_name_c)
parms = NULL_TREE;
else
@@ -118,18 +159,18 @@ frob_specs (specs_attrs, lookups)
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = build_tree_list (NULL_TREE, current_declspecs);
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
/* We have to indicate that there is an "extern", but that it
was part of a language specifier. For instance,
-
+
extern "C" typedef int (*Ptr) ();
is well formed. */
current_declspecs = tree_cons (error_mark_node,
- get_identifier ("extern"),
+ get_identifier ("extern"),
current_declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
}
@@ -222,26 +263,15 @@ check_class_key (key, aggr)
: key == record_type_node ? "struct" : "class", aggr);
}
-void
-cp_parse_init ()
-{
- ggc_add_tree_root (&current_declspecs, 1);
- ggc_add_tree_root (&prefix_attributes, 1);
- ggc_add_tree_root (&current_enum_type, 1);
- ggc_add_tree_root (&saved_scopes, 1);
-}
-
-/* Rename the "yyparse" function so that we can override it elsewhere. */
-#define yyparse yyparse_1
%}
%start program
-%union {
- long itype;
- tree ttype;
- char *strtype;
- enum tree_code code;
+%union { GTY(())
+ long itype;
+ tree ttype;
+ char *strtype;
+ enum tree_code code;
flagged_type_tree ftype;
struct unparsed_text *pi;
}
@@ -277,7 +307,7 @@ cp_parse_init ()
/* __func__, __FUNCTION__ or __PRETTY_FUNCTION__.
yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token VAR_FUNC_NAME
+%token <ttype> VAR_FUNC_NAME
/* String constants in raw form.
yylval is a STRING_CST node. */
@@ -349,14 +379,14 @@ cp_parse_init ()
%type <ttype> PFUNCNAME maybe_identifier
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas expr_no_comma_rangle
-%type <ttype> cast_expr unary_expr primary string STRING
-%type <ttype> reserved_declspecs boolean.literal
+%type <ttype> cast_expr unary_expr primary STRING
+%type <ttype> reserved_declspecs boolean_literal
%type <ttype> reserved_typespecquals
%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
%type <ttype> init initlist maybeasm maybe_init defarg defarg1
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word
+%type <ttype> any_word unoperator
%type <itype> save_lineno
%type <ttype> simple_stmt simple_if
@@ -366,14 +396,14 @@ cp_parse_init ()
%type <ttype> after_type_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
%type <itype> components notype_components
-%type <ttype> component_decl component_decl_1
+%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> absdcl cv_qualifiers
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_declarator direct_new_declarator
-%type <ttype> xexpr parmlist parms bad_parm
+%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 expr_or_declarator_intern
@@ -382,7 +412,7 @@ cp_parse_init ()
%type <ttype> template_id do_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
%type <ttype> complex_direct_notype_declarator functional_cast
-%type <ttype> complex_parmlist parms_comma
+%type <ttype> complex_parmlist parms_comma
%type <ttype> namespace_qualifier namespace_using_decl
%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
@@ -396,22 +426,22 @@ cp_parse_init ()
%token <ttype> PTYPENAME
%token <ttype> EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
-%token <pi> PRE_PARSED_FUNCTION_DECL
+%token <pi> PRE_PARSED_FUNCTION_DECL
%type <ttype> component_constructor_declarator
-%type <ttype> fn.def2 return_id constructor_declarator
-%type <ttype> .begin_function_body
+%type <ttype> fn_def2 return_id constructor_declarator
+%type <ttype> begin_function_body_
%type <ttype> class_head class_head_apparent_template
%type <ftype> class_head_decl class_head_defn
%type <ttype> base_class_list
%type <ttype> base_class_access_list
-%type <ttype> base_class maybe_base_class_list base_class.1
+%type <ttype> base_class maybe_base_class_list base_class_1
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
%type <ttype> operator_name
%type <ttype> object aggr
%type <itype> new delete
/* %type <ttype> primary_no_id */
%type <ttype> maybe_parmlist
-%type <ttype> member_init
+%type <ttype> begin_member_init member_init
%type <ftype> member_init_list
%type <ttype> template_parm_header template_spec_header template_header
%type <ttype> template_parm_list template_parm
@@ -432,7 +462,7 @@ cp_parse_init ()
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
%type <ttype> handler_args
-%type <ttype> self_template_type .finish_template_type
+%type <ttype> self_template_type finish_template_type_
%token NSNAME
%type <ttype> NSNAME
@@ -476,12 +506,11 @@ extdefs_opt:
;
.hush_warning:
- { have_extern_spec = 1;
- used_extern_spec = 0;
+ { have_extern_spec = true;
$<ttype>$ = NULL_TREE; }
;
.warning_ok:
- { have_extern_spec = 0; }
+ { have_extern_spec = false; }
;
extension:
@@ -514,9 +543,8 @@ extdef:
{ do_pending_inlines (); }
| template_def
{ do_pending_inlines (); }
- | asm_keyword '(' string ')' ';'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
- assemble_asm ($3); }
+ | asm_keyword '(' STRING ')' ';'
+ { assemble_asm ($3); }
| extern_lang_string '{' extdefs_opt '}'
{ pop_lang_context (); }
| extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
@@ -540,7 +568,7 @@ extdef:
;
namespace_alias:
- NAMESPACE identifier '='
+ NAMESPACE identifier '='
{ begin_only_namespace_names (); }
any_id ';'
{
@@ -627,7 +655,7 @@ template_parm_header:
template_spec_header:
TEMPLATE '<' '>'
- { begin_specialization();
+ { begin_specialization();
$$ = NULL_TREE; }
;
@@ -682,14 +710,7 @@ template_parm:
{ $$ = build_tree_list (NULL_TREE, $1); }
| template_template_parm '=' template_arg
{
- if (TREE_CODE ($3) != TEMPLATE_DECL
- && TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
- && TREE_CODE ($3) != TYPE_DECL
- && TREE_CODE ($3) != UNBOUND_CLASS_TEMPLATE)
- {
- error ("invalid default template argument");
- $3 = error_mark_node;
- }
+ $3 = check_template_template_default_arg ($3);
$$ = build_tree_list ($3, $1);
}
;
@@ -778,9 +799,9 @@ eat_saved_input:
mem-initializer-list, so we open one there and suppress the one that
actually corresponds to the curly braces. */
function_body:
- .begin_function_body ctor_initializer_opt save_lineno '{'
+ begin_function_body_ ctor_initializer_opt save_lineno '{'
{ $<ttype>$ = begin_compound_stmt (/*has_no_scope=*/1); }
- compstmtend
+ compstmtend
{
STMT_LINENO ($<ttype>5) = $3;
finish_compound_stmt (/*has_no_scope=*/1, $<ttype>5);
@@ -798,15 +819,15 @@ fndef:
;
constructor_declarator:
- nested_name_specifier SELFNAME '('
+ nested_name_specifier SELFNAME '('
{ $$ = begin_constructor_declarator ($1, $2); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
| nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
- { $$ = begin_constructor_declarator ($1, $2);
+ { $$ = begin_constructor_declarator ($1, $2);
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
}
- | global_scope nested_name_specifier SELFNAME '('
+ | global_scope nested_name_specifier SELFNAME '('
{ $$ = begin_constructor_declarator ($2, $3); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
@@ -814,7 +835,7 @@ constructor_declarator:
{ $$ = begin_constructor_declarator ($2, $3);
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
}
- | nested_name_specifier self_template_type '('
+ | nested_name_specifier self_template_type '('
{ $$ = begin_constructor_declarator ($1, $2); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
@@ -822,12 +843,12 @@ constructor_declarator:
{ $$ = begin_constructor_declarator ($1, $2);
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
}
- | global_scope nested_name_specifier self_template_type '('
+ | global_scope nested_name_specifier self_template_type '('
{ $$ = begin_constructor_declarator ($2, $3); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
| global_scope nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
- { $$ = begin_constructor_declarator ($2, $3);
+ { $$ = begin_constructor_declarator ($2, $3);
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
}
;
@@ -835,19 +856,19 @@ constructor_declarator:
fn.def1:
typed_declspecs declarator
{ check_for_new_type ("return type", $1);
- if (!begin_function_definition ($1.t, $2))
+ if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| declmods notype_declarator
- { if (!begin_function_definition ($1.t, $2))
+ { if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| notype_declarator
- { if (!begin_function_definition (NULL_TREE, $1))
+ { if (!parse_begin_function_definition (NULL_TREE, $1))
YYERROR1; }
| declmods constructor_declarator
- { if (!begin_function_definition ($1.t, $2))
+ { if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| constructor_declarator
- { if (!begin_function_definition (NULL_TREE, $1))
+ { if (!parse_begin_function_definition (NULL_TREE, $1))
YYERROR1; }
;
@@ -872,7 +893,7 @@ component_constructor_declarator:
/* more C++ complexity. See component_decl for a comment on the
reduce/reduce conflict introduced by these rules. */
-fn.def2:
+fn_def2:
declmods component_constructor_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups);
rest_of_mdef:
@@ -882,19 +903,19 @@ fn.def2:
yychar = YYLEX;
snarf_method ($$); }
| component_constructor_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
| typed_declspecs declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| declmods notype_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| notype_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
| declmods constructor_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| constructor_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
;
@@ -915,18 +936,15 @@ return_init:
;
base_init:
- ':' member_init_list
+ ':' { begin_mem_initializers (); } member_init_list
{
- if (! DECL_CONSTRUCTOR_P (current_function_decl))
- error ("only constructors take base initializers");
- else if ($2.new_type_flag == 0)
+ if ($3.new_type_flag == 0)
error ("no base or member initializers given following ':'");
-
- finish_mem_initializers ($2.t);
+ finish_mem_initializers ($3.t);
}
;
-.begin_function_body:
+begin_function_body_:
/* empty */
{
$$ = begin_function_body ();
@@ -935,20 +953,20 @@ base_init:
member_init_list:
/* empty */
- {
- $$.new_type_flag = 0;
- $$.t = NULL_TREE;
+ {
+ $$.new_type_flag = 0;
+ $$.t = NULL_TREE;
}
| member_init
- {
- $$.new_type_flag = 1;
- $$.t = $1;
+ {
+ $$.new_type_flag = 1;
+ $$.t = $1;
}
| member_init_list ',' member_init
- {
- if ($3)
+ {
+ if ($3)
{
- $$.new_type_flag = 1;
+ $$.new_type_flag = 1;
TREE_CHAIN ($3) = $1.t;
$$.t = $3;
}
@@ -958,38 +976,35 @@ member_init_list:
| member_init_list error
;
-member_init:
- '(' nonnull_exprlist ')'
+begin_member_init:
+ /* empty */
{
- if (current_class_name)
+ if (current_class_name)
pedwarn ("anachronistic old style base class initializer");
- $$ = expand_member_init (current_class_ref, NULL_TREE, $2);
+ $$ = expand_member_init (NULL_TREE);
+ in_base_initializer = $$ && !DECL_P ($$);
}
- | LEFT_RIGHT
- {
- if (current_class_name)
- pedwarn ("anachronistic old style base class initializer");
- $$ = expand_member_init (current_class_ref,
- NULL_TREE,
- void_type_node);
- }
- | notype_identifier '(' nonnull_exprlist ')'
- { $$ = expand_member_init (current_class_ref, $1, $3); }
- | notype_identifier LEFT_RIGHT
- { $$ = expand_member_init (current_class_ref, $1,
- void_type_node); }
- | nonnested_type '(' nonnull_exprlist ')'
- { $$ = expand_member_init (current_class_ref, $1, $3); }
- | nonnested_type LEFT_RIGHT
- { $$ = expand_member_init (current_class_ref, $1,
- void_type_node); }
- | typename_sub '(' nonnull_exprlist ')'
- { $$ = expand_member_init (current_class_ref, $1, $3); }
- | typename_sub LEFT_RIGHT
- { $$ = expand_member_init (current_class_ref, $1,
- void_type_node); }
+ | notype_identifier
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ | nonnested_type
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ | typename_sub
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ ;
+
+member_init:
+ begin_member_init '(' nonnull_exprlist ')'
+ { in_base_initializer = 0;
+ $$ = $1 ? build_tree_list ($1, $3) : NULL_TREE; }
+ | begin_member_init LEFT_RIGHT
+ { in_base_initializer = 0;
+ $$ = $1 ? build_tree_list ($1, void_type_node) : NULL_TREE; }
| error
- { $$ = NULL_TREE; }
+ { in_base_initializer = 0;
+ $$ = NULL_TREE; }
;
identifier:
@@ -1002,7 +1017,7 @@ identifier:
notype_identifier:
IDENTIFIER
- | PTYPENAME
+ | PTYPENAME
| NSNAME %prec EMPTY
;
@@ -1019,40 +1034,40 @@ explicit_instantiation:
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation typed_declspecs declarator
{ tree specs = strip_attrs ($3.t);
- do_decl_instantiation (specs, $4, NULL_TREE); }
+ parse_decl_instantiation (specs, $4, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation notype_declarator
- { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ { parse_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation constructor_declarator
- { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ { parse_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation typespec ';'
{ do_type_instantiation ($4.t, $1, 1);
yyungetc (';', 1); }
end_explicit_instantiation
{}
- | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
+ | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
declarator
{ tree specs = strip_attrs ($4.t);
- do_decl_instantiation (specs, $5, $1); }
+ parse_decl_instantiation (specs, $5, $1); }
end_explicit_instantiation
{}
| SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator
- { do_decl_instantiation (NULL_TREE, $4, $1); }
+ { parse_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
{}
| SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator
- { do_decl_instantiation (NULL_TREE, $4, $1); }
+ { parse_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
{}
;
-begin_explicit_instantiation:
+begin_explicit_instantiation:
{ begin_explicit_instantiation(); }
;
-end_explicit_instantiation:
+end_explicit_instantiation:
{ end_explicit_instantiation(); }
;
@@ -1062,10 +1077,10 @@ end_explicit_instantiation:
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
| tTYPENAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
| self_template_type
;
@@ -1073,29 +1088,29 @@ template_type:
apparent_template_type:
template_type
| identifier '<' template_arg_list_opt '>'
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
;
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
;
-.finish_template_type:
- {
+finish_template_type_:
+ {
if (yychar == YYEMPTY)
yychar = YYLEX;
- $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
+ $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
yychar == SCOPE);
}
;
template_close_bracket:
'>'
- | RSHIFT
+ | RSHIFT
{
/* Handle `Class<Class<Type>>' without space in the `>>' */
pedwarn ("`>>' should be `> >' in template class name");
@@ -1140,7 +1155,7 @@ template_arg:
$$ = error_mark_node;
}
else
- $$ = make_unbound_class_template ($1, $3, 1);
+ $$ = make_unbound_class_template ($1, $3, tf_error | tf_parsing);
}
;
@@ -1206,11 +1221,11 @@ condition:
$<ttype>$ = parse_decl ($<ttype>2, $4, 1);
}
init
- {
+ {
parse_end_decl ($<ttype>6, $7, $4);
- $$ = convert_from_reference ($<ttype>6);
+ $$ = convert_from_reference ($<ttype>6);
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
- error ("definition of array `%#D' in condition", $$);
+ error ("definition of array `%#D' in condition", $$);
}
| expr
;
@@ -1224,10 +1239,10 @@ compstmtend:
nontrivial_exprlist:
expr_no_commas ',' expr_no_commas
- { $$ = tree_cons (NULL_TREE, $$,
+ { $$ = tree_cons (NULL_TREE, $$,
build_tree_list (NULL_TREE, $3)); }
| expr_no_commas ',' error
- { $$ = tree_cons (NULL_TREE, $$,
+ { $$ = tree_cons (NULL_TREE, $$,
build_tree_list (NULL_TREE, error_mark_node)); }
| nontrivial_exprlist ',' expr_no_commas
{ chainon ($$, build_tree_list (NULL_TREE, $3)); }
@@ -1270,37 +1285,37 @@ unary_expr:
{ $$ = finish_alignof ($2);
skip_evaluation--; }
| alignof '(' type_id ')' %prec HYPERUNARY
- { $$ = finish_alignof (groktypename ($3.t));
+ { $$ = finish_alignof (groktypename ($3.t));
check_for_new_type ("alignof", $3);
skip_evaluation--; }
/* The %prec EMPTY's here are required by the = init initializer
syntax extension; see below. */
| new new_type_id %prec EMPTY
- { $$ = build_new (NULL_TREE, $2.t, NULL_TREE, $1);
+ { $$ = build_new (NULL_TREE, $2.t, NULL_TREE, $1);
check_for_new_type ("new", $2); }
| new new_type_id new_initializer
- { $$ = build_new (NULL_TREE, $2.t, $3, $1);
+ { $$ = build_new (NULL_TREE, $2.t, $3, $1);
check_for_new_type ("new", $2); }
| new new_placement new_type_id %prec EMPTY
- { $$ = build_new ($2, $3.t, NULL_TREE, $1);
+ { $$ = build_new ($2, $3.t, NULL_TREE, $1);
check_for_new_type ("new", $3); }
| new new_placement new_type_id new_initializer
- { $$ = build_new ($2, $3.t, $4, $1);
+ { $$ = build_new ($2, $3.t, $4, $1);
check_for_new_type ("new", $3); }
| new '(' type_id ')'
%prec EMPTY
{ $$ = build_new (NULL_TREE, groktypename($3.t),
- NULL_TREE, $1);
+ NULL_TREE, $1);
check_for_new_type ("new", $3); }
| new '(' type_id ')' new_initializer
- { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1);
+ { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1);
check_for_new_type ("new", $3); }
| new new_placement '(' type_id ')' %prec EMPTY
- { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1);
+ { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1);
check_for_new_type ("new", $4); }
| new new_placement '(' type_id ')' new_initializer
- { $$ = build_new ($2, groktypename($4.t), $6, $1);
+ { $$ = build_new ($2, groktypename($4.t), $6, $1);
check_for_new_type ("new", $4); }
| delete cast_expr %prec UNARY
@@ -1337,21 +1352,12 @@ new_initializer:
error ("`%T' is not a valid expression", $2.t);
$$ = error_mark_node;
}
- /* GNU extension so people can use initializer lists. Note that
- this alters the meaning of `new int = 1', which was previously
- syntactically valid but semantically invalid.
- This feature is now deprecated and will be removed in a future
- release. */
| '=' init
{
- if (pedantic)
- pedwarn ("ISO C++ forbids initialization of new expression with `='");
- cp_deprecated ("new initializer lists extension");
- if (TREE_CODE ($2) != TREE_LIST
- && TREE_CODE ($2) != CONSTRUCTOR)
- $$ = build_tree_list (NULL_TREE, $2);
- else
- $$ = $2;
+ /* This was previously allowed as an extension, but
+ was removed in G++ 3.3. */
+ error ("initialization of new expression with `='");
+ $$ = error_mark_node;
}
;
@@ -1362,7 +1368,7 @@ regcast_or_absdcl:
$$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $2); }
| regcast_or_absdcl '(' type_id ')' %prec EMPTY
- { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
+ { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
$$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $3); }
;
@@ -1372,9 +1378,9 @@ cast_expr:
| regcast_or_absdcl unary_expr %prec UNARY
{ $$ = reparse_absdcl_as_casts ($$, $2); }
| regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY
- {
+ {
tree init = build_nt (CONSTRUCTOR, NULL_TREE,
- nreverse ($3));
+ nreverse ($3));
if (pedantic)
pedwarn ("ISO C++ forbids compound literals");
/* Indicate that this was a C99 compound literal. */
@@ -1506,11 +1512,11 @@ notype_unqualified_id:
do_id:
{
- /* 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
+ /* If lastiddecl is a BASELINK 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)
+ if (!lastiddecl || !BASELINK_P (lastiddecl))
$$ = do_identifier ($<ttype>-1, 3, NULL_TREE);
else
$$ = $<ttype>-1;
@@ -1518,10 +1524,20 @@ do_id:
;
template_id:
- PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
- { $$ = lookup_template_function ($3, $4); }
+ PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
+ {
+ tree template_name = $3;
+ if (TREE_CODE (template_name) == COMPONENT_REF)
+ template_name = TREE_OPERAND (template_name, 1);
+ $$ = lookup_template_function (template_name, $4);
+ }
| operator_name '<' do_id template_arg_list_opt template_close_bracket
- { $$ = lookup_template_function ($3, $4); }
+ {
+ tree template_name = $3;
+ if (TREE_CODE (template_name) == COMPONENT_REF)
+ template_name = TREE_OPERAND (template_name, 1);
+ $$ = lookup_template_function (template_name, $4);
+ }
;
object_template_id:
@@ -1529,7 +1545,7 @@ object_template_id:
{ $$ = lookup_template_function ($2, $4); }
| TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
- | TEMPLATE operator_name '<' template_arg_list_opt
+ | TEMPLATE operator_name '<' template_arg_list_opt
template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
;
@@ -1566,7 +1582,7 @@ notype_template_declarator:
| NSNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
;
-
+
direct_notype_declarator:
complex_direct_notype_declarator
/* This precedence declaration is to prefer this reduce
@@ -1582,15 +1598,15 @@ primary:
{
if (TREE_CODE ($1) == BIT_NOT_EXPR)
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0));
- else
+ else
$$ = finish_id_expr ($1);
- }
+ }
| CONSTANT
- | boolean.literal
- | string
+ | boolean_literal
+ | STRING
{
- $$ = combine_strings ($$);
- /* combine_strings doesn't set up TYPE_MAIN_VARIANT of
+ $$ = fix_string_type ($$);
+ /* fix_string_type 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
@@ -1598,11 +1614,7 @@ primary:
TYPE_DOMAIN (TREE_TYPE ($$)));
}
| VAR_FUNC_NAME
- {
- $$ = fname_decl (C_RID_CODE ($$), $$);
- if (processing_template_decl)
- $$ = build_min_nt (LOOKUP_EXPR, DECL_NAME ($$));
- }
+ { $$ = finish_fname ($1); }
| '(' expr ')'
{ $$ = finish_parenthesized_expr ($2); }
| '(' expr_or_declarator_intern ')'
@@ -1611,15 +1623,14 @@ primary:
| '(' error ')'
{ $$ = error_mark_node; }
| '('
- { tree scope = current_scope ();
- if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
+ { if (!at_function_scope_p ())
{
error ("braced-group within expression allowed only inside a function");
YYERROR;
}
if (pedantic)
- pedwarn ("ISO C++ forbids braced-groups within expressions");
- $<ttype>$ = begin_stmt_expr ();
+ pedwarn ("ISO C++ forbids braced-groups within expressions");
+ $<ttype>$ = begin_stmt_expr ();
}
compstmt_or_stmtexpr ')'
{ $$ = finish_stmt_expr ($<ttype>2); }
@@ -1627,13 +1638,13 @@ primary:
We could store lastiddecl in $1 to avoid another lookup,
but that would result in many additional reduce/reduce conflicts. */
| notype_unqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_call_expr ($1, $3, 1); }
+ { $$ = parse_finish_call_expr ($1, $3, 1); }
| notype_unqualified_id LEFT_RIGHT
- { $$ = finish_call_expr ($1, NULL_TREE, 1); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
- { $$ = finish_call_expr ($1, $3, 0); }
+ { $$ = parse_finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
- { $$ = finish_call_expr ($1, NULL_TREE, 0); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| VA_ARG '(' expr_no_commas ',' type_id ')'
{ $$ = build_x_va_arg ($3, groktypename ($5.t));
check_for_new_type ("__builtin_va_arg", $5); }
@@ -1681,38 +1692,33 @@ primary:
check_for_new_type ("typeid", $3);
$$ = get_typeid (type); }
| global_scope IDENTIFIER
- { $$ = do_scoped_id ($2, 1); }
+ { $$ = parse_scoped_id ($2); }
| global_scope template_id
{ $$ = $2; }
| global_scope operator_name
{
got_scope = NULL_TREE;
if (TREE_CODE ($2) == IDENTIFIER_NODE)
- $$ = do_scoped_id ($2, 1);
+ $$ = parse_scoped_id ($2);
else
$$ = $2;
}
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_qualified_call_expr ($1, $3); }
+ { $$ = parse_finish_call_expr ($1, $3, 0); }
| overqualified_id LEFT_RIGHT
- { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| object object_template_id %prec UNARY
- {
- $$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
- }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object object_template_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object object_template_id LEFT_RIGHT
{ $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
| object unqualified_id %prec UNARY
- { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object overqualified_id %prec UNARY
- { if (processing_template_decl)
- $$ = build_min_nt (COMPONENT_REF, $1, $2);
- else
- $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+ { $$ = finish_class_member_access_expr ($1, $2); }
| object unqualified_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object unqualified_id LEFT_RIGHT
@@ -1784,20 +1790,13 @@ delete:
{ got_scope = NULL_TREE; $$ = 1; }
;
-boolean.literal:
+boolean_literal:
CXX_TRUE
{ $$ = boolean_true_node; }
| CXX_FALSE
{ $$ = boolean_false_node; }
;
-/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
-string:
- STRING
- | string STRING
- { $$ = chainon ($$, $2); }
- ;
-
nodecls:
/* empty */
{
@@ -1811,7 +1810,7 @@ object:
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT
{
- $$ = build_x_arrow ($$);
+ $$ = build_x_arrow ($$);
got_object = TREE_TYPE ($$);
}
;
@@ -1860,20 +1859,20 @@ fcast_or_absdcl:
/* ISO type-id (8.1) */
type_id:
typed_typespecs absdcl
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers absdcl
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
{ $$.t = build_tree_list (build_tree_list (NULL_TREE, $1.t),
- $2);
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_typespecs %prec EMPTY
{ $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -1891,23 +1890,23 @@ typed_declspecs:
typed_declspecs1:
declmods typespec
- { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
+ { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_declspecs %prec HYPERUNARY
- { $$.t = tree_cons (NULL_TREE, $1.t, $2);
+ { $$.t = tree_cons (NULL_TREE, $1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec reserved_typespecquals reserved_declspecs
- { $$.t = tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
+ { $$.t = tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
$$.new_type_flag = $1.new_type_flag; }
| declmods typespec reserved_declspecs
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals reserved_declspecs
{ $$.t = tree_cons (NULL_TREE, $2.t,
- chainon ($3, chainon ($4, $1.t)));
+ chainon ($3, chainon ($4, $1.t)));
$$.new_type_flag = $2.new_type_flag; }
;
@@ -1973,16 +1972,16 @@ declmods:
typed_typespecs:
typespec %prec EMPTY
- { $$.t = build_tree_list (NULL_TREE, $1.t);
+ { $$.t = build_tree_list (NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec
- { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
+ { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $1.t, $2);
+ { $$.t = tree_cons (NULL_TREE, $1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
;
@@ -2091,8 +2090,8 @@ nomods_initdecls:
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
- | asm_keyword '(' string ')'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; }
+ | asm_keyword '(' STRING ')'
+ { $$ = $3; }
;
initdcl:
@@ -2119,7 +2118,7 @@ initdcl0_innards:
{ $<ttype>$ = parse_decl0 ($<ttype>-1, $<ftype>-2.t,
$<ftype>-2.lookups, $1, 1); }
/* Note how the declaration of the variable is in effect
- while its init is parsed! */
+ while its init is parsed! */
init
{ parse_end_decl ($<ttype>3, $4, $<ttype>0); }
| maybe_attribute
@@ -2127,7 +2126,7 @@ initdcl0_innards:
$<ftype>-2.lookups, $1, 0);
parse_end_decl (d, NULL_TREE, $<ttype>0); }
;
-
+
initdcl0:
declarator maybeasm initdcl0_innards
{}
@@ -2137,15 +2136,15 @@ notype_initdcl0:
notype_declarator maybeasm initdcl0_innards
{}
;
-
+
nomods_initdcl0:
notype_declarator maybeasm
{ /* Set things up as initdcl0_innards expects. */
$<ttype>$ = $2;
- $2 = $1;
+ $2 = $1;
$<ftype>1.t = NULL_TREE;
$<ftype>1.lookups = NULL_TREE; }
- initdcl0_innards
+ initdcl0_innards
{}
| constructor_declarator maybeasm maybe_attribute
{ tree d = parse_decl0 ($1, NULL_TREE, NULL_TREE, $3, 0);
@@ -2160,7 +2159,7 @@ maybe_attribute:
| attributes
{ $$ = $1; }
;
-
+
attributes:
attribute
{ $$ = $1; }
@@ -2179,7 +2178,7 @@ attribute_list:
| attribute_list ',' attrib
{ $$ = chainon ($1, $3); }
;
-
+
attrib:
/* empty */
{ $$ = NULL_TREE; }
@@ -2259,13 +2258,13 @@ pending_inline:
process_next_inline ($1);
}
| PRE_PARSED_FUNCTION_DECL maybe_return_init function_try_block
- {
- expand_body (finish_function (2));
+ {
+ expand_body (finish_function (2));
process_next_inline ($1);
}
| PRE_PARSED_FUNCTION_DECL maybe_return_init error
- {
- finish_function (2);
+ {
+ finish_function (2);
process_next_inline ($1); }
;
@@ -2311,14 +2310,14 @@ structsp:
current_enum_type = $<ttype>3;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
- { $$.t = xref_tag (enum_type_node, $2, 1);
+ { $$.t = parse_xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| ENUM complex_type_name
- { $$.t = xref_tag (enum_type_node, $2, 1);
+ { $$.t = parse_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)
pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
@@ -2327,20 +2326,28 @@ structsp:
if ($2 && $1.t != error_mark_node)
{
tree type = TREE_TYPE ($1.t);
-
+
if (TREE_CODE (type) == TYPENAME_TYPE)
- /* In a definition of a member class template,
- we will get here with an implicit typename,
- a TYPENAME_TYPE with a type. */
- type = TREE_TYPE (type);
+ {
+ if (IMPLICIT_TYPENAME_P (type))
+ /* In a definition of a member class template,
+ we will get here with an implicit typename,
+ a TYPENAME_TYPE with a type. */
+ type = TREE_TYPE (type);
+ else
+ {
+ error ("qualified name does not name a class");
+ type = error_mark_node;
+ }
+ }
maybe_process_partial_specialization (type);
- xref_basetypes (current_aggr, $1.t, type, $2);
+ xref_basetypes (type, $2);
}
- $1.t = begin_class_definition (TREE_TYPE ($1.t));
+ $1.t = begin_class_definition (TREE_TYPE ($1.t));
check_class_key (current_aggr, $1.t);
current_aggr = NULL_TREE; }
opt.component_decl_list '}' maybe_attribute
- {
+ {
int semi;
tree t;
@@ -2364,9 +2371,8 @@ structsp:
}
pending_inlines
{
- finish_inline_definitions ();
$$.t = $<ttype>8;
- $$.new_type_flag = 1;
+ $$.new_type_flag = 1;
}
| class_head_decl
{
@@ -2427,18 +2433,18 @@ class_head:
class_head_apparent_template:
aggr apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $2;
}
| aggr nested_name_specifier apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $3;
}
| aggr global_scope nested_name_specifier apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $4;
}
;
@@ -2446,14 +2452,15 @@ class_head_apparent_template:
class_head_decl:
class_head %prec EMPTY
{
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 0, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 0, &$$.new_type_flag);
}
| aggr identifier_defn %prec EMPTY
{
current_aggr = $1;
- $$.t = TYPE_MAIN_DECL (xref_tag (current_aggr, $2, 0));
+ $$.t = TYPE_MAIN_DECL (parse_xref_tag (current_aggr, $2, 0));
$$.new_type_flag = 1;
}
| class_head_apparent_template %prec EMPTY
@@ -2467,59 +2474,54 @@ class_head_defn:
class_head '{'
{
yyungetc ('{', 1);
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 1,
+ &$$.new_type_flag);
}
| class_head ':'
{
yyungetc (':', 1);
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 1, &$$.new_type_flag);
}
| class_head_apparent_template '{'
{
yyungetc ('{', 1);
- $$.t = $1;
- $$.new_type_flag = 0;
- if (TREE_CODE (TREE_TYPE ($1)) == RECORD_TYPE)
- /* We might be specializing a template with a different
- class-key. */
- CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($1))
- = (current_aggr == class_type_node);
+ $$.t = handle_class_head_apparent_template
+ ($1, &$$.new_type_flag);
}
| class_head_apparent_template ':'
{
yyungetc (':', 1);
- $$.t = $1;
- $$.new_type_flag = 0;
- if (TREE_CODE (TREE_TYPE ($1)) == RECORD_TYPE)
- /* We might be specializing a template with a different
- class-key. */
- CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($1))
- = (current_aggr == class_type_node);
+ $$.t = handle_class_head_apparent_template
+ ($1, &$$.new_type_flag);
}
| aggr identifier_defn '{'
{
yyungetc ('{', 1);
current_aggr = $1;
- $$.t = handle_class_head (current_aggr,
- NULL_TREE, $2,
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ NULL_TREE, $2,
+ 1, &$$.new_type_flag);
}
| aggr identifier_defn ':'
{
yyungetc (':', 1);
current_aggr = $1;
- $$.t = handle_class_head (current_aggr,
- NULL_TREE, $2,
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ NULL_TREE, $2,
+ 1, &$$.new_type_flag);
}
| aggr '{'
{
current_aggr = $1;
- $$.t = TYPE_MAIN_DECL (xref_tag ($1, make_anon_name (), 0));
+ $$.t = TYPE_MAIN_DECL (parse_xref_tag ($1,
+ make_anon_name (),
+ 0));
$$.new_type_flag = 0;
CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($$.t))
= $1 == class_type_node;
@@ -2544,13 +2546,13 @@ base_class_list:
;
base_class:
- base_class.1
+ base_class_1
{ $$ = finish_base_specifier (access_default_node, $1); }
- | base_class_access_list see_typename base_class.1
+ | base_class_access_list see_typename base_class_1
{ $$ = finish_base_specifier ($1, $3); }
;
-base_class.1:
+base_class_1:
typename_sub
{ if (!TYPE_P ($$))
$$ = error_mark_node; }
@@ -2592,7 +2594,7 @@ base_class_access_list:
opt.component_decl_list:
| component_decl_list
| opt.component_decl_list access_specifier component_decl_list
- | opt.component_decl_list access_specifier
+ | opt.component_decl_list access_specifier
;
access_specifier:
@@ -2606,13 +2608,13 @@ access_specifier:
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
- {
+ {
finish_member_declaration ($1);
current_aggr = NULL_TREE;
reset_type_access_control ();
}
| component_decl_list component_decl
- {
+ {
finish_member_declaration ($2);
current_aggr = NULL_TREE;
reset_type_access_control ();
@@ -2626,13 +2628,13 @@ component_decl:
yyungetc ('}', 0); }
/* C++: handle constructors, destructors and inline functions */
/* note that INLINE is like a TYPESPEC */
- | fn.def2 ':' /* base_init compstmt */
+ | fn_def2 ':' /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 TRY /* base_init compstmt */
+ | fn_def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 RETURN_KEYWORD /* base_init compstmt */
+ | fn_def2 RETURN_KEYWORD /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 '{' /* nodecls compstmt */
+ | fn_def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); }
| ';'
{ $$ = NULL_TREE; }
@@ -2640,7 +2642,7 @@ component_decl:
{ $$ = $2;
pedantic = $1; }
| template_header component_decl
- {
+ {
if ($2)
$$ = finish_member_template_decl ($2);
else
@@ -2650,8 +2652,8 @@ component_decl:
finish_template_decl ($1);
}
| template_header typed_declspecs ';'
- {
- $$ = finish_member_class_template ($2.t);
+ {
+ $$ = finish_member_class_template ($2.t);
finish_template_decl ($1);
}
| bad_decl
@@ -2684,10 +2686,10 @@ component_decl_1:
$$ = NULL_TREE;
}
| declmods notype_components
- {
+ {
if (!$2)
grok_x_components ($1.t);
- $$ = NULL_TREE;
+ $$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
@@ -2723,14 +2725,14 @@ components:
/* empty: possibly anonymous */
{ $$ = 0; }
| component_declarator0
- {
+ {
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$1 = finish_member_template_decl ($1);
- finish_member_declaration ($1);
+ finish_member_declaration ($1);
$$ = 1;
}
| components ',' component_declarator
- {
+ {
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
@@ -2743,18 +2745,18 @@ notype_components:
/* empty: possibly anonymous */
{ $$ = 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
- {
+ {
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
- finish_member_declaration ($3);
+ finish_member_declaration ($3);
$$ = 2;
}
;
@@ -2833,10 +2835,10 @@ enumerator:
/* ISO new-type-id (5.3.4) */
new_type_id:
type_specifier_seq new_declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| type_specifier_seq %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
/* GNU extension to allow arrays of arbitrary types with
non-constant dimension. */
@@ -2862,13 +2864,13 @@ nonempty_cv_qualifiers:
{ $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
- { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
+ { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| attributes %prec EMPTY
- { $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
+ { $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers attributes %prec EMPTY
- { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t);
+ { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -2977,7 +2979,7 @@ notype_declarator_intern:
$$ = tree_cons ($1, $2, NULL_TREE);
}
;
-
+
notype_declarator:
'*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
@@ -3025,7 +3027,7 @@ complex_direct_notype_declarator:
{ enter_scope_of ($2); $$ = $2;}
| global_scope notype_unqualified_id
{ $$ = build_nt (SCOPE_REF, global_namespace, $2);
- enter_scope_of ($$);
+ enter_scope_of ($$);
}
| nested_name_specifier notype_template_declarator
{ got_scope = NULL_TREE;
@@ -3078,15 +3080,15 @@ nested_name_specifier:
| nested_name_specifier nested_name_specifier_1
{ $$ = $2; }
| nested_name_specifier TEMPLATE explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $3, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $3, tf_error | tf_parsing); }
/* Error handling per Core 125. */
| nested_name_specifier IDENTIFIER SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| nested_name_specifier PTYPENAME SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
;
/* Why the @#$%^& do type_name and notype_identifier need to be expanded
@@ -3128,7 +3130,7 @@ typename_sub0:
typename_sub1 identifier %prec EMPTY
{
if (TYPE_P ($1))
- $$ = make_typename_type ($1, $2, tf_error);
+ $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2);
else
@@ -3141,9 +3143,9 @@ typename_sub0:
| typename_sub1 template_type %prec EMPTY
{ $$ = TREE_TYPE ($2); }
| typename_sub1 explicit_template_type %prec EMPTY
- { $$ = make_typename_type ($1, $2, tf_error); }
+ { $$ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
- { $$ = make_typename_type ($1, $3, tf_error); }
+ { $$ = make_typename_type ($1, $3, tf_error | tf_parsing); }
;
typename_sub1:
@@ -3157,7 +3159,7 @@ typename_sub1:
| typename_sub1 typename_sub2
{
if (TYPE_P ($1))
- $$ = make_typename_type ($1, $2, tf_error);
+ $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2);
else
@@ -3168,11 +3170,11 @@ typename_sub1:
}
}
| typename_sub1 explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $3, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $3, tf_error | tf_parsing); }
;
/* This needs to return a TYPE_DECL for simple names so that we don't
@@ -3279,7 +3281,7 @@ absdcl_intern:
$$ = tree_cons ($1, $2, NULL_TREE);
}
;
-
+
/* ISO abstract-declarator (8.1) */
absdcl:
'*' nonempty_cv_qualifiers absdcl_intern
@@ -3365,7 +3367,7 @@ label_decls:
label_decl:
LABEL identifiers_or_typenames ';'
- {
+ {
while ($2)
{
finish_label_decl (TREE_VALUE ($2));
@@ -3377,7 +3379,7 @@ label_decl:
compstmt_or_stmtexpr:
save_lineno '{'
{ $<ttype>$ = begin_compound_stmt (0); }
- compstmtend
+ compstmtend
{ STMT_LINENO ($<ttype>3) = $1;
finish_compound_stmt (0, $<ttype>3); }
;
@@ -3400,9 +3402,9 @@ simple_if:
implicitly_scoped_stmt:
compstmt
- |
+ |
{ $<ttype>$ = begin_compound_stmt (0); }
- save_lineno simple_stmt
+ save_lineno simple_stmt
{ STMT_LINENO ($<ttype>1) = $2;
if ($3) STMT_LINENO ($3) = $2;
finish_compound_stmt (0, $<ttype>1); }
@@ -3423,9 +3425,9 @@ simple_stmt:
| simple_if ELSE
{ begin_else_clause (); }
implicitly_scoped_stmt
- {
+ {
$$ = $1;
- finish_else_clause ($1);
+ finish_else_clause ($1);
finish_if_stmt ();
}
| simple_if %prec IF
@@ -3462,7 +3464,7 @@ simple_stmt:
implicitly_scoped_stmt
{ $$ = $<ttype>2;
finish_for_stmt ($<ttype>2); }
- | SWITCH
+ | SWITCH
{ $<ttype>$ = begin_switch_stmt (); }
'(' condition ')'
{ finish_switch_cond ($4, $<ttype>2); }
@@ -3489,31 +3491,31 @@ simple_stmt:
{ $$ = finish_return_stmt (NULL_TREE); }
| RETURN_KEYWORD expr ';'
{ $$ = finish_return_stmt ($2); }
- | asm_keyword maybe_cv_qualifier '(' string ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
NULL_TREE);
ASM_INPUT_P ($$) = 1; }
/* This is the case with just output operands. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
/* This is the case with input operands as well. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ':'
asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
- | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING SCOPE asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, NULL_TREE); }
/* This is the case with clobbered registers as well. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, $8, $10); }
- | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING SCOPE asm_operands ':'
asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, $8); }
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands SCOPE
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands SCOPE
asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
| GOTO '*' expr ';'
- {
+ {
if (pedantic)
pedwarn ("ISO C++ forbids computed gotos");
$$ = finish_goto_stmt ($3);
@@ -3604,7 +3606,7 @@ handler_args:
expand_start_catch_block ($2.t, $3); }
This allows reference parameters... */
| '(' parm ')'
- {
+ {
check_for_new_type ("inside exception declarations", $2);
$$ = start_handler_parms (TREE_PURPOSE ($2.t),
TREE_VALUE ($2.t));
@@ -3666,14 +3668,16 @@ asm_operand:
STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
- { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+ { $2 = build_string (IDENTIFIER_LENGTH ($2),
+ IDENTIFIER_POINTER ($2));
+ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
asm_clobbers:
- string
- { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE);}
- | asm_clobbers ',' string
- { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+ STRING
+ { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);}
+ | asm_clobbers ',' STRING
+ { $$ = tree_cons (NULL_TREE, $3, $1); }
;
/* This is what appears inside the parens in a function declarator.
@@ -3705,7 +3709,7 @@ complex_parmlist:
{ $$ = finish_parmlist ($1, 1); }
| type_id ELLIPSIS
{ $$ = finish_parmlist (build_tree_list (NULL_TREE,
- $1.t), 1); }
+ $1.t), 1); }
| ELLIPSIS
{ $$ = finish_parmlist (NULL_TREE, 1); }
| parms ':'
@@ -3725,7 +3729,7 @@ complex_parmlist:
parenthesis. */
yyerror ("possibly missing ')'");
$$ = finish_parmlist (build_tree_list (NULL_TREE,
- $1.t), 0);
+ $1.t), 0);
yyungetc (':', 0);
yychar = ')';
}
@@ -3777,20 +3781,20 @@ named_parm:
{ $$.new_type_flag = $1.new_type_flag;
$$.t = build_tree_list ($1.t, $2); }
| typed_typespecs declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec declarator
{ $$.t = build_tree_list (build_tree_list (NULL_TREE, $1.t),
- $2);
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
{ $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = 0; }
;
@@ -3912,6 +3916,7 @@ unoperator:
got_object = TREE_VALUE (saved_scopes);
looking_for_typename = TREE_LANG_FLAG_0 (saved_scopes);
saved_scopes = TREE_CHAIN (saved_scopes);
+ $$ = got_scope;
}
;
@@ -3983,7 +3988,7 @@ operator_name:
| operator DELETE '[' ']' unoperator
{ $$ = frob_opname (ansi_opname (VEC_DELETE_EXPR)); }
| operator type_specifier_seq conversion_declarator unoperator
- { $$ = frob_opname (grokoptypename ($2.t, $3)); }
+ { $$ = frob_opname (grokoptypename ($2.t, $3, $4)); }
| operator error unoperator
{ $$ = frob_opname (ansi_opname (ERROR_MARK)); }
;
@@ -4005,5 +4010,211 @@ debug_yytranslate (value)
{
return yytname[YYTRANSLATE (value)];
}
-
#endif
+
+/* Free malloced parser stacks if necessary. */
+
+void
+free_parser_stacks ()
+{
+ if (malloced_yyss)
+ {
+ free (malloced_yyss);
+ free (malloced_yyvs);
+ }
+}
+
+/* Return the value corresponding to TOKEN in the global scope. */
+
+static tree
+parse_scoped_id (token)
+ tree token;
+{
+ cxx_binding binding;
+
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (token, global_namespace, &binding, 0))
+ binding.value = NULL;
+ if (yychar == YYEMPTY)
+ yychar = yylex();
+
+ return do_scoped_id (token, binding.value);
+}
+
+/* AGGR may be either a type node (like class_type_node) or a
+ TREE_LIST whose TREE_PURPOSE is a list of attributes and whose
+ TREE_VALUE is a type node. Set *TAG_KIND and *ATTRIBUTES to
+ represent the information encoded. */
+
+static void
+parse_split_aggr (tree aggr, enum tag_types *tag_kind, tree *attributes)
+{
+ if (TREE_CODE (aggr) == TREE_LIST)
+ {
+ *attributes = TREE_PURPOSE (aggr);
+ aggr = TREE_VALUE (aggr);
+ }
+ else
+ *attributes = NULL_TREE;
+ *tag_kind = (enum tag_types) tree_low_cst (aggr, 1);
+}
+
+/* Like xref_tag, except that the AGGR may be either a type node (like
+ class_type_node) or a TREE_LIST whose TREE_PURPOSE is a list of
+ attributes and whose TREE_VALUE is a type node. */
+
+static tree
+parse_xref_tag (tree aggr, tree name, int globalize)
+{
+ tree attributes;
+ enum tag_types tag_kind;
+ parse_split_aggr (aggr, &tag_kind, &attributes);
+ return xref_tag (tag_kind, name, attributes, globalize);
+}
+
+/* Like handle_class_head, but AGGR may be as for parse_xref_tag. */
+
+static tree
+parse_handle_class_head (tree aggr, tree scope, tree id,
+ int defn_p, int *new_type_p)
+{
+ tree attributes;
+ enum tag_types tag_kind;
+ parse_split_aggr (aggr, &tag_kind, &attributes);
+ return handle_class_head (tag_kind, scope, id, attributes,
+ defn_p, new_type_p);
+}
+
+/* Like do_decl_instantiation, but the declarator has not yet been
+ parsed. */
+
+static void
+parse_decl_instantiation (tree declspecs, tree declarator, tree storage)
+{
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
+ do_decl_instantiation (decl, storage);
+}
+
+/* Like begin_function_definition, but SPECS_ATTRS is a combined list
+ containing both a decl-specifier-seq and attributes. */
+
+static int
+parse_begin_function_definition (tree specs_attrs, tree declarator)
+{
+ tree specs;
+ tree attrs;
+
+ split_specs_attrs (specs_attrs, &specs, &attrs);
+ return begin_function_definition (specs, attrs, declarator);
+}
+
+/* Like finish_call_expr, but the name for FN has not yet been
+ resolved. */
+
+static tree
+parse_finish_call_expr (tree fn, tree args, int koenig)
+{
+ bool disallow_virtual;
+
+ if (TREE_CODE (fn) == OFFSET_REF)
+ return build_offset_ref_call_from_tree (fn, args);
+
+ if (TREE_CODE (fn) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (fn, 0);
+ tree name = TREE_OPERAND (fn, 1);
+
+ if (scope == error_mark_node || name == error_mark_node)
+ return error_mark_node;
+ if (!processing_template_decl)
+ fn = resolve_scoped_fn_name (scope, name);
+ disallow_virtual = true;
+ }
+ else
+ disallow_virtual = false;
+
+ if (koenig && TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ tree f;
+
+ /* Do the Koenig lookup. */
+ fn = do_identifier (fn, 2, args);
+ /* If name lookup didn't find any matching declarations, we've
+ got an unbound identifier. */
+ if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ /* For some reason, do_identifier does not resolve
+ conversion operator names if the only matches would be
+ template conversion operators. So, we do it here. */
+ if (IDENTIFIER_TYPENAME_P (fn) && current_class_type)
+ {
+ f = lookup_member (current_class_type, fn,
+ /*protect=*/1, /*want_type=*/0);
+ if (f)
+ return finish_call_expr (f, args,
+ /*disallow_virtual=*/false);
+ }
+ /* If the name still could not be resolved, then the program
+ is ill-formed. */
+ if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ unqualified_name_lookup_error (fn);
+ return error_mark_node;
+ }
+ }
+ else if (TREE_CODE (fn) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (fn)
+ || TREE_CODE (fn) == OVERLOAD)
+ {
+ tree scope = DECL_CONTEXT (get_first_fn (fn));
+ if (scope && TYPE_P (scope))
+ {
+ tree access_scope;
+
+ if (DERIVED_FROM_P (scope, current_class_type)
+ && current_class_ref)
+ {
+ fn = build_baselink (lookup_base (current_class_type,
+ scope,
+ ba_any,
+ NULL),
+ TYPE_BINFO (current_class_type),
+ fn,
+ /*optype=*/NULL_TREE);
+ return finish_object_call_expr (fn,
+ current_class_ref,
+ args);
+ }
+
+
+ access_scope = current_class_type;
+ while (!DERIVED_FROM_P (scope, access_scope))
+ {
+ access_scope = TYPE_CONTEXT (access_scope);
+ while (DECL_P (access_scope))
+ access_scope = DECL_CONTEXT (access_scope);
+ }
+
+ fn = build_baselink (NULL_TREE,
+ TYPE_BINFO (access_scope),
+ fn,
+ /*optype=*/NULL_TREE);
+ }
+ }
+ }
+
+ if (TREE_CODE (fn) == COMPONENT_REF)
+ /* If the parser sees `(x->y)(bar)' we get here because the
+ parentheses confuse the parser. Treat this like
+ `x->y(bar)'. */
+ return finish_object_call_expr (TREE_OPERAND (fn, 1),
+ TREE_OPERAND (fn, 0),
+ args);
+
+ if (processing_template_decl)
+ return build_nt (CALL_EXPR, fn, args, NULL_TREE);
+
+ return build_call_from_tree (fn, args, disallow_virtual);
+}
+
+#include "gt-cp-parse.h"
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index b751ad4..22f93bf 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -47,35 +47,32 @@ Boston, MA 02111-1307, USA. */
returning an int. */
typedef int (*tree_fn_t) PARAMS ((tree, void*));
-extern struct obstack permanent_obstack;
-
/* 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
+ the instantiate request occurred; the TREE_VALUE is 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 GTY(()) tree pending_templates;
static tree last_pending_template;
int processing_template_parmlist;
static int template_header_count;
-static tree saved_trees;
-static varray_type inline_parm_levels;
+static GTY(()) tree saved_trees;
+static GTY(()) varray_type inline_parm_levels;
static size_t inline_parm_levels_used;
-static tree current_tinst_level;
+static GTY(()) tree current_tinst_level;
+
+static GTY(()) tree saved_access_scope;
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
static htab_t local_specializations;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
#define UNIFY_ALLOW_NONE 0
#define UNIFY_ALLOW_MORE_CV_QUAL 1
#define UNIFY_ALLOW_LESS_CV_QUAL 2
@@ -92,6 +89,9 @@ static htab_t local_specializations;
#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
type with the desired type. */
+static void push_access_scope_real PARAMS ((tree, tree, tree));
+static void push_access_scope PARAMS ((tree));
+static void pop_access_scope PARAMS ((tree));
static int resolve_overloaded_unification PARAMS ((tree, tree, tree, tree,
unification_kind_t, int));
static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
@@ -120,7 +120,7 @@ static tree convert_nontype_argument PARAMS ((tree, tree));
static tree convert_template_argument PARAMS ((tree, tree, tree,
tsubst_flags_t, int, tree));
static tree get_bindings_overload PARAMS ((tree, tree, tree));
-static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*));
+static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*, htab_t));
static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
static int inline_needs_template_parms PARAMS ((tree));
static void push_inline_template_parms_recursive PARAMS ((tree, int));
@@ -132,6 +132,7 @@ static int unregister_specialization PARAMS ((tree, tree));
static tree reduce_template_parm_level PARAMS ((tree, tree, int));
static tree build_template_decl PARAMS ((tree, tree));
static int mark_template_parm PARAMS ((tree, void *));
+static int template_parm_this_level_p PARAMS ((tree, void *));
static tree tsubst_friend_function PARAMS ((tree, tree));
static tree tsubst_friend_class PARAMS ((tree, tree));
static int can_complete_type_without_circularity PARAMS ((tree));
@@ -170,14 +171,85 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
-/* Called once to initialize pt.c. */
+/* Make the current scope suitable for access checking when we are
+ processing T. T can be FUNCTION_DECL for instantiated function
+ template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
+ static member variable (need by instantiate_decl). ARGS is the
+ template argument for TEMPLATE_DECL. If CONTEXT is not NULL_TREE,
+ this is used instead of the context of T. */
+
+void
+push_access_scope_real (t, args, context)
+ tree t, args, context;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* When we are processing specialization `foo<Outer>' for code like
+
+ template <class U> typename U::Inner foo ();
+ class Outer {
+ struct Inner {};
+ friend Outer::Inner foo<Outer> ();
+ };
+
+ `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
+ its specialization. We can get the FUNCTION_DECL with the right
+ information because this specialization has already been
+ registered by the friend declaration above. */
+
+ if (DECL_FUNCTION_TEMPLATE_P (t) && args)
+ {
+ tree full_args = tsubst_template_arg_vector
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
+ tree spec = NULL_TREE;
+ if (full_args != error_mark_node)
+ spec = retrieve_specialization (t, full_args);
+ if (spec)
+ t = spec;
+ }
+ }
+
+ if (!context)
+ context = DECL_CONTEXT (t);
+ if (context && TYPE_P (context))
+ push_nested_class (context, 2);
+ else
+ push_to_top_level ();
+
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ saved_access_scope = tree_cons
+ (NULL_TREE, current_function_decl, saved_access_scope);
+ current_function_decl = t;
+ }
+}
+
+/* Like push_access_scope_real, but always uses DECL_CONTEXT. */
+
+void
+push_access_scope (t)
+ tree t;
+{
+ push_access_scope_real (t, NULL_TREE, NULL_TREE);
+}
+
+/* Restore the scope set up by push_access_scope. T is the node we
+ are processing. */
void
-init_pt ()
+pop_access_scope (t)
+ tree t;
{
- ggc_add_tree_root (&pending_templates, 1);
- ggc_add_tree_root (&saved_trees, 1);
- ggc_add_tree_root (&current_tinst_level, 1);
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ current_function_decl = TREE_VALUE (saved_access_scope);
+ saved_access_scope = TREE_CHAIN (saved_access_scope);
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ pop_nested_class ();
+ else
+ pop_from_top_level ();
}
/* Do any processing required when DECL (a member template declaration
@@ -395,7 +467,7 @@ maybe_begin_member_template_processing (decl)
++inline_parm_levels_used;
}
-/* Undo the effects of begin_member_template_processing. */
+/* Undo the effects of begin_member_template_processing. */
void
maybe_end_member_template_processing ()
@@ -416,7 +488,7 @@ maybe_end_member_template_processing ()
}
}
-/* Returns non-zero iff T is a member template function. We must be
+/* Returns nonzero iff T is a member template function. We must be
careful as in
template <class T> class C { void f(); }
@@ -453,7 +525,7 @@ is_member_template (t)
}
#if 0 /* UNUSED */
-/* Returns non-zero iff T is a member template class. See
+/* Returns nonzero iff T is a member template class. See
is_member_template for a description of what precisely constitutes
a member template. */
@@ -599,7 +671,7 @@ begin_template_parm_list ()
}
/* This routine is called when a specialization is declared. If it is
- illegal to declare a specialization here, an error is reported. */
+ invalid to declare a specialization here, an error is reported. */
static void
check_specialization_scope ()
@@ -631,7 +703,7 @@ check_specialization_scope ()
error ("enclosing class templates are not explicitly specialized");
}
-/* We've just seen template <>. */
+/* We've just seen template <>. */
void
begin_specialization ()
@@ -652,7 +724,7 @@ end_specialization ()
}
/* Any template <>'s that we have seen thus far are not referring to a
- function specialization. */
+ function specialization. */
void
reset_specialization ()
@@ -661,7 +733,7 @@ reset_specialization ()
template_header_count = 0;
}
-/* We've just seen a template header. If SPECIALIZATION is non-zero,
+/* We've just seen a template header. If SPECIALIZATION is nonzero,
it was of the form template <>. */
static void
@@ -695,8 +767,22 @@ void
maybe_process_partial_specialization (type)
tree type;
{
- if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ /* TYPE maybe an ERROR_MARK_NODE. */
+ tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+
+ if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
+ /* This is for ordinary explicit specialization and partial
+ specialization of a template class such as:
+
+ template <> class C<int>;
+
+ or:
+
+ template <class T> class C<T*>;
+
+ Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
+
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
@@ -714,6 +800,62 @@ maybe_process_partial_specialization (type)
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of `%T' after instantiation", type);
}
+ else if (CLASS_TYPE_P (type)
+ && !CLASSTYPE_USE_TEMPLATE (type)
+ && CLASSTYPE_TEMPLATE_INFO (type)
+ && context && CLASS_TYPE_P (context)
+ && CLASSTYPE_TEMPLATE_INFO (context))
+ {
+ /* This is for an explicit specialization of member class
+ template according to [temp.expl.spec/18]:
+
+ template <> template <class U> class C<int>::D;
+
+ The context `C<int>' must be an implicit instantiation.
+ Otherwise this is just a member class template declared
+ earlier like:
+
+ template <> class C<int> { template <class U> class D; };
+ template <> template <class U> class C<int>::D;
+
+ In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ while in the second case, `C<int>::D' is a primary template
+ and `C<T>::D' may not exist. */
+
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+ && !COMPLETE_TYPE_P (type))
+ {
+ tree t;
+
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+
+ /* Check for invalid specialization after instantiation:
+
+ template <> template <> class C<int>::D<int>;
+ template <> template <class U> class C<int>::D; */
+
+ for (t = DECL_TEMPLATE_INSTANTIATIONS
+ (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) != type
+ && TYPE_CONTEXT (TREE_VALUE (t)) == context)
+ error ("specialization `%T' after instantiation `%T'",
+ type, TREE_VALUE (t));
+
+ /* Mark TYPE as a specialization. And as a result, we only
+ have one level of template argument for the innermost
+ class template. */
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ CLASSTYPE_TI_ARGS (type)
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ }
+ }
else if (processing_specialization)
error ("explicit specialization of non-template `%T'", type);
}
@@ -758,7 +900,7 @@ retrieve_local_specialization (tmpl)
return (tree) htab_find (local_specializations, tmpl);
}
-/* Returns non-zero iff DECL is a specialization of TMPL. */
+/* Returns nonzero iff DECL is a specialization of TMPL. */
int
is_specialization_of (decl, tmpl)
@@ -961,7 +1103,7 @@ print_candidates (fns)
NULL_TREE if none is available. In that case, the functions in
TEMPLATE_ID are non-members.
- If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a
+ If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a
specialization of a member template.
The template args (those explicitly specified and those deduced)
@@ -995,9 +1137,9 @@ determine_specialization (template_id, decl, targs_out,
if (fns == error_mark_node)
return error_mark_node;
- /* Check for baselinks. */
+ /* Check for baselinks. */
if (BASELINK_P (fns))
- fns = TREE_VALUE (fns);
+ fns = BASELINK_FUNCTIONS (fns);
if (!is_overloaded_fn (fns))
{
@@ -1007,28 +1149,58 @@ determine_specialization (template_id, decl, targs_out,
for (; fns; fns = OVL_NEXT (fns))
{
- tree tmpl;
-
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- /* DECL might be a specialization of FN. */
- tmpl = fn;
+ {
+ tree decl_arg_types;
+
+ /* DECL might be a specialization of FN. */
+
+ /* 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);
+
+ /* Check that the number of function parameters matches.
+ For example,
+ template <class T> void f(int i = 0);
+ template <> void f<int>();
+ The specialization f<int> is invalid but is not caught
+ by get_bindings below. */
+
+ if (list_length (TYPE_ARG_TYPES (TREE_TYPE (fn)))
+ != list_length (decl_arg_types))
+ continue;
+
+ /* See whether this function might be a specialization of this
+ template. */
+ targs = get_bindings (fn, decl, explicit_targs);
+
+ if (!targs)
+ /* We cannot deduce template arguments that when used to
+ specialize TMPL will produce DECL. */
+ continue;
+
+ /* Save this template, and the arguments deduced. */
+ templates = tree_cons (targs, fn, templates);
+ }
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 if (DECL_ARTIFICIAL (fn))
/* Cannot specialize functions that are created implicitly. */
- continue;
+ ;
else
{
tree decl_arg_types;
@@ -1064,21 +1236,7 @@ determine_specialization (template_id, decl, targs_out,
decl_arg_types))
/* They match! */
candidates = tree_cons (NULL_TREE, fn, candidates);
-
- continue;
}
-
- /* 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;
-
- /* Save this template, and the arguments deduced. */
- templates = tree_cons (targs, tmpl, templates);
}
if (templates && TREE_CHAIN (templates))
@@ -1108,7 +1266,7 @@ determine_specialization (template_id, decl, targs_out,
template.
So, we do use the partial ordering rules, at least for now.
- This extension can only serve to make illegal programs legal,
+ This extension can only serve to make invalid programs valid,
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
@@ -1139,7 +1297,7 @@ determine_specialization (template_id, decl, targs_out,
return error_mark_node;
}
- /* We have one, and exactly one, match. */
+ /* We have one, and exactly one, match. */
if (candidates)
{
/* It was a specialization of an ordinary member function in a
@@ -1313,7 +1471,7 @@ copy_default_args_to_explicit_spec (decl)
template <> void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is
- illegal; there should be no template <>.)
+ invalid; there should be no template <>.)
If the function is a specialization, it is marked as such via
DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO
@@ -1414,7 +1572,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
template <class T> struct S { void f(); };
void S<int>::f() {} // Missing template <>
- That used to be legal C++. */
+ That used to be valid C++. */
if (pedantic)
pedwarn
("explicit specialization not preceded by `template <>'");
@@ -1496,13 +1654,13 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
{
if (!explicit_instantiation)
- /* A specialization in class scope. This is illegal,
+ /* A specialization in class scope. This is invalid,
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
+ /* It's not valid to write an explicit instantiation in
class scope, e.g.:
class C { template void f(); }
@@ -1512,7 +1670,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
template class C { void f(); };
- (which is illegal) we can get here. The error will be
+ (which is invalid) we can get here. The error will be
issued later. */
;
}
@@ -1538,8 +1696,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
tree fns = NULL_TREE;
int idx;
- if (name == constructor_name (ctype)
- || name == constructor_name_full (ctype))
+ if (constructor_name_p (name, ctype))
{
int is_constructor = DECL_CONSTRUCTOR_P (decl);
@@ -1580,7 +1737,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
- for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx)
+ for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ idx < TREE_VEC_LENGTH (methods); ++idx)
{
tree ovl = TREE_VEC_ELT (methods, idx);
@@ -1653,6 +1811,18 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return instantiate_template (tmpl, targs);
}
+ /* If we thought 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. We also have
+ to adjust last_function_parms to avoid confusing
+ start_function later. */
+ if (DECL_STATIC_FUNCTION_P (tmpl)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ revert_static_member_fn (decl);
+ last_function_parms = TREE_CHAIN (last_function_parms);
+ }
+
/* If this is a specialization of a member template of a
template class. In we want to return the TEMPLATE_DECL,
not the specialization of it. */
@@ -1663,16 +1833,6 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return tmpl;
}
- /* If we thought 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);
- last_function_parms = TREE_CHAIN (last_function_parms);
- }
-
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
@@ -1732,7 +1892,7 @@ maybe_check_template_type (type)
struct I {};
};
- is illegal, but:
+ is invalid, but:
template <class T> struct S {
template <class U> struct I;
@@ -2104,10 +2264,9 @@ build_template_decl (decl, parms)
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
if (DECL_LANG_SPECIFIC (decl))
{
- if (CAN_HAVE_FULL_LANG_DECL_P (decl))
- DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
+ DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_P (decl);
DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
if (DECL_OVERLOADED_OPERATOR_P (decl))
@@ -2129,12 +2288,12 @@ struct template_parm_data
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
+ elements are nonzero 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
+ elements are nonzero if the argument makes use of template
parameters of this level. */
int* arg_uses_template_parms;
};
@@ -2218,7 +2377,7 @@ process_partial_specialization (decl)
struct S2<T>;
};
- The S2<T> declaration is actually illegal; it is a
+ The S2<T> declaration is actually invalid; it is a
full-specialization. Of course,
template <class U>
@@ -2236,7 +2395,8 @@ process_partial_specialization (decl)
tpd.current_arg = i;
for_each_template_parm (TREE_VEC_ELT (inner_args, i),
&mark_template_parm,
- &tpd);
+ &tpd,
+ NULL);
}
for (i = 0; i < ntparms; ++i)
if (tpd.parms[i] == 0)
@@ -2317,7 +2477,8 @@ process_partial_specialization (decl)
memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
for_each_template_parm (type,
&mark_template_parm,
- &tpd2);
+ &tpd2,
+ NULL);
if (tpd2.arg_uses_template_parms [i])
{
@@ -2352,8 +2513,8 @@ process_partial_specialization (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. */
+ nonzero if DECL is the thing declared by a primary template.
+ IS_PARTIAL is nonzero if DECL is a partial specialization. */
static void
check_default_tmpl_args (decl, parms, is_primary, is_partial)
@@ -2457,7 +2618,7 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
/* 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:
+ on the other, default arguments are valid 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
@@ -2497,12 +2658,32 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
}
}
+/* Worker for push_template_decl_real, called via
+ for_each_template_parm. DATA is really an int, indicating the
+ level of the parameters we are interested in. If T is a template
+ parameter of that level, return nonzero. */
+
+static int
+template_parm_this_level_p (t, data)
+ tree t;
+ void *data;
+{
+ int this_level = *(int *)data;
+ int level;
+
+ if (TREE_CODE (t) == TEMPLATE_PARM_INDEX)
+ level = TEMPLATE_PARM_LEVEL (t);
+ else
+ level = TEMPLATE_TYPE_LEVEL (t);
+ return level == this_level;
+}
+
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
equivalent one, if it is replaced via a call to duplicate_decls.
- If IS_FRIEND is non-zero, DECL is a friend declaration. */
+ If IS_FRIEND is nonzero, DECL is a friend declaration. */
tree
push_template_decl_real (decl, is_friend)
@@ -2593,7 +2774,7 @@ push_template_decl_real (decl, is_friend)
{
/* Since a template declaration already existed for this
class-type, we must be redeclaring it here. Make sure
- that the redeclaration is legal. */
+ that the redeclaration is valid. */
redeclare_class_template (TREE_TYPE (decl),
current_template_parms);
/* We don't need to create a new TEMPLATE_DECL; just use the
@@ -2609,7 +2790,7 @@ push_template_decl_real (decl, is_friend)
&& DECL_TEMPLATE_SPECIALIZATION (decl))
{
/* A specialization of a member template of a template
- class. */
+ class. */
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
DECL_TEMPLATE_INFO (decl) = NULL_TREE;
@@ -2719,7 +2900,22 @@ push_template_decl_real (decl, is_friend)
tmpl = pushdecl_namespace_level (tmpl);
if (primary)
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ {
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ if (DECL_CONV_FN_P (tmpl))
+ {
+ int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+
+ /* It is a conversion operator. See if the type converted to
+ depends on innermost template operands. */
+
+ if (for_each_template_parm (TREE_TYPE (TREE_TYPE (tmpl)),
+ template_parm_this_level_p,
+ &depth,
+ NULL))
+ DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
+ }
+ }
info = tree_cons (tmpl, args, NULL_TREE);
@@ -2962,7 +3158,7 @@ convert_nontype_argument (type, expr)
case ENUMERAL_TYPE:
/* For a non-type template-parameter of integral or enumeration
type, integral promotions (_conv.prom_) and integral
- conversions (_conv.integral_) are applied. */
+ conversions (_conv.integral_) are applied. */
if (!INTEGRAL_TYPE_P (expr_type))
return error_mark_node;
@@ -3120,7 +3316,7 @@ convert_nontype_argument (type, expr)
return error_mark_node;
}
- mark_addressable (expr);
+ cxx_mark_addressable (expr);
return build1 (ADDR_EXPR, type, expr);
}
break;
@@ -3287,7 +3483,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
{
/* The template argument was the name of some
member function. That's usually
- illegal, but static members are OK. In any
+ invalid, but static members are OK. In any
case, grab the underlying fields/functions
and issue an error later if required. */
arg = TREE_VALUE (arg);
@@ -3458,7 +3654,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
extension, since deciding whether or not these
conversions can occur is part of determining which
function template to call, or whether a given explicit
- argument specification is legal. */
+ argument specification is valid. */
val = convert_nontype_argument (t, arg);
else
val = arg;
@@ -3480,7 +3676,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
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
+ If REQUIRE_ALL_ARGUMENTS is nonzero, 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. */
@@ -3781,9 +3977,9 @@ add_pending_template (d)
}
-/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which
- may be either a _DECL or an overloaded function or an
- IDENTIFIER_NODE), and ARGLIST. */
+/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS and
+ ARGLIST. Valid choices for FNS are given in the cp-tree.def
+ documentation for TEMPLATE_ID_EXPR. */
tree
lookup_template_function (fns, arglist)
@@ -3791,20 +3987,36 @@ lookup_template_function (fns, arglist)
{
tree type;
+ if (fns == error_mark_node || arglist == error_mark_node)
+ return error_mark_node;
+
if (fns == NULL_TREE)
{
error ("non-template used as template");
return error_mark_node;
}
+ my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE
+ || TREE_CODE (fns) == LOOKUP_EXPR,
+ 20020730);
+
+ if (BASELINK_P (fns))
+ {
+ BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
+ return fns;
+ }
+
type = TREE_TYPE (fns);
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
-
- if (processing_template_decl)
- return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
- else
- return build (TEMPLATE_ID_EXPR, type, fns, arglist);
+
+ return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
@@ -3837,7 +4049,7 @@ maybe_get_template_decl_from_type_decl (decl)
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
+ If ENTERING_SCOPE is nonzero, we are about to enter the scope of
the class we are looking up.
Issue error and warning messages under control of COMPLAIN.
@@ -3857,6 +4069,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
tree template = NULL_TREE, parmlist;
tree t;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
if (IDENTIFIER_VALUE (d1)
@@ -3912,7 +4125,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
{
if (complain & tf_error)
error ("`%T' is not a template", d1);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
@@ -3928,7 +4141,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
}
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
@@ -3963,10 +4176,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
- return parm;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
@@ -4053,7 +4266,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* In the scope of a template class, explicit references to the
template class refer to the type of the template, not any
@@ -4090,7 +4303,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
}
}
if (found)
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
*tp;
@@ -4106,7 +4319,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
= DECL_TEMPLATE_INSTANTIATIONS (template);
DECL_TEMPLATE_INSTANTIATIONS (template) = found;
- return TREE_VALUE (found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
}
/* This type is a "partial instantiation" if any of the template
@@ -4122,7 +4335,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
found = xref_tag_from_type (TREE_TYPE (template),
DECL_NAME (template),
/*globalize=*/1);
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
context = tsubst (DECL_CONTEXT (template), arglist,
@@ -4168,14 +4381,17 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
type_decl = create_implicit_typedef (DECL_NAME (template), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
- DECL_SOURCE_FILE (type_decl)
- = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
- DECL_SOURCE_LINE (type_decl)
- = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
+ DECL_SOURCE_LOCATION (type_decl)
+ = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
}
else
type_decl = TYPE_NAME (t);
+ TREE_PRIVATE (type_decl)
+ = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ TREE_PROTECTED (type_decl)
+ = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
instantiation. */
@@ -4275,14 +4491,16 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct pair_fn_data
{
tree_fn_t fn;
void *data;
+ htab_t visited;
};
/* Called from for_each_template_parm via walk_tree. */
@@ -4297,9 +4515,20 @@ for_each_template_parm_r (tp, walk_subtrees, d)
struct pair_fn_data *pfd = (struct pair_fn_data *) d;
tree_fn_t fn = pfd->fn;
void *data = pfd->data;
-
+ void **slot;
+
+ /* If we have already visited this tree, there's no need to walk
+ subtrees. Otherwise, add it to the visited table. */
+ slot = htab_find_slot (pfd->visited, *tp, INSERT);
+ if (*slot)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ *slot = *tp;
+
if (TYPE_P (t)
- && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
+ && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
return error_mark_node;
switch (TREE_CODE (t))
@@ -4314,20 +4543,21 @@ for_each_template_parm_r (tp, walk_subtrees, d)
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
- fn, data))
+ fn, data, pfd->visited))
return error_mark_node;
break;
case METHOD_TYPE:
/* Since we're not going to walk subtrees, we have to do this
explicitly here. */
- if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
+ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
+ pfd->visited))
return error_mark_node;
/* Fall through. */
case FUNCTION_TYPE:
/* Check the return type. */
- if (for_each_template_parm (TREE_TYPE (t), fn, data))
+ if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
return error_mark_node;
/* Check the parameter types. Since default arguments are not
@@ -4340,7 +4570,8 @@ for_each_template_parm_r (tp, walk_subtrees, d)
tree parm;
for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
- if (for_each_template_parm (TREE_VALUE (parm), fn, data))
+ if (for_each_template_parm (TREE_VALUE (parm), fn, data,
+ pfd->visited))
return error_mark_node;
/* Since we've already handled the TYPE_ARG_TYPES, we don't
@@ -4352,20 +4583,22 @@ for_each_template_parm_r (tp, walk_subtrees, d)
case FUNCTION_DECL:
case VAR_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
- && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
+ && for_each_template_parm (DECL_TI_ARGS (t), fn, data,
+ pfd->visited))
return error_mark_node;
/* Fall through. */
case CONST_DECL:
case PARM_DECL:
if (DECL_CONTEXT (t)
- && for_each_template_parm (DECL_CONTEXT (t), fn, data))
+ && for_each_template_parm (DECL_CONTEXT (t), fn, data,
+ pfd->visited))
return error_mark_node;
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
+ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited))
return error_mark_node;
/* Fall through. */
@@ -4381,7 +4614,7 @@ for_each_template_parm_r (tp, walk_subtrees, d)
case TEMPLATE_DECL:
/* A template template parameter is encountered */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && for_each_template_parm (TREE_TYPE (t), fn, data))
+ && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
return error_mark_node;
/* Already substituted template template parameter */
@@ -4389,14 +4622,17 @@ for_each_template_parm_r (tp, walk_subtrees, d)
break;
case TYPENAME_TYPE:
- if (!fn || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, data))
+ if (!fn
+ || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
+ data, pfd->visited))
return error_mark_node;
break;
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
&& for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
- (TREE_TYPE (t)), fn, data))
+ (TREE_TYPE (t)), fn, data,
+ pfd->visited))
return error_mark_node;
break;
@@ -4423,6 +4659,16 @@ for_each_template_parm_r (tp, walk_subtrees, d)
return error_mark_node;
break;
+ case BASELINK:
+ /* If we do not handle this case specially, we end up walking
+ the BINFO hierarchy, which is circular, and therefore
+ confuses walk_tree. */
+ *walk_subtrees = 0;
+ if (for_each_template_parm (BASELINK_FUNCTIONS (*tp), fn, data,
+ pfd->visited))
+ return error_mark_node;
+ break;
+
default:
break;
}
@@ -4434,19 +4680,21 @@ for_each_template_parm_r (tp, walk_subtrees, d)
/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
BOUND_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
+ If FN returns nonzero, the iteration is terminated, and
for_each_template_parm returns 1. Otherwise, the iteration
- continues. If FN never returns a non-zero value, the value
+ continues. If FN never returns a nonzero value, the value
returned by for_each_template_parm is 0. If FN is NULL, it is
considered to be the function which always returns 1. */
static int
-for_each_template_parm (t, fn, data)
+for_each_template_parm (t, fn, data, visited)
tree t;
tree_fn_t fn;
void* data;
+ htab_t visited;
{
struct pair_fn_data pfd;
+ int result;
/* Set up. */
pfd.fn = fn;
@@ -4455,18 +4703,30 @@ for_each_template_parm (t, fn, data)
/* Walk the tree. (Conceptually, we would like to walk without
duplicates, but for_each_template_parm_r recursively calls
for_each_template_parm, so we would need to reorganize a fair
- bit to use walk_tree_without_duplicates.) */
- return walk_tree (&t,
- for_each_template_parm_r,
- &pfd,
- NULL) != NULL_TREE;
+ bit to use walk_tree_without_duplicates, so we keep our own
+ visited list.) */
+ if (visited)
+ pfd.visited = visited;
+ else
+ pfd.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer,
+ NULL);
+ result = walk_tree (&t,
+ for_each_template_parm_r,
+ &pfd,
+ NULL) != NULL_TREE;
+
+ /* Clean up. */
+ if (!visited)
+ htab_delete (pfd.visited);
+
+ return result;
}
int
uses_template_parms (t)
tree t;
{
- return for_each_template_parm (t, 0, 0);
+ return for_each_template_parm (t, 0, 0, NULL);
}
static int tinst_depth;
@@ -4681,7 +4941,7 @@ tsubst_friend_function (decl, args)
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
- into the namespace of the template. */
+ into the namespace of the template. */
ns = decl_namespace_context (new_friend);
push_nested_namespace (ns);
old_decl = pushdecl_namespace_level (new_friend);
@@ -4912,7 +5172,7 @@ tree
instantiate_class_template (type)
tree type;
{
- tree template, args, pattern, t;
+ tree template, args, pattern, t, member;
tree typedecl;
if (type == error_mark_node)
@@ -5007,7 +5267,8 @@ instantiate_class_template (type)
TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
TYPE_METHODS (type) = TYPE_METHODS (pattern);
- CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
+ CLASSTYPE_NESTED_UDTS (type) = CLASSTYPE_NESTED_UDTS (pattern);
CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
/* Pretend that the type is complete, so that we will look
@@ -5028,7 +5289,7 @@ instantiate_class_template (type)
if (t)
{
- /* This TYPE is actually a instantiation of of a partial
+ /* This TYPE is actually an instantiation of a partial
specialization. We replace the innermost set of ARGS with
the arguments appropriate for substitution. For example,
given:
@@ -5101,6 +5362,10 @@ instantiate_class_template (type)
if (ANON_AGGR_TYPE_P (pattern))
SET_ANON_AGGR_TYPE_P (type);
+ if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern)))
+ /* First instantiate our enclosing class. */
+ complete_type (TYPE_CONTEXT (type));
+
if (TYPE_BINFO_BASETYPES (pattern))
{
tree base_list = NULL_TREE;
@@ -5150,13 +5415,7 @@ instantiate_class_template (type)
/* 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);
+ xref_basetypes (type, base_list);
}
/* Now that our base classes are set up, enter the scope of the
@@ -5166,175 +5425,170 @@ instantiate_class_template (type)
class. */
pushclass (type, 1);
- for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
+ /* Now members are processed in the order of declaration. */
+ for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
{
- tree tag = TREE_VALUE (t);
- tree name = TYPE_IDENTIFIER (tag);
- tree newtag;
+ tree t = TREE_VALUE (member);
- newtag = tsubst (tag, args, tf_error, NULL_TREE);
- my_friendly_assert (newtag != error_mark_node, 20010206);
- if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+ if (TREE_PURPOSE (member))
{
- 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);
- }
- }
-
- /* Don't replace enum constants here. */
- for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) != CONST_DECL)
- {
- tree r;
+ if (TYPE_P (t))
+ {
+ /* Build new CLASSTYPE_NESTED_UDTS. */
- /* 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);
+ tree tag = t;
+ tree name = TYPE_IDENTIFIER (tag);
+ tree newtag;
- r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
- if (TREE_CODE (r) == VAR_DECL)
- {
- tree init;
+ newtag = tsubst (tag, args, tf_error, NULL_TREE);
+ my_friendly_assert (newtag != error_mark_node, 20010206);
+ if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+ {
+ 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 if (TREE_CODE (t) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* Build new TYPE_METHODS. */
- if (DECL_INITIALIZED_IN_CLASS_P (r))
- init = tsubst_expr (DECL_INITIAL (t), args,
- tf_error | tf_warning, NULL_TREE);
- else
- init = NULL_TREE;
+ tree r = tsubst (t, args, tf_error, NULL_TREE);
+ set_current_access_from_decl (r);
+ grok_special_member_properties (r);
+ finish_member_declaration (r);
+ }
+ else
+ {
+ /* Build new TYPE_FIELDS. */
- finish_static_data_member_decl (r, init,
- /*asmspec_tree=*/NULL_TREE,
- /*flags=*/0);
+ if (TREE_CODE (t) != CONST_DECL)
+ {
+ tree r;
- if (DECL_INITIALIZED_IN_CLASS_P (r))
- check_static_variable_definition (r, TREE_TYPE (r));
- }
- else if (TREE_CODE (r) == FIELD_DECL)
- {
- /* Determine whether R has a valid type and can be
- completed later. If R is invalid, then it is replaced
- by error_mark_node so that it will not be added to
- TYPE_FIELDS. */
- tree rtype = TREE_TYPE (r);
- if (!can_complete_type_without_circularity (rtype))
- {
- incomplete_type_error (r, rtype);
- r = error_mark_node;
- }
- }
+ /* 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 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);
- }
- }
+ r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ if (TREE_CODE (r) == VAR_DECL)
+ {
+ tree init;
- /* 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, tf_error, NULL_TREE);
- set_current_access_from_decl (r);
- grok_special_member_properties (r);
- finish_member_declaration (r);
- }
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
+ init = tsubst_expr (DECL_INITIAL (t), args,
+ tf_error | tf_warning, NULL_TREE);
+ else
+ init = NULL_TREE;
- /* Construct the DECL_FRIENDLIST for the new class type. */
- typedecl = TYPE_MAIN_DECL (type);
- for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
- t != NULL_TREE;
- t = TREE_CHAIN (t))
- {
- tree friends;
-
- for (friends = TREE_VALUE (t);
- friends != NULL_TREE;
- friends = TREE_CHAIN (friends))
- if (TREE_PURPOSE (friends) == error_mark_node)
- add_friend (type,
- tsubst_friend_function (TREE_VALUE (friends),
- args));
- else
- abort ();
- }
+ finish_static_data_member_decl (r, init,
+ /*asmspec_tree=*/NULL_TREE,
+ /*flags=*/0);
- for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
- t != NULL_TREE;
- t = TREE_CHAIN (t))
- {
- tree friend_type = TREE_VALUE (t);
- tree new_friend_type;
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
+ check_static_variable_definition (r, TREE_TYPE (r));
+ }
+ else if (TREE_CODE (r) == FIELD_DECL)
+ {
+ /* Determine whether R has a valid type and can be
+ completed later. If R is invalid, then it is
+ replaced by error_mark_node so that it will not be
+ added to TYPE_FIELDS. */
+ tree rtype = TREE_TYPE (r);
+ if (can_complete_type_without_circularity (rtype))
+ complete_type (rtype);
+
+ if (!COMPLETE_TYPE_P (rtype))
+ {
+ cxx_incomplete_type_error (r, rtype);
+ r = error_mark_node;
+ }
+ }
- 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,
- tf_error | tf_warning, NULL_TREE);
- else
- {
- tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
-
- /* The call to xref_tag_from_type does injection for friend
- classes. */
- push_nested_namespace (ns);
- new_friend_type =
- xref_tag_from_type (friend_type, NULL_TREE, 1);
- pop_nested_namespace (ns);
+ /* If 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 in finish_member_declaration in the
+ CLASSTYPE_NESTED_UDTS case above. */
+ if (!(TREE_CODE (r) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
+ && DECL_ARTIFICIAL (r)))
+ {
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
+ }
+ }
}
+ else
+ {
+ if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
+ {
+ /* Build new CLASSTYPE_FRIEND_CLASSES. */
+
+ tree friend_type = t;
+ tree new_friend_type;
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- /* Trick make_friend_class into realizing that the friend
- we're adding is a template, not an ordinary class. It's
- important that we use make_friend_class since it will
- perform some error-checking and output cross-reference
- information. */
- ++processing_template_decl;
+ 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,
+ tf_error | tf_warning, NULL_TREE);
+ else
+ {
+ tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
+
+ /* The call to xref_tag_from_type does injection for friend
+ classes. */
+ push_nested_namespace (ns);
+ new_friend_type =
+ xref_tag_from_type (friend_type, NULL_TREE, 1);
+ pop_nested_namespace (ns);
+ }
- if (new_friend_type != error_mark_node)
- make_friend_class (type, new_friend_type);
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ /* Trick make_friend_class into realizing that the friend
+ we're adding is a template, not an ordinary class. It's
+ important that we use make_friend_class since it will
+ perform some error-checking and output cross-reference
+ information. */
+ ++processing_template_decl;
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- --processing_template_decl;
- }
+ if (new_friend_type != error_mark_node)
+ make_friend_class (type, new_friend_type);
- /* Now that TYPE_FIELDS and TYPE_METHODS are set up. We can
- instantiate templates used by this class. */
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- {
- TREE_TYPE (t) = complete_type (TREE_TYPE (t));
- require_complete_type (t);
- }
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ --processing_template_decl;
+ }
+ else
+ /* Build new DECL_FRIENDLIST. */
+ add_friend (type, tsubst_friend_function (t, args));
+ }
+ }
/* 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. */
+ typedecl = TYPE_MAIN_DECL (type);
lineno = DECL_SOURCE_LINE (typedecl);
input_filename = DECL_SOURCE_FILE (typedecl);
@@ -5362,6 +5616,9 @@ instantiate_class_template (type)
pop_from_top_level ();
pop_tinst_level ();
+ if (TYPE_CONTAINS_VPTR_P (type))
+ keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
return type;
}
@@ -5506,7 +5763,7 @@ tsubst_template_parms (parms, args, complain)
/* 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
+ ENTERING_SCOPE is nonzero, T is the context for a template which
we are presently tsubst'ing. Return the substituted value. */
static tree
@@ -5592,15 +5849,19 @@ tsubst_default_argument (fn, type, arg)
};
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_CONTEXT (fn), 2);
+ rather than in the current class.
+
+ ??? current_class_type affects a lot more than name lookup. This is
+ very fragile. Fortunately, it will go away when we do 2-phase name
+ binding properly. */
+
+ /* FN is already the desired FUNCTION_DECL. */
+ push_access_scope (fn);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
- if (DECL_CLASS_SCOPE_P (fn))
- popclass ();
+ pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
@@ -5650,8 +5911,6 @@ tsubst_decl (t, args, type, complain)
tree r = NULL_TREE;
tree in_decl = t;
- my_friendly_assert (complain & tf_error, 20011214);
-
/* Set the filename and linenumber to improve error-reporting. */
saved_lineno = lineno;
saved_filename = input_filename;
@@ -5716,10 +5975,6 @@ tsubst_decl (t, args, type, complain)
= tsubst_aggr_type (DECL_CONTEXT (t), args,
complain, in_decl,
/*entering_scope=*/1);
- DECL_VIRTUAL_CONTEXT (r)
- = tsubst_aggr_type (DECL_VIRTUAL_CONTEXT (t), args,
- complain, in_decl,
- /*entering_scope=*/1);
DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
@@ -5746,7 +6001,7 @@ tsubst_decl (t, args, type, complain)
/* The template parameters for this new template are all the
template parameters for the old template, except the
- outermost level of parameters. */
+ outermost level of parameters. */
DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
@@ -5782,6 +6037,10 @@ tsubst_decl (t, args, type, complain)
{
tree spec;
+ /* If T is not dependent, just return it. */
+ if (!uses_template_parms (DECL_TI_ARGS (t)))
+ return t;
+
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
specialize R. */
@@ -5890,10 +6149,6 @@ tsubst_decl (t, args, type, complain)
SET_DECL_RTL (r, NULL_RTX);
DECL_CONTEXT (r) = ctx;
- DECL_VIRTUAL_CONTEXT (r)
- = tsubst_aggr_type (DECL_VIRTUAL_CONTEXT (t), args,
- complain, t,
- /*entering_scope=*/1);
if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
@@ -5981,7 +6236,7 @@ tsubst_decl (t, args, type, complain)
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
-
+
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
@@ -5992,10 +6247,9 @@ tsubst_decl (t, args, type, complain)
complain, in_decl);
DECL_CONTEXT (r) = NULL_TREE;
- if (!DECL_TEMPLATE_PARM_P (r) && PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (r) = integer_type_node;
+
+ if (!DECL_TEMPLATE_PARM_P (r))
+ DECL_ARG_TYPE (r) = type_passed_as (type);
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
complain, TREE_CHAIN (t));
@@ -6102,7 +6356,10 @@ tsubst_decl (t, args, type, complain)
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (r) = 0;
+ {
+ DECL_DEAD_FOR_LOCAL (r) = 0;
+ DECL_INITIALIZED_P (r) = 0;
+ }
if (!local_p)
{
@@ -6703,7 +6960,7 @@ tsubst (t, args, complain, in_decl)
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("creating pointer to member reference type `%T'", type);
return error_mark_node;
@@ -6736,7 +6993,7 @@ tsubst (t, args, complain, in_decl)
if (fntype == error_mark_node)
return error_mark_node;
- /* Substitue the exception specification. */
+ /* Substitue the exception specification. */
raises = TYPE_RAISES_EXCEPTIONS (t);
if (raises)
{
@@ -6843,7 +7100,7 @@ tsubst (t, args, complain, in_decl)
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
- incomplete_type_error (NULL_TREE, ctx);
+ cxx_incomplete_type_error (NULL_TREE, ctx);
return error_mark_node;
}
}
@@ -6931,7 +7188,10 @@ tsubst (t, args, complain, in_decl)
if (e1 == error_mark_node)
return error_mark_node;
- return TREE_TYPE (e1);
+ return cp_build_qualified_type_real (TREE_TYPE (e1),
+ cp_type_quals (t)
+ | cp_type_quals (TREE_TYPE (e1)),
+ complain);
}
default:
@@ -7330,22 +7590,14 @@ tsubst_expr (t, args, complain, in_decl)
break;
case CTOR_INITIALIZER:
- {
- tree member_init_list;
- tree base_init_list;
-
- prep_stmt (t);
- member_init_list
- = tsubst_initializer_list (TREE_OPERAND (t, 0), args);
- base_init_list
- = tsubst_initializer_list (TREE_OPERAND (t, 1), args);
- emit_base_init (member_init_list, base_init_list);
- break;
- }
+ prep_stmt (t);
+ finish_mem_initializers (tsubst_initializer_list
+ (TREE_OPERAND (t, 0), args));
+ break;
case RETURN_STMT:
prep_stmt (t);
- finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
+ finish_return_stmt (tsubst_expr (RETURN_STMT_EXPR (t),
args, complain, in_decl));
break;
@@ -7405,7 +7657,7 @@ tsubst_expr (t, args, complain, in_decl)
/* For __PRETTY_FUNCTION__ we have to adjust the
initializer. */
const char *const name
- = (*decl_printable_name) (current_function_decl, 2);
+ = cxx_printable_name (current_function_decl, 2);
init = cp_fname_init (name);
TREE_TYPE (decl) = TREE_TYPE (init);
}
@@ -7417,7 +7669,7 @@ tsubst_expr (t, args, complain, in_decl)
}
/* A DECL_STMT can also be used as an expression, in the condition
- clause of a if/for/while construct. If we aren't followed by
+ clause of an if/for/while construct. If we aren't followed by
another statement, return our decl. */
if (TREE_CHAIN (t) == NULL_TREE)
return decl;
@@ -7632,10 +7884,6 @@ tsubst_expr (t, args, complain, in_decl)
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
- case CTOR_STMT:
- add_stmt (copy_node (t));
- break;
-
default:
abort ();
}
@@ -7667,7 +7915,7 @@ instantiate_template (tmpl, targ_ptr)
tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr);
tree clone;
- /* Look for the clone. */
+ /* Look for the clone. */
for (clone = TREE_CHAIN (spec);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
@@ -7716,9 +7964,19 @@ instantiate_template (tmpl, targ_ptr)
}
}
+ /* Make sure that we can see identifiers, and compute access
+ correctly. The desired FUNCTION_DECL for FNDECL may or may not be
+ created earlier. Let push_access_scope_real figure that out. */
+ push_access_scope_real
+ (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ tf_error, gen_tmpl));
+
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, tf_error, gen_tmpl);
+
+ pop_access_scope (gen_tmpl);
+
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
DECL_TI_TEMPLATE (fndecl) = tmpl;
@@ -7789,7 +8047,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
int result;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
+
fntype = TREE_TYPE (fn);
if (explicit_targs)
{
@@ -7967,6 +8225,12 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
}
+
+ /* DR 322. For conversion deduction, remove a reference type on parm
+ too (which has been swapped into ARG). */
+ if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
+ *arg = TREE_TYPE (*arg);
+
return result;
}
@@ -7995,8 +8259,7 @@ type_unification_real (tparms, targs, xparms, xargs, subr,
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
my_friendly_assert (xparms == NULL_TREE
|| TREE_CODE (xparms) == TREE_LIST, 290);
- /* ARGS could be NULL (via a call from parse.y to
- build_x_function_call). */
+ /* ARGS could be NULL. */
if (xargs)
my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
@@ -8173,8 +8436,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
arg = TREE_OPERAND (arg, 1);
/* Strip baselink information. */
- while (TREE_CODE (arg) == TREE_LIST)
- arg = TREE_VALUE (arg);
+ if (BASELINK_P (arg))
+ arg = BASELINK_FUNCTIONS (arg);
if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
@@ -8205,7 +8468,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD)
+ else if (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL)
{
for (; arg; arg = OVL_NEXT (arg))
{
@@ -8332,29 +8596,12 @@ static int
verify_class_unification (targs, parms, args)
tree targs, parms, args;
{
- int i;
- int nparms = TREE_VEC_LENGTH (parms);
- tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
- tf_none, NULL_TREE);
- if (new_parms == error_mark_node)
+ parms = tsubst (parms, add_outermost_template_args (args, targs),
+ tf_none, NULL_TREE);
+ if (parms == error_mark_node)
return 1;
- args = INNERMOST_TEMPLATE_ARGS (args);
-
- for (i = 0; i < nparms; i++)
- {
- tree parm = TREE_VEC_ELT (new_parms, i);
- tree arg = TREE_VEC_ELT (args, i);
-
- /* In case we are deducing from a function argument of a function
- templates, some parameters may not be deduced yet. So we
- make sure that only fully substituted elements of PARM are
- compared below. */
-
- if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
- return 1;
- }
- return 0;
+ return !comp_template_args (parms, INNERMOST_TEMPLATE_ARGS (args));
}
/* PARM is a template class (perhaps with unbound template
@@ -8372,7 +8619,8 @@ try_class_unification (tparms, targs, parm, arg)
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
- || CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
+ || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
+ != most_general_template (CLASSTYPE_TI_TEMPLATE (parm))))
return NULL_TREE;
/* We need to make a new template argument vector for the call to
@@ -8401,7 +8649,7 @@ try_class_unification (tparms, targs, parm, arg)
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
+ `S<0, 1, 2>' is derived from `S<0, 0, 0>', the code is invalid
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. */
@@ -8543,7 +8791,7 @@ template_decl_level (decl)
/* Decide whether ARG can be unified with PARM, considering only the
cv-qualifiers of each type, given STRICT as documented for unify.
- Returns non-zero iff the unification is OK on that basis.*/
+ Returns nonzero iff the unification is OK on that basis.*/
static int
check_cv_quals_for_unify (strict, arg, parm)
@@ -8763,6 +9011,12 @@ unify (tparms, targs, parm, arg, strict)
}
else
{
+ /* If ARG is an offset type, we're trying to unify '*T' with
+ 'U C::*', which is ill-formed. See the comment in the
+ POINTER_TYPE case about this ugliness. */
+ if (TREE_CODE (arg) == OFFSET_TYPE)
+ return 1;
+
/* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
@@ -8831,8 +9085,12 @@ unify (tparms, targs, parm, arg, strict)
deduced from an array bound may be of any integral type.
The non-type parameter might use already deduced type parameters. */
tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
- if (same_type_p (TREE_TYPE (arg), tparm))
- /* OK */;
+ if (!TREE_TYPE (arg))
+ /* Template-parameter dependent expression. Just accept it for now.
+ It will later be processed in convert_template_argument. */
+ ;
+ else if (same_type_p (TREE_TYPE (arg), tparm))
+ /* OK */;
else if ((strict & UNIFY_ALLOW_INTEGER)
&& (TREE_CODE (tparm) == INTEGER_TYPE
|| TREE_CODE (tparm) == BOOLEAN_TYPE))
@@ -8872,7 +9130,7 @@ unify (tparms, targs, parm, arg, strict)
{
/* Avoid getting confused about cv-quals; don't recurse here.
Pointers to members should really be just OFFSET_TYPE, not
- this two-level nonsense... */
+ this two-level nonsense... */
parm = TREE_TYPE (parm);
arg = TREE_TYPE (arg);
@@ -8900,7 +9158,7 @@ unify (tparms, targs, parm, arg, strict)
TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL);
case REAL_TYPE:
case COMPLEX_TYPE:
@@ -9117,11 +9375,6 @@ mark_decl_instantiated (result, extern_p)
tree result;
int extern_p;
{
- if (TREE_CODE (result) != FUNCTION_DECL)
- /* The TREE_PUBLIC flag for function declarations will have been
- set correctly by tsubst. */
- TREE_PUBLIC (result) = 1;
-
/* We used to set this unconditionally; we moved that to
do_decl_instantiation so it wouldn't get set on members of
explicit class template instantiations. But we still need to set
@@ -9130,6 +9383,19 @@ mark_decl_instantiated (result, extern_p)
if (extern_p)
SET_DECL_EXPLICIT_INSTANTIATION (result);
+ /* If this entity has already been written out, it's too late to
+ make any modifications. */
+ if (TREE_ASM_WRITTEN (result))
+ return;
+
+ if (TREE_CODE (result) != FUNCTION_DECL)
+ /* The TREE_PUBLIC flag for function declarations will have been
+ set correctly by tsubst. */
+ TREE_PUBLIC (result) = 1;
+
+ /* This might have been set by an earlier implicit instantiation. */
+ DECL_COMDAT (result) = 0;
+
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
@@ -9143,7 +9409,8 @@ mark_decl_instantiated (result, extern_p)
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
- else if (TREE_CODE (result) == FUNCTION_DECL)
+
+ if (TREE_CODE (result) == FUNCTION_DECL)
defer_fn (result);
}
@@ -9234,7 +9501,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len)
if (DECL_TEMPLATE_INFO (decl))
tmpl = DECL_TI_TEMPLATE (decl);
else
- /* We can get here for some illegal specializations. */
+ /* We can get here for some invalid specializations. */
return NULL_TREE;
converted_args
@@ -9434,6 +9701,10 @@ most_general_template (decl)
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ break;
+
/* Stop if we run into an explicitly specialized class template. */
if (!DECL_NAMESPACE_SCOPE_P (decl)
&& DECL_CONTEXT (decl)
@@ -9505,13 +9776,11 @@ most_specialized_class (tmpl, args)
return champ;
}
-/* called from the parser. */
+/* Explicitly instantiate DECL. */
void
-do_decl_instantiation (declspecs, declarator, storage)
- tree declspecs, declarator, storage;
+do_decl_instantiation (tree decl, tree storage)
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
@@ -9550,7 +9819,7 @@ do_decl_instantiation (declspecs, declarator, storage)
result = decl;
/* Check for various error cases. Note that if the explicit
- instantiation is legal the RESULT will currently be marked as an
+ instantiation is valid the RESULT will currently be marked as an
*implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
until we get here. */
@@ -9635,9 +9904,21 @@ mark_class_instantiated (t, extern_p)
}
}
+/* Called from do_type_instantiation through binding_table_foreach to
+ do recursive instantiation for the type bound in ENTRY. */
+static void
+bt_instantiate_type_proc (binding_entry entry, void *data)
+{
+ tree storage = *(tree *) data;
+
+ if (IS_AGGR_TYPE (entry->type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
+ do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
+}
+
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
- non-zero if this is called from the parser, zero if called recursively,
+ nonzero if this is called from the parser, zero if called recursively,
since the standard is unclear (as detailed below). */
void
@@ -9775,10 +10056,9 @@ do_type_instantiation (t, storage, complain)
instantiate_decl (tmp, /*defer_ok=*/1);
}
- for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (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, 0);
+ if (CLASSTYPE_NESTED_UDTS (t))
+ binding_table_foreach (CLASSTYPE_NESTED_UDTS (t),
+ bt_instantiate_type_proc, &storage);
}
}
@@ -9825,6 +10105,7 @@ regenerate_decl_from_template (decl, tmpl)
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
+ push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
unregistered = unregister_specialization (decl, gen_tmpl);
/* If the DECL was not unregistered then something peculiar is
@@ -9832,11 +10113,6 @@ regenerate_decl_from_template (decl, tmpl)
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, tf_error, NULL_TREE);
@@ -9844,11 +10120,10 @@ regenerate_decl_from_template (decl, tmpl)
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
- DECL_INITIAL (new_decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl));
- /* Pop the class context we pushed above. */
- popclass ();
+ if (!DECL_INITIALIZED_IN_CLASS_P (decl))
+ DECL_INITIAL (new_decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
@@ -9859,6 +10134,8 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (decl) = NULL_TREE;
}
+ pop_access_scope (decl);
+
/* 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
@@ -9879,7 +10156,7 @@ regenerate_decl_from_template (decl, tmpl)
}
/* Produce the definition of D, a _DECL generated from a template. If
- DEFER_OK is non-zero, then we don't have to actually do the
+ DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. */
tree
@@ -9888,7 +10165,8 @@ instantiate_decl (d, defer_ok)
int defer_ok;
{
tree tmpl = DECL_TI_TEMPLATE (d);
- tree args = DECL_TI_ARGS (d);
+ tree gen_args;
+ tree args;
tree td;
tree code_pattern;
tree spec;
@@ -9903,6 +10181,9 @@ instantiate_decl (d, defer_ok)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
+ if (TREE_CODE (d) == VAR_DECL)
+ defer_ok = 0;
+
/* Don't instantiate cloned functions. Instead, instantiate the
functions they cloned. */
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
@@ -9922,7 +10203,8 @@ instantiate_decl (d, defer_ok)
specializations, so we must explicitly check
DECL_TEMPLATE_SPECIALIZATION. */
gen_tmpl = most_general_template (tmpl);
- spec = retrieve_specialization (gen_tmpl, args);
+ gen_args = DECL_TI_ARGS (d);
+ spec = retrieve_specialization (gen_tmpl, gen_args);
if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
return spec;
@@ -9983,6 +10265,16 @@ instantiate_decl (d, defer_ok)
code_pattern = DECL_TEMPLATE_RESULT (td);
+ if ((DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
+ || DECL_TEMPLATE_SPECIALIZATION (td))
+ /* In the case of a friend template whose definition is provided
+ outside the class, we may have too many arguments. Drop the
+ ones we don't need. The same is true for specializations. */
+ args = get_innermost_template_args
+ (gen_args, TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (td)));
+ else
+ args = gen_args;
+
if (TREE_CODE (d) == FUNCTION_DECL)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
@@ -10040,18 +10332,25 @@ instantiate_decl (d, defer_ok)
tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
tree type = TREE_TYPE (gen);
+ /* Make sure that we can see identifiers, and compute access
+ correctly. D is already the target FUNCTION_DECL with the
+ right context. */
+ push_access_scope (d);
+
if (TREE_CODE (gen) == FUNCTION_DECL)
{
- tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
- tsubst (TYPE_RAISES_EXCEPTIONS (type), args,
+ tsubst (DECL_ARGUMENTS (gen), gen_args, tf_error | tf_warning, d);
+ tsubst (TYPE_RAISES_EXCEPTIONS (type), gen_args,
tf_error | tf_warning, d);
/* Don't simply tsubst the function type, as that will give
duplicate warnings about poor parameter qualifications.
The function arguments are the same as the decl_arguments
- without the top level cv qualifiers. */
+ without the top level cv qualifiers. */
type = TREE_TYPE (type);
}
- tsubst (type, args, tf_error | tf_warning, d);
+ tsubst (type, gen_args, tf_error | tf_warning, d);
+
+ pop_access_scope (d);
}
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
@@ -10092,15 +10391,10 @@ instantiate_decl (d, defer_ok)
if (need_push)
push_to_top_level ();
- /* 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
they changed as a result of calling regenerate_decl_from_template. */
lineno = DECL_SOURCE_LINE (d);
@@ -10108,20 +10402,52 @@ instantiate_decl (d, defer_ok)
if (TREE_CODE (d) == VAR_DECL)
{
+ /* Clear out DECL_RTL; whatever was there before may not be right
+ since we've reset the type of the declaration. */
+ SET_DECL_RTL (d, NULL_RTX);
+
DECL_IN_AGGR_P (d) = 0;
- if (DECL_INTERFACE_KNOWN (d))
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+ import_export_decl (d);
+ DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+
+ if (DECL_EXTERNAL (d))
+ {
+ /* The fact that this code is executing indicates that:
+
+ (1) D is a template static data member, for which a
+ definition is available.
+
+ (2) An implicit or explicit instantiation has occured.
+
+ (3) We are not going to emit a definition of the static
+ data member at this time.
+
+ This situation is peculiar, but it occurs on platforms
+ without weak symbols when performing an implicit
+ instantiation. There, we cannot implicitly instantiate a
+ defined static data member in more than one translation
+ unit, so import_export_decl marks the declaration as
+ external; we must rely on explicit instantiation. */
+ }
else
{
- DECL_EXTERNAL (d) = 1;
- DECL_NOT_REALLY_EXTERN (d) = 1;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
+ ? DECL_INITIAL (d) : NULL_TREE),
+ NULL_TREE, 0);
}
- cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
@@ -10133,6 +10459,7 @@ instantiate_decl (d, defer_ok)
NULL);
/* Set up context. */
+ import_export_decl (d);
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
/* Substitute into the body of the function. */
@@ -10144,7 +10471,8 @@ instantiate_decl (d, defer_ok)
local_specializations = saved_local_specializations;
/* Finish the function. */
- expand_body (finish_function (0));
+ d = finish_function (0);
+ expand_body (d);
}
/* We're not deferring instantiation any more. */
@@ -10260,8 +10588,7 @@ static tree
tsubst_initializer_list (t, argvec)
tree t, argvec;
{
- tree first = NULL_TREE;
- tree *p = &first;
+ tree inits = NULL_TREE;
for (; t; t = TREE_CHAIN (t))
{
@@ -10271,23 +10598,30 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
+ decl = expand_member_init (decl);
+ if (decl && !DECL_P (decl))
+ in_base_initializer = 1;
+
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
-
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
for (val = init; val; val = TREE_CHAIN (val))
TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
- else
+ else if (init != void_type_node)
init = convert_from_reference (init);
- *p = expand_member_init (current_class_ref, decl,
- init ? init : void_type_node);
- if (*p)
- p = &TREE_CHAIN (*p);
+ in_base_initializer = 0;
+
+ if (decl)
+ {
+ init = build_tree_list (decl, init);
+ TREE_CHAIN (init) = inits;
+ inits = init;
+ }
}
- return first;
+ return inits;
}
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
@@ -10334,25 +10668,19 @@ tsubst_enum (tag, newtag, args)
}
finish_enum (newtag);
- DECL_SOURCE_LINE (TYPE_NAME (newtag)) = DECL_SOURCE_LINE (TYPE_NAME (tag));
- DECL_SOURCE_FILE (TYPE_NAME (newtag)) = DECL_SOURCE_FILE (TYPE_NAME (tag));
+ DECL_SOURCE_LOCATION (TYPE_NAME (newtag))
+ = DECL_SOURCE_LOCATION (TYPE_NAME (tag));
}
/* DECL is a FUNCTION_DECL that is a template specialization. Return
its type -- but without substituting the innermost set of template
arguments. So, innermost set of template parameters will appear in
- the type. If CONTEXTP is non-NULL, then the partially substituted
- DECL_CONTEXT (if any) will also be filled in. Similarly, TPARMSP
- will be filled in with the substituted template parameters, if it
- is non-NULL. */
+ the type. */
tree
-get_mostly_instantiated_function_type (decl, contextp, tparmsp)
+get_mostly_instantiated_function_type (decl)
tree decl;
- tree *contextp;
- tree *tparmsp;
{
- tree context = NULL_TREE;
tree fn_type;
tree tmpl;
tree targs;
@@ -10369,8 +10697,6 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
fn_type = TREE_TYPE (tmpl);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = DECL_CONTEXT (decl);
if (parm_depth == 1)
/* No substitution is necessary. */
@@ -10390,11 +10716,16 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
TMPL_ARGS_DEPTH (targs),
make_tree_vec (DECL_NTPARMS (tmpl)));
+ /* Make sure that we can see identifiers, and compute access
+ correctly. We can just use the context of DECL for the
+ partial substitution here. It depends only on outer template
+ parameters, regardless of whether the innermost level is
+ specialized or not. */
+ push_access_scope (decl);
+
/* Now, do the (partial) substitution to figure out the
appropriate function type. */
fn_type = tsubst (fn_type, partial_args, tf_error, NULL_TREE);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = tsubst (context, partial_args, tf_error, NULL_TREE);
/* Substitute into the template parameters to obtain the real
innermost set of parameters. This step is important if the
@@ -10402,12 +10733,9 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
parameters whose types depend on outer template parameters. */
TREE_VEC_LENGTH (partial_args)--;
tparms = tsubst_template_parms (tparms, partial_args, tf_error);
- }
- if (contextp)
- *contextp = context;
- if (tparmsp)
- *tparmsp = tparms;
+ pop_access_scope (decl);
+ }
return fn_type;
}
@@ -10434,7 +10762,7 @@ current_instantiation ()
}
/* [temp.param] Check that template non-type parm TYPE is of an allowable
- type. Return zero for ok, non-zero for disallowed. Issue error and
+ type. Return zero for ok, nonzero for disallowed. Issue error and
warning messages under control of COMPLAIN. */
static int
@@ -10460,3 +10788,5 @@ invalid_nontype_parm_type_p (type, complain)
type);
return 1;
}
+
+#include "gt-cp-pt.h"
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index f40e412..6a7b26c 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -157,15 +157,23 @@ cxx_print_type (file, node, indent)
}
}
+static void
+cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix)
+{
+ fprintf (stream, "%s <", prefix);
+ fprintf (stream, HOST_PTR_PRINTF, (char *) binding);
+ fprintf (stream, ">");
+}
+
void
cxx_print_identifier (file, node, indent)
FILE *file;
tree node;
int indent;
{
- print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
+ cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
+ cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
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);
@@ -180,12 +188,6 @@ cxx_print_xnode (file, node, indent)
{
switch (TREE_CODE (node))
{
- case CPLUS_BINDING:
- 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;
case OVERLOAD:
print_node (file, "function", OVL_FUNCTION (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
diff --git a/contrib/gcc/cp/repo.c b/contrib/gcc/cp/repo.c
index fe2eb62..64c6ec87 100644
--- a/contrib/gcc/cp/repo.c
+++ b/contrib/gcc/cp/repo.c
@@ -42,15 +42,14 @@ static void open_repo_file PARAMS ((const char *));
static char *afgets PARAMS ((FILE *));
static void reopen_repo_file_for_write PARAMS ((void));
-static tree pending_repo;
-static tree original_repo;
+static GTY(()) tree pending_repo;
+static GTY(()) tree original_repo;
static char *repo_name;
static FILE *repo_file;
-static char *old_args, *old_dir, *old_main;
+static const char *old_args, *old_dir, *old_main;
static struct obstack temporary_obstack;
-extern struct obstack permanent_obstack;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
@@ -292,8 +291,9 @@ open_repo_file (filename)
if (! p)
p = s + strlen (s);
- obstack_grow (&permanent_obstack, s, p - s);
- repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
+ repo_name = xmalloc (p - s + 5);
+ memcpy (repo_name, s, p - s);
+ memcpy (repo_name + (p - s), ".rpo", 5);
repo_file = fopen (repo_name, "r");
}
@@ -320,8 +320,6 @@ init_repo (filename)
if (! flag_use_repository)
return;
- ggc_add_tree_root (&pending_repo, 1);
- ggc_add_tree_root (&original_repo, 1);
gcc_obstack_init (&temporary_obstack);
open_repo_file (filename);
@@ -334,16 +332,13 @@ init_repo (filename)
switch (buf[0])
{
case 'A':
- old_args = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_args = ggc_strdup (buf + 2);
break;
case 'D':
- old_dir = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_dir = ggc_strdup (buf + 2);
break;
case 'M':
- old_main = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_main = ggc_strdup (buf + 2);
break;
case 'C':
case 'O':
@@ -458,3 +453,5 @@ finish_repo ()
if (repo_file)
fclose (repo_file);
}
+
+#include "gt-cp-repo.h"
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
index fbb37fe..7b4a248 100644
--- a/contrib/gcc/cp/rtti.c
+++ b/contrib/gcc/cp/rtti.c
@@ -62,13 +62,13 @@ Boston, MA 02111-1307, USA. */
/* Accessors for the type_info objects. We need to remember several things
about each of the type_info types. The global tree nodes such as
bltn_desc_type_node are TREE_LISTs, and these macros are used to access
- the required information. */
-/* The RECORD_TYPE of a type_info derived class. */
+ the required information. */
+/* The RECORD_TYPE of a type_info derived class. */
#define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
/* The VAR_DECL of the vtable for the type_info derived class.
- This is only filled in at the end of the translation. */
+ This is only filled in at the end of the translation. */
#define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
-/* The IDENTIFIER_NODE naming the real class. */
+/* The IDENTIFIER_NODE naming the real class. */
#define TINFO_REAL_NAME(NODE) TREE_PURPOSE (NODE)
static tree build_headof PARAMS((tree));
@@ -109,8 +109,9 @@ void
init_rtti_processing ()
{
push_namespace (std_identifier);
- type_info_type_node = xref_tag
- (class_type_node, get_identifier ("type_info"), 1);
+ type_info_type_node
+ = xref_tag (class_type, get_identifier ("type_info"),
+ /*attributes=*/NULL_TREE, 1);
pop_namespace ();
type_info_ptr_type =
build_pointer_type
@@ -142,7 +143,7 @@ build_headof (exp)
exp = save_expr (exp);
/* The offset-to-top field is at index -2 from the vptr. */
- index = build_int_2 (-2, -1);
+ index = build_int_2 (-2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index);
@@ -166,7 +167,7 @@ throw_bad_cast ()
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_node));
- return build_call (fn, NULL_TREE);
+ return build_cxx_call (fn, NULL_TREE, NULL_TREE);
}
static tree
@@ -182,7 +183,7 @@ throw_bad_typeid ()
fn = push_throw_library_fn (fn, t);
}
- return build_call (fn, NULL_TREE);
+ return build_cxx_call (fn, NULL_TREE, NULL_TREE);
}
/* Return a pointer to type_info function associated with the expression EXP.
@@ -221,7 +222,7 @@ get_tinfo_decl_dynamic (exp)
tree index;
/* The RTTI information is at index -1. */
- index = integer_minus_one_node;
+ index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
TREE_TYPE (t) = type_info_ptr_type;
return t;
@@ -298,7 +299,7 @@ tinfo_name (type)
tree name_string;
name = mangle_type_string (type);
- name_string = combine_strings (build_string (strlen (name) + 1, name));
+ name_string = fix_string_type (build_string (strlen (name) + 1, name));
return name_string;
}
@@ -351,9 +352,8 @@ get_tinfo_decl (type)
DECL_EXTERNAL (d) = 1;
SET_DECL_ASSEMBLER_NAME (d, name);
DECL_COMDAT (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
- pushdecl_top_level (d);
+ pushdecl_top_level_and_finish (d, NULL_TREE);
if (CLASS_TYPE_P (type))
CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
@@ -633,8 +633,9 @@ build_dynamic_cast_1 (type, expr)
const char *name;
push_nested_namespace (ns);
- tinfo_ptr = xref_tag (class_type_node,
+ tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
+ /*attributes=*/NULL_TREE,
1);
tinfo_ptr = build_pointer_type
@@ -651,7 +652,7 @@ build_dynamic_cast_1 (type, expr)
pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn;
}
- result = build_call (dcast_fn, elems);
+ result = build_cxx_call (dcast_fn, elems, elems);
if (tc == REFERENCE_TYPE)
{
@@ -695,8 +696,7 @@ qualifier_flags (type)
tree type;
{
int flags = 0;
- /* we want the qualifiers on this type, not any array core, it might have */
- int quals = TYPE_QUALS (type);
+ int quals = cp_type_quals (type);
if (quals & TYPE_QUAL_CONST)
flags |= 1;
@@ -707,7 +707,7 @@ qualifier_flags (type)
return flags;
}
-/* Return non-zero, if the pointer chain TYPE ends at an incomplete type, or
+/* Return nonzero, if the pointer chain TYPE ends at an incomplete type, or
contains a pointer to member of an incomplete class. */
static int
@@ -767,8 +767,7 @@ tinfo_base_init (desc, target)
SET_DECL_ASSEMBLER_NAME (name_decl,
mangle_typeinfo_string_for_type (target));
DECL_INITIAL (name_decl) = name_string;
- cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
- pushdecl_top_level (name_decl);
+ pushdecl_top_level_and_finish (name_decl, name_string);
}
vtable_ptr = TINFO_VTABLE_DECL (desc);
@@ -777,9 +776,10 @@ tinfo_base_init (desc, target)
tree real_type;
push_nested_namespace (abi_node);
- real_type = xref_tag (class_type_node, TINFO_REAL_NAME (desc), 1);
+ real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
+ /*attributes=*/NULL_TREE, 1);
pop_nested_namespace (abi_node);
-
+
if (!COMPLETE_TYPE_P (real_type))
{
/* We never saw a definition of this type, so we need to
@@ -796,7 +796,7 @@ tinfo_base_init (desc, target)
vtable_ptr = build
(PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
size_binop (MULT_EXPR,
- size_int (2),
+ size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
TYPE_SIZE_UNIT (vtable_entry_type)));
TREE_CONSTANT (vtable_ptr) = 1;
@@ -932,7 +932,7 @@ dfs_class_hint_mark (binfo, data)
return NULL_TREE;
};
-/* Clear the base's dfs marks, after searching for duplicate bases. */
+/* Clear the base's dfs marks, after searching for duplicate bases. */
static tree
dfs_class_hint_unmark (binfo, data)
@@ -986,7 +986,7 @@ class_initializer (desc, target, trail)
return init;
}
-/* Returns non-zero if the typeinfo for type should be placed in
+/* Returns nonzero if the typeinfo for type should be placed in
the runtime library. */
static int
@@ -1015,7 +1015,7 @@ typeinfo_in_lib_p (type)
}
/* Generate the initializer for the type info describing
- TYPE. VAR_DESC is a . NON_PUBLIC_P is set non-zero, if the VAR_DECL
+ TYPE. VAR_DESC is a . NON_PUBLIC_P is set nonzero, if the VAR_DECL
should not be exported from this object file. This should only be
called at the end of translation, when we know that no further
types will be completed. */
@@ -1105,15 +1105,17 @@ get_pseudo_ti_init (type, var_desc, non_public_p)
base_init = tree_cons (NULL_TREE, offset, base_init);
base_init = tree_cons (NULL_TREE, tinfo, base_init);
base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
+ TREE_HAS_CONSTRUCTOR (base_init) = 1;
base_inits = tree_cons (NULL_TREE, base_init, base_inits);
}
base_inits = build (CONSTRUCTOR,
NULL_TREE, NULL_TREE, base_inits);
+ TREE_HAS_CONSTRUCTOR (base_inits) = 1;
base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
/* Prepend the number of bases. */
base_inits = tree_cons (NULL_TREE,
build_int_2 (nbases, 0), base_inits);
- /* Prepend the hint flags. */
+ /* Prepend the hint flags. */
base_inits = tree_cons (NULL_TREE,
build_int_2 (hint, 0), base_inits);
@@ -1155,24 +1157,24 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
VA_FIXEDARG (ap, const char *, real_name);
VA_FIXEDARG (ap, int, ident);
- /* Generate the pseudo type name. */
+ /* Generate the pseudo type name. */
pseudo_name = (char *)alloca (strlen (real_name) + 30);
strcpy (pseudo_name, real_name);
strcat (pseudo_name, "_pseudo");
if (ident)
sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);
- /* First field is the pseudo type_info base class. */
+ /* First field is the pseudo type_info base class. */
fields[0] = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
/* Now add the derived fields. */
for (ix = 0; (field_decl = va_arg (ap, tree));)
fields[++ix] = field_decl;
- /* Create the pseudo type. */
+ /* Create the pseudo type. */
pseudo_type = make_aggr_type (RECORD_TYPE);
finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
- TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
+ CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
TINFO_REAL_NAME (result) = get_identifier (real_name);
@@ -1207,7 +1209,8 @@ get_pseudo_ti_desc (type)
return ptm_desc_type_node;
else if (!COMPLETE_TYPE_P (type))
{
- my_friendly_assert (at_eof, 20020609);
+ if (!at_eof)
+ cxx_incomplete_type_error (NULL_TREE, type);
return class_desc_type_node;
}
else if (!CLASSTYPE_N_BASECLASSES (type))
@@ -1222,7 +1225,7 @@ get_pseudo_ti_desc (type)
&& TREE_PUBLIC (base_binfo)
&& !TREE_VIA_VIRTUAL (base_binfo)
&& integer_zerop (BINFO_OFFSET (base_binfo)))
- /* single non-virtual public. */
+ /* single non-virtual public. */
return si_class_desc_type_node;
else
{
@@ -1295,7 +1298,7 @@ create_tinfo_types ()
("__fundamental_type_info", 0,
NULL);
- /* Array, function and enum type_info. No additional fields. */
+ /* Array, function and enum type_info. No additional fields. */
ary_desc_type_node = create_pseudo_type_info
("__array_type_info", 0,
NULL);
@@ -1319,7 +1322,7 @@ create_tinfo_types ()
NULL);
/* Base class internal helper. Pointer to base type, offset to base,
- flags. */
+ flags. */
{
tree fields[2];
@@ -1331,12 +1334,12 @@ create_tinfo_types ()
TYPE_HAS_CONSTRUCTOR (base_desc_type_node) = 1;
}
- /* General hierarchy is created as necessary in this vector. */
+ /* General hierarchy is created as necessary in this vector. */
vmi_class_desc_type_node = make_tree_vec (10);
/* Pointer type_info. Adds two fields, qualification mask
and pointer to the pointed to type. This is really a descendant of
- __pbase_type_info. */
+ __pbase_type_info. */
ptr_desc_type_node = create_pseudo_type_info
("__pointer_type_info", 0,
build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
@@ -1382,8 +1385,10 @@ emit_support_tinfos ()
tree bltn_type, dtor;
push_nested_namespace (abi_node);
- bltn_type = xref_tag (class_type_node,
- get_identifier ("__fundamental_type_info"), 1);
+ bltn_type = xref_tag (class_type,
+ get_identifier ("__fundamental_type_info"),
+ /*attributes=*/NULL_TREE,
+ 1);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
@@ -1413,7 +1418,7 @@ emit_support_tinfos ()
}
}
-/* Return non-zero, iff T is a type_info variable which has not had a
+/* Return nonzero, iff T is a type_info variable which has not had a
definition emitted for it. */
int
@@ -1470,7 +1475,7 @@ emit_tinfo_decl (decl_ptr, data)
DECL_INITIAL (decl) = var_init;
cp_finish_decl (decl, var_init, NULL_TREE, 0);
- /* cp_finish_decl will have dealt with linkage. */
+ /* cp_finish_decl will have dealt with linkage. */
/* Say we've dealt with it. */
TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index 38f4634..7a82796 100644
--- a/contrib/gcc/cp/search.c
+++ b/contrib/gcc/cp/search.c
@@ -31,11 +31,8 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "rtl.h"
#include "output.h"
+#include "ggc.h"
#include "toplev.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
#include "stack.h"
/* Obstack used for remembering decision points of breadth-first. */
@@ -83,12 +80,12 @@ struct vbase_info
tree inits;
};
-static tree lookup_field_1 PARAMS ((tree, tree));
static int is_subobject_of_p PARAMS ((tree, tree, tree));
+static int is_subobject_of_p_1 PARAMS ((tree, tree, tree));
static tree dfs_check_overlap PARAMS ((tree, void *));
static tree dfs_no_overlap_yet PARAMS ((tree, void *));
static base_kind lookup_base_r
- PARAMS ((tree, tree, base_access, int, int, int, tree *));
+ PARAMS ((tree, tree, base_access, int, tree *));
static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *));
static tree marked_pushdecls_p PARAMS ((tree, void *));
static tree unmarked_pushdecls_p PARAMS ((tree, void *));
@@ -167,12 +164,8 @@ static int n_contexts_saved;
/* Worker for lookup_base. BINFO is the binfo we are searching at,
BASE is the RECORD_TYPE we are searching for. ACCESS is the
- required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
- IS_VIRTUAL indicate how BINFO was reached from the start of the
- search. WITHIN_CURRENT_SCOPE is true if we met the current scope,
- or friend thereof (this allows us to determine whether a protected
- base is accessible or not). IS_NON_PUBLIC indicates whether BINFO
- is accessible and IS_VIRTUAL indicates if it is morally virtual.
+ required access checks. IS_VIRTUAL indicates if BINFO is morally
+ virtual.
If BINFO is of the required type, then *BINFO_PTR is examined to
compare with any other instance of BASE we might have already
@@ -182,12 +175,9 @@ static int n_contexts_saved;
Otherwise BINFO's bases are searched. */
static base_kind
-lookup_base_r (binfo, base, access, within_current_scope,
- is_non_public, is_virtual, binfo_ptr)
+lookup_base_r (binfo, base, access, is_virtual, binfo_ptr)
tree binfo, base;
base_access access;
- int within_current_scope;
- int is_non_public; /* inside a non-public part */
int is_virtual; /* inside a virtual part */
tree *binfo_ptr;
{
@@ -195,24 +185,13 @@ lookup_base_r (binfo, base, access, within_current_scope,
tree bases;
base_kind found = bk_not_base;
- if (access == ba_check
- && !within_current_scope
- && is_friend (BINFO_TYPE (binfo), current_scope ()))
- {
- /* Do not clear is_non_public here. If A is a private base of B, A
- is not allowed to convert a B* to an A*. */
- within_current_scope = 1;
- }
-
if (same_type_p (BINFO_TYPE (binfo), base))
{
/* We have found a base. Check against what we have found
- already. */
+ already. */
found = bk_same_type;
if (is_virtual)
found = bk_via_virtual;
- if (is_non_public)
- found = bk_inaccessible;
if (!*binfo_ptr)
*binfo_ptr = binfo;
@@ -237,29 +216,11 @@ lookup_base_r (binfo, base, access, within_current_scope,
for (i = TREE_VEC_LENGTH (bases); i--;)
{
tree base_binfo = TREE_VEC_ELT (bases, i);
- int this_non_public = is_non_public;
- int this_virtual = is_virtual;
base_kind bk;
- if (access <= ba_ignore)
- ; /* no change */
- else if (TREE_VIA_PUBLIC (base_binfo))
- ; /* no change */
- else if (access == ba_not_special)
- this_non_public = 1;
- else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
- ; /* no change */
- else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
- ; /* no change */
- else
- this_non_public = 1;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- this_virtual = 1;
-
bk = lookup_base_r (base_binfo, base,
- access, within_current_scope,
- this_non_public, this_virtual,
+ access,
+ is_virtual || TREE_VIA_VIRTUAL (base_binfo),
binfo_ptr);
switch (bk)
@@ -270,14 +231,6 @@ lookup_base_r (binfo, base, access, within_current_scope,
found = bk;
break;
- case bk_inaccessible:
- if (found == bk_not_base)
- found = bk;
- my_friendly_assert (found == bk_via_virtual
- || found == bk_inaccessible, 20010723);
-
- break;
-
case bk_same_type:
bk = bk_proper_base;
/* FALLTHROUGH */
@@ -293,6 +246,9 @@ lookup_base_r (binfo, base, access, within_current_scope,
case bk_not_base:
break;
+
+ default:
+ abort ();
}
}
return found;
@@ -303,8 +259,10 @@ lookup_base_r (binfo, base, access, within_current_scope,
canonical). If KIND_PTR is non-NULL, fill with information about
what kind of base we discovered.
- If ba_quiet bit is set in ACCESS, then do not issue an error, and
- return NULL_TREE for failure. */
+ If the base is inaccessible, or ambiguous, and the ba_quiet bit is
+ not set in ACCESS, then an error is issued and error_mark_node is
+ returned. If the ba_quiet bit is set, then no error is issued and
+ NULL_TREE is returned. */
tree
lookup_base (t, base, access, kind_ptr)
@@ -312,7 +270,8 @@ lookup_base (t, base, access, kind_ptr)
base_access access;
base_kind *kind_ptr;
{
- tree binfo = NULL; /* The binfo we've found so far. */
+ tree binfo = NULL; /* The binfo we've found so far. */
+ tree t_binfo = NULL;
base_kind bk;
if (t == error_mark_node || base == error_mark_node)
@@ -321,39 +280,78 @@ lookup_base (t, base, access, kind_ptr)
*kind_ptr = bk_not_base;
return error_mark_node;
}
- my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127);
+ my_friendly_assert (TYPE_P (base), 20011127);
+ if (!TYPE_P (t))
+ {
+ t_binfo = t;
+ t = BINFO_TYPE (t);
+ }
+ else
+ t_binfo = TYPE_BINFO (t);
+
/* Ensure that the types are instantiated. */
t = complete_type (TYPE_MAIN_VARIANT (t));
base = complete_type (TYPE_MAIN_VARIANT (base));
- bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet,
- 0, 0, 0, &binfo);
+ bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+
+ /* Check that the base is unambiguous and accessible. */
+ if (access != ba_any)
+ switch (bk)
+ {
+ case bk_not_base:
+ break;
+
+ case bk_ambig:
+ binfo = NULL_TREE;
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an ambiguous base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ break;
+
+ default:
+ if (access != ba_ignore
+ /* If BASE is incomplete, then BASE and TYPE are probably
+ the same, in which case BASE is accessible. If they
+ are not the same, then TYPE is invalid. In that case,
+ there's no need to issue another error here, and
+ there's no implicit typedef to use in the code that
+ follows, so we skip the check. */
+ && COMPLETE_TYPE_P (base))
+ {
+ tree decl;
+
+ /* [class.access.base]
+
+ A base class is said to be accessible if an invented public
+ member of the base class is accessible. */
+ /* Rather than inventing a public member, we use the implicit
+ public typedef created in the scope of every class. */
+ decl = TYPE_FIELDS (base);
+ while (TREE_CODE (decl) != TYPE_DECL
+ || !DECL_ARTIFICIAL (decl)
+ || DECL_NAME (decl) != constructor_name (base))
+ decl = TREE_CHAIN (decl);
+ while (ANON_AGGR_TYPE_P (t))
+ t = TYPE_CONTEXT (t);
+ if (!accessible_p (t, decl))
+ {
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an inaccessible base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ else
+ binfo = NULL_TREE;
+ bk = bk_inaccessible;
+ }
+ }
+ break;
+ }
- switch (bk)
- {
- case bk_inaccessible:
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an inaccessible base of `%T'", base, t);
- binfo = error_mark_node;
- }
- break;
- case bk_ambig:
- if (access != ba_any)
- {
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an ambiguous base of `%T'", base, t);
- binfo = error_mark_node;
- }
- }
- break;
- default:;
- }
-
if (kind_ptr)
*kind_ptr = bk;
@@ -444,9 +442,8 @@ get_dynamic_cast_base_type (subtype, target)
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
-static tree
-lookup_field_1 (type, name)
- tree type, name;
+tree
+lookup_field_1 (tree type, tree name, bool want_type)
{
register tree field;
@@ -483,14 +480,28 @@ lookup_field_1 (type, name)
lo = i + 1;
else
{
+ field = NULL_TREE;
+
/* We might have a nested class and a field with the
same name; we sorted them appropriately via
- field_decl_cmp, so just look for the last field with
- this name. */
- while (i + 1 < hi
- && DECL_NAME (fields[i+1]) == name)
- ++i;
- return fields[i];
+ field_decl_cmp, so just look for the first or last
+ field with this name. */
+ if (want_type)
+ {
+ do
+ field = fields[i--];
+ while (i >= lo && DECL_NAME (fields[i]) == name);
+ if (TREE_CODE (field) != TYPE_DECL
+ && !DECL_CLASS_TEMPLATE_P (field))
+ field = NULL_TREE;
+ }
+ else
+ {
+ do
+ field = fields[i++];
+ while (i < hi && DECL_NAME (fields[i]) == name);
+ }
+ return field;
}
}
return NULL_TREE;
@@ -501,7 +512,7 @@ lookup_field_1 (type, name)
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
#endif /* GATHER_STATISTICS */
- while (field)
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
@@ -510,7 +521,7 @@ lookup_field_1 (type, name)
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
- tree temp = lookup_field_1 (TREE_TYPE (field), name);
+ tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
if (temp)
return temp;
}
@@ -520,10 +531,13 @@ lookup_field_1 (type, name)
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)
+ continue;
+
+ if (DECL_NAME (field) == name
+ && (!want_type
+ || TREE_CODE (field) == TYPE_DECL
+ || DECL_CLASS_TEMPLATE_P (field)))
return field;
- field = TREE_CHAIN (field);
}
/* Not found. */
if (name == vptr_identifier)
@@ -569,7 +583,7 @@ current_scope ()
return current_class_type;
}
-/* Returns non-zero if we are currently in a function scope. Note
+/* Returns nonzero if we are currently in a function scope. Note
that this function returns zero if we are within a local class, but
not within a member function body of the local class. */
@@ -580,6 +594,15 @@ at_function_scope_p ()
return cs && TREE_CODE (cs) == FUNCTION_DECL;
}
+/* Returns true if the innermost active scope is a class scope. */
+
+bool
+at_class_scope_p ()
+{
+ tree cs = current_scope ();
+ return cs && TYPE_P (cs);
+}
+
/* Return the scope of DECL, as appropriate when doing name-lookup. */
tree
@@ -845,7 +868,7 @@ dfs_accessible_p (binfo, data)
return NULL_TREE;
}
-/* Returns non-zero if it is OK to access DECL through an object
+/* Returns nonzero if it is OK to access DECL through an object
indiated by BINFO in the context of DERIVED. */
static int
@@ -908,7 +931,7 @@ protected_accessible_p (decl, derived, binfo)
return 1;
}
-/* Returns non-zero if SCOPE is a friend of a type which would be able
+/* Returns nonzero if SCOPE is a friend of a type which would be able
to access DECL through the object indicated by BINFO. */
static int
@@ -961,8 +984,8 @@ friend_accessible_p (scope, decl, binfo)
return 0;
}
-/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
- This is fairly complex, so here's the design:
+/* Perform access control on TYPE_DECL or TEMPLATE_DECL VAL, which was
+ looked up in TYPE. This is fairly complex, so here's the design:
The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
start to process a top-level declaration.
@@ -985,7 +1008,8 @@ void
type_access_control (type, val)
tree type, val;
{
- if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
+ if (val == NULL_TREE
+ || (TREE_CODE (val) != TEMPLATE_DECL && TREE_CODE (val) != TYPE_DECL)
|| ! DECL_CLASS_SCOPE_P (val))
return;
@@ -996,7 +1020,7 @@ type_access_control (type, val)
}
/* DECL is a declaration from a base class of TYPE, which was the
- class used to name DECL. Return non-zero if, in the current
+ class used to name DECL. Return nonzero 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. */
@@ -1010,7 +1034,7 @@ accessible_p (type, decl)
tree binfo;
tree t;
- /* Non-zero if it's OK to access DECL if it has protected
+ /* Nonzero if it's OK to access DECL if it has protected
accessibility in TYPE. */
int protected_ok = 0;
@@ -1081,13 +1105,11 @@ accessible_p (type, decl)
return t != NULL_TREE;
}
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
- found as a base class and sub-object of the object denoted by
- BINFO. MOST_DERIVED is the most derived type of the hierarchy being
- searched. */
+/* Recursive helper funciton for is_subobject_of_p; see that routine
+ for documentation of the parameters. */
static int
-is_subobject_of_p (parent, binfo, most_derived)
+is_subobject_of_p_1 (parent, binfo, most_derived)
tree parent, binfo, most_derived;
{
tree binfos;
@@ -1099,23 +1121,54 @@ is_subobject_of_p (parent, binfo, most_derived)
binfos = BINFO_BASETYPES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- /* Iterate the base types. */
+ /* Iterate through the base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (!CLASS_TYPE_P (TREE_TYPE (base_binfo)))
+ tree base_type;
+
+ base_type = TREE_TYPE (base_binfo);
+ if (!CLASS_TYPE_P (base_type))
/* 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,
- CANONICAL_BINFO (base_binfo, most_derived),
- most_derived))
+ /* Avoid walking into the same virtual base more than once. */
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ {
+ if (CLASSTYPE_MARKED4 (base_type))
+ continue;
+ SET_CLASSTYPE_MARKED4 (base_type);
+ base_binfo = binfo_for_vbase (base_type, most_derived);
+ }
+
+ if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
return 1;
}
return 0;
}
+/* Routine to see if the sub-object denoted by the binfo PARENT can be
+ found as a base class and sub-object of the object denoted by
+ BINFO. MOST_DERIVED is the most derived type of the hierarchy being
+ searched. */
+
+static int
+is_subobject_of_p (tree parent, tree binfo, tree most_derived)
+{
+ int result;
+ tree vbase;
+
+ result = is_subobject_of_p_1 (parent, binfo, most_derived);
+ /* Clear the mark bits on virtual bases. */
+ for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
+
+ return result;
+}
+
struct lookup_field_info {
/* The type in which we're looking. */
tree type;
@@ -1128,15 +1181,15 @@ struct lookup_field_info {
/* 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. */
+ /* If nonzero, we are looking for types, not data members. */
int want_type;
- /* If non-zero, RVAL was found by looking through a dependent base. */
+ /* If nonzero, 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
+/* Returns nonzero 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. */
@@ -1154,11 +1207,12 @@ lookup_field_queue_p (binfo, data)
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
+ binfo = CANONICAL_BINFO (binfo, lfi->type);
if (!lfi->from_dep_base_p && lfi->rval_binfo
&& is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
return NULL_TREE;
- return CANONICAL_BINFO (binfo, lfi->type);
+ return binfo;
}
/* Within the scope of a template class, you can refer to the to the
@@ -1167,7 +1221,7 @@ lookup_field_queue_p (binfo, data)
template <typename T> struct S { S* sp; }
- Returns non-zero if DECL is such a declaration in a class TYPE. */
+ Returns nonzero if DECL is such a declaration in a class TYPE. */
static int
template_self_reference_p (type, decl)
@@ -1239,7 +1293,7 @@ lookup_field_r (binfo, data)
if (!nval)
/* Look for a data member or type. */
- nval = lookup_field_1 (type, lfi->name);
+ nval = lookup_field_1 (type, lfi->name, lfi->want_type);
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
@@ -1264,11 +1318,12 @@ lookup_field_r (binfo, data)
}
else
nval = NULL_TREE;
- if (!nval)
+ if (!nval && CLASSTYPE_NESTED_UDTS (type) != NULL)
{
- nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
- if (nval)
- nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+ binding_entry e = binding_table_find (CLASSTYPE_NESTED_UDTS (type),
+ lfi->name);
+ if (e != NULL)
+ nval = TYPE_MAIN_DECL (e->type);
else
return NULL_TREE;
}
@@ -1354,16 +1409,44 @@ lookup_field_r (binfo, data)
return NULL_TREE;
}
+/* Return a "baselink" which BASELINK_BINFO, BASELINK_ACCESS_BINFO,
+ BASELINK_FUNCTIONS, and BASELINK_OPTYPE set to BINFO, ACCESS_BINFO,
+ FUNCTIONS, and OPTYPE respectively. */
+
+tree
+build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
+{
+ tree baselink;
+
+ my_friendly_assert (TREE_CODE (functions) == FUNCTION_DECL
+ || TREE_CODE (functions) == TEMPLATE_DECL
+ || TREE_CODE (functions) == TEMPLATE_ID_EXPR
+ || TREE_CODE (functions) == OVERLOAD,
+ 20020730);
+ my_friendly_assert (!optype || TYPE_P (optype), 20020730);
+ my_friendly_assert (TREE_TYPE (functions), 20020805);
+
+ baselink = build (BASELINK, TREE_TYPE (functions), NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ BASELINK_BINFO (baselink) = binfo;
+ BASELINK_ACCESS_BINFO (baselink) = access_binfo;
+ BASELINK_FUNCTIONS (baselink) = functions;
+ BASELINK_OPTYPE (baselink) = optype;
+
+ return baselink;
+}
+
/* Look for a member named NAME in an inheritance lattice dominated by
- XBASETYPE. If 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
- TREE_TYPE is error_mark_node and whose TREE_VALUEs are the list of
- ambiguous candidates.
+ XBASETYPE. If 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 error
+ messages about inaccessible or ambiguous lookup. If PROTECT is 2,
+ we return a TREE_LIST whose TREE_TYPE is error_mark_node and whose
+ TREE_VALUEs are the list of ambiguous candidates.
+
+ WANT_TYPE is 1 when we should only return TYPE_DECLs.
- WANT_TYPE is 1 when we should only return TYPE_DECLs, if no
- TYPE_DECL can be found return NULL_TREE. */
+ If nothing can be found return NULL_TREE and do not issue an error. */
tree
lookup_member (xbasetype, name, protect, want_type)
@@ -1387,7 +1470,7 @@ lookup_member (xbasetype, name, protect, want_type)
&& IDENTIFIER_CLASS_VALUE (name))
{
tree field = IDENTIFIER_CLASS_VALUE (name);
- if (TREE_CODE (field) != FUNCTION_DECL
+ if (! is_overloaded_fn (field)
&& ! (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. */
@@ -1463,19 +1546,9 @@ lookup_member (xbasetype, name, protect, want_type)
TREE_TYPE (rval)));
if (rval && is_overloaded_fn (rval))
- {
- /* Note that the binfo we put in the baselink is the binfo where
- we found the functions, which we need for overload
- resolution, but which should not be passed to enforce_access;
- rather, enforce_access wants a binfo which refers to the
- scope in which we started looking for the function. This
- will generally be the binfo passed into this function as
- xbasetype. */
-
- rval = tree_cons (rval_binfo, rval, NULL_TREE);
- SET_BASELINK_P (rval);
- }
-
+ rval = build_baselink (rval_binfo, basetype_path, rval,
+ (IDENTIFIER_TYPENAME_P (name)
+ ? TREE_TYPE (name): NULL_TREE));
return rval;
}
@@ -1490,7 +1563,7 @@ lookup_field (xbasetype, name, protect, want_type)
tree rval = lookup_member (xbasetype, name, protect, want_type);
/* Ignore functions. */
- if (rval && TREE_CODE (rval) == TREE_LIST)
+ if (rval && BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -1507,7 +1580,7 @@ lookup_fnfields (xbasetype, name, protect)
tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
/* Ignore non-functions. */
- if (rval && TREE_CODE (rval) != TREE_LIST)
+ if (rval && !BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -1577,100 +1650,192 @@ lookup_nested_field (name, complain)
return id;
}
+/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
+ corresponding to "operator TYPE ()", or -1 if there is no such
+ operator. Only CLASS_TYPE itself is searched; this routine does
+ not scan the base classes of CLASS_TYPE. */
+
+static int
+lookup_conversion_operator (tree class_type, tree type)
+{
+ int pass;
+ int i;
+
+ tree methods = CLASSTYPE_METHOD_VEC (class_type);
+
+ for (pass = 0; pass < 2; ++pass)
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ i < TREE_VEC_LENGTH (methods);
+ ++i)
+ {
+ tree fn = TREE_VEC_ELT (methods, i);
+ /* The size of the vector may have some unused slots at the
+ end. */
+ if (!fn)
+ break;
+
+ /* All the conversion operators come near the beginning of the
+ class. Therefore, if FN is not a conversion operator, there
+ is no matching conversion operator in CLASS_TYPE. */
+ fn = OVL_CURRENT (fn);
+ if (!DECL_CONV_FN_P (fn))
+ break;
+
+ if (pass == 0)
+ {
+ /* On the first pass we only consider exact matches. If
+ the types match, this slot is the one where the right
+ conversion operators can be found. */
+ if (TREE_CODE (fn) != TEMPLATE_DECL
+ && same_type_p (DECL_CONV_FN_TYPE (fn), type))
+ return i;
+ }
+ else
+ {
+ /* On the second pass we look for template conversion
+ operators. It may be possible to instantiate the
+ template to get the type desired. All of the template
+ conversion operators share a slot. By looking for
+ templates second we ensure that specializations are
+ preferred over templates. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
/* 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. */
int
-lookup_fnfields_1 (type, name)
- tree type, name;
+lookup_fnfields_1 (tree type, tree name)
{
- tree method_vec
- = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
+ tree method_vec;
+ tree *methods;
+ tree tmp;
+ int i;
+ int len;
- if (method_vec != 0)
- {
- register int i;
- register tree *methods = &TREE_VEC_ELT (method_vec, 0);
- int len = TREE_VEC_LENGTH (method_vec);
- tree tmp;
+ if (!CLASS_TYPE_P (type))
+ return -1;
+
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+
+ if (!method_vec)
+ return -1;
+
+ methods = &TREE_VEC_ELT (method_vec, 0);
+ len = TREE_VEC_LENGTH (method_vec);
#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields_1++;
+ n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
- /* Constructors are first... */
- if (name == ctor_identifier)
- return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
- ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
- /* and destructors are second. */
- if (name == dtor_identifier)
- return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
- ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
-
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < len && methods[i];
- ++i)
+ /* Constructors are first... */
+ if (name == ctor_identifier)
+ return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
+ ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
+ /* and destructors are second. */
+ if (name == dtor_identifier)
+ return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
+ ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
+ if (IDENTIFIER_TYPENAME_P (name))
+ return lookup_conversion_operator (type, TREE_TYPE (name));
+
+ /* Skip the conversion operators. */
+ i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
+ i++;
+
+ /* If the type is complete, use binary search. */
+ if (COMPLETE_TYPE_P (type))
+ {
+ int lo = i;
+ int hi = len;
+
+ while (lo < hi)
{
+ i = (lo + hi) / 2;
+
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
- tmp = OVL_CURRENT (methods[i]);
- if (DECL_NAME (tmp) == name)
+ tmp = methods[i];
+ /* This slot may be empty; we allocate more slots than we
+ need. In that case, the entry we're looking for is
+ closer to the beginning of the list. */
+ if (tmp)
+ tmp = DECL_NAME (OVL_CURRENT (tmp));
+ if (!tmp || tmp > name)
+ hi = i;
+ else if (tmp < name)
+ lo = i + 1;
+ else
return i;
+ }
+ }
+ else
+ for (; i < len && methods[i]; ++i)
+ {
+#ifdef GATHER_STATISTICS
+ n_outer_fields_searched++;
+#endif /* GATHER_STATISTICS */
- /* If the type is complete and we're past the conversion ops,
- switch to binary search. */
- if (! DECL_CONV_FN_P (tmp)
- && COMPLETE_TYPE_P (type))
- {
- int lo = i + 1, hi = len;
+ tmp = OVL_CURRENT (methods[i]);
+ if (DECL_NAME (tmp) == name)
+ return i;
+ }
- while (lo < hi)
- {
- i = (lo + hi) / 2;
+ return -1;
+}
-#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
-#endif /* GATHER_STATISTICS */
+/* DECL is the result of a qualified name lookup. QUALIFYING_CLASS
+ was the class used to qualify the name. CONTEXT_CLASS is the class
+ corresponding to the object in which DECL will be used. Return a
+ possibly modified version of DECL that takes into account the
+ CONTEXT_CLASS.
- tmp = DECL_NAME (OVL_CURRENT (methods[i]));
+ In particular, consider an expression like `B::m' in the context of
+ a derived class `D'. If `B::m' has been resolved to a BASELINK,
+ then the most derived class indicated by the BASELINK_BINFO will be
+ `B', not `D'. This function makes that adjustment. */
- if (tmp > name)
- hi = i;
- else if (tmp < name)
- lo = i + 1;
- else
- return i;
- }
- break;
- }
- }
+tree
+adjust_result_of_qualified_name_lookup (tree decl,
+ tree qualifying_class,
+ tree context_class)
+{
+ my_friendly_assert (CLASS_TYPE_P (qualifying_class), 20020808);
+ my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
- /* 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 (IDENTIFIER_TYPENAME_P (name))
+ if (BASELINK_P (decl)
+ && DERIVED_FROM_P (qualifying_class, context_class))
+ {
+ tree base;
+
+ /* Look for the QUALIFYING_CLASS as a base of the CONTEXT_CLASS.
+ Because we do not yet know which function will be chosen by
+ overload resolution, we cannot yet check either accessibility
+ or ambiguity -- in either case, the choice of a static member
+ function might make the usage valid. */
+ base = lookup_base (context_class, qualifying_class,
+ ba_ignore | ba_quiet, NULL);
+ if (base)
{
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < len && methods[i];
- ++i)
- {
- tmp = OVL_CURRENT (methods[i]);
- if (! DECL_CONV_FN_P (tmp))
- {
- /* Since all conversion operators come first, we know
- there is no such operator. */
- break;
- }
- else if (TREE_CODE (tmp) == TEMPLATE_DECL)
- return i;
- }
+ BASELINK_ACCESS_BINFO (decl) = base;
+ BASELINK_BINFO (decl)
+ = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
+ ba_ignore | ba_quiet,
+ NULL);
}
}
- return -1;
+ return decl;
}
+
/* Walk the class hierarchy dominated by TYPE. FN is called for each
type in the hierarchy, in a breadth-first preorder traversal.
@@ -1678,7 +1843,7 @@ lookup_fnfields_1 (type, name)
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. Before each base-class is walked QFN is called. If the
- value returned is non-zero, the base-class is walked; otherwise it
+ value returned is nonzero, 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. */
@@ -1739,9 +1904,6 @@ bfs_walk (binfo, fn, qfn, data)
}
}
- /* Clean up. */
- VARRAY_FREE (bfs_bases);
-
return rval;
}
@@ -1918,7 +2080,7 @@ check_final_overrider (overrider, basefn)
virtual functions in TYPE's hierarchy which FNDECL overrides.
We do not look in TYPE itself, only its bases.
- Returns non-zero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
+ Returns nonzero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
find that it overrides anything.
We check that every function which is overridden, is correctly
@@ -1944,9 +2106,8 @@ look_for_overrides (type, fndecl)
return found;
}
-/* Look in TYPE for virtual functions with the same signature as FNDECL.
- This differs from get_matching_virtual in that it will only return
- a function from TYPE. */
+/* Look in TYPE for virtual functions with the same signature as
+ FNDECL. */
tree
look_for_overrides_here (type, fndecl)
@@ -1985,7 +2146,7 @@ look_for_overrides_here (type, fndecl)
}
/* Look in TYPE for virtual functions overridden by FNDECL. Check both
- TYPE itself and its bases. */
+ TYPE itself and its bases. */
static int
look_for_overrides_r (type, fndecl)
@@ -2473,7 +2634,7 @@ setup_class_bindings (name, type_binding_p)
{
if (BASELINK_P (value_binding))
/* NAME is some overloaded functions. */
- value_binding = TREE_VALUE (value_binding);
+ value_binding = BASELINK_FUNCTIONS (value_binding);
pushdecl_class_level (value_binding);
}
}
@@ -2525,7 +2686,8 @@ dfs_push_decls (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (DECL_NAME (fields)
&& TREE_CODE (fields) != TYPE_DECL
- && TREE_CODE (fields) != USING_DECL)
+ && TREE_CODE (fields) != USING_DECL
+ && !DECL_ARTIFICIAL (fields))
setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
else if (TREE_CODE (fields) == FIELD_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
@@ -2533,7 +2695,8 @@ dfs_push_decls (binfo, data)
method_vec = (CLASS_TYPE_P (type)
? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
- if (method_vec)
+
+ if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
{
tree *methods;
tree *end;
@@ -2542,7 +2705,7 @@ dfs_push_decls (binfo, data)
end = TREE_VEC_END (method_vec);
for (methods = &TREE_VEC_ELT (method_vec, 2);
- *methods && methods != end;
+ methods < end && *methods;
methods++)
setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
/*type_binding_p=*/0);
@@ -2586,7 +2749,7 @@ dfs_unuse_fields (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
TREE_USED (fields) = 0;
@@ -2693,8 +2856,8 @@ lookup_conversions (type)
tree t;
tree conversions = NULL_TREE;
- if (COMPLETE_TYPE_P (type))
- bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
+ complete_type (type);
+ bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
for (t = conversions; t; t = TREE_CHAIN (t))
IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
@@ -2785,7 +2948,7 @@ binfo_for_vtable (var)
}
/* If no secondary base classes matched, return the primary base, if
- there is one. */
+ there is one. */
if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (main_binfo)))
return get_primary_binfo (main_binfo);
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
index a6f9afb..110eb3a 100644
--- a/contrib/gcc/cp/semantics.c
+++ b/contrib/gcc/cp/semantics.c
@@ -56,8 +56,6 @@ static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree));
static void genrtl_eh_spec_block PARAMS ((tree));
static void genrtl_handler PARAMS ((tree));
-static void genrtl_ctor_stmt PARAMS ((tree));
-static void genrtl_subobject PARAMS ((tree));
static void genrtl_named_return_value PARAMS ((void));
static void cp_expand_stmt PARAMS ((tree));
static void genrtl_start_function PARAMS ((tree));
@@ -81,7 +79,7 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
(SUBSTMT) = (COND); \
} while (0)
-/* Returns non-zero if the current statement is a full expression,
+/* Returns nonzero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
@@ -99,7 +97,7 @@ stmt_tree
current_stmt_tree ()
{
return (cfun
- ? &cfun->language->x_stmt_tree
+ ? &cfun->language->base.x_stmt_tree
: &scope_chain->x_stmt_tree);
}
@@ -111,7 +109,7 @@ int
anon_aggr_type_p (node)
tree node;
{
- return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
+ return ANON_AGGR_TYPE_P (node);
}
/* Finish a scope. */
@@ -268,7 +266,6 @@ finish_then_clause (if_stmt)
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
- last_tree = if_stmt;
return if_stmt;
}
@@ -294,21 +291,8 @@ finish_else_clause (if_stmt)
void
finish_if_stmt ()
{
- do_poplevel ();
finish_stmt ();
-}
-
-void
-clear_out_block ()
-{
- /* If COND wasn't a declaration, clear out the
- block we made for it and start a new one here so the
- optimization in expand_end_loop will work. */
- if (getdecls () == NULL_TREE)
- {
- do_poplevel ();
- do_pushlevel ();
- }
+ do_poplevel ();
}
/* Begin a while-statement. Returns a newly created WHILE_STMT if
@@ -333,8 +317,29 @@ finish_while_stmt_cond (cond, while_stmt)
tree while_stmt;
{
cond = maybe_convert_cond (cond);
- FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
- clear_out_block ();
+ if (processing_template_decl)
+ /* Don't mess with condition decls in a template. */
+ FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
+ else if (getdecls () == NULL_TREE)
+ /* It was a simple condition; install it. */
+ WHILE_COND (while_stmt) = cond;
+ else
+ {
+ /* If there was a declaration in the condition, we can't leave it
+ there; transform
+ while (A x = 42) { }
+ to
+ while (true) { A x = 42; if (!x) break; } */
+ tree if_stmt;
+ WHILE_COND (while_stmt) = boolean_true_node;
+
+ if_stmt = begin_if_stmt ();
+ cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+ finish_if_stmt_cond (cond, if_stmt);
+ finish_break_stmt ();
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
}
/* Finish a while-statement, which may be given by WHILE_STMT. */
@@ -419,12 +424,12 @@ begin_for_stmt ()
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
- add_stmt (r);
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
note_level_for_for ();
}
+ add_stmt (r);
return r;
}
@@ -450,8 +455,29 @@ finish_for_cond (cond, for_stmt)
tree for_stmt;
{
cond = maybe_convert_cond (cond);
- FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
- clear_out_block ();
+ if (processing_template_decl)
+ /* Don't mess with condition decls in a template. */
+ FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
+ else if (getdecls () == NULL_TREE)
+ /* It was a simple condition; install it. */
+ FOR_COND (for_stmt) = cond;
+ else
+ {
+ /* If there was a declaration in the condition, we can't leave it
+ there; transform
+ for (; A x = 42;) { }
+ to
+ for (;;) { A x = 42; if (!x) break; } */
+ tree if_stmt;
+ FOR_COND (for_stmt) = NULL_TREE;
+
+ if_stmt = begin_if_stmt ();
+ cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+ finish_if_stmt_cond (cond, if_stmt);
+ finish_break_stmt ();
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
}
/* Finish the increment-EXPRESSION in a for-statement, which may be
@@ -504,9 +530,9 @@ tree
begin_switch_stmt ()
{
tree r;
+ do_pushlevel ();
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_stmt (r);
- do_pushlevel ();
return r;
}
@@ -562,11 +588,11 @@ finish_switch_stmt (switch_stmt)
{
RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
pop_switch ();
- do_poplevel ();
finish_stmt ();
+ do_poplevel ();
}
-/* Generate the RTL for T, which is a TRY_BLOCK. */
+/* Generate the RTL for T, which is a TRY_BLOCK. */
static void
genrtl_try_block (t)
@@ -603,7 +629,7 @@ genrtl_try_block (t)
}
}
-/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
+/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
static void
genrtl_eh_spec_block (t)
@@ -712,7 +738,7 @@ finish_function_handler_sequence (try_block)
check_handlers (TRY_HANDLERS (try_block));
}
-/* Generate the RTL for T, which is a HANDLER. */
+/* Generate the RTL for T, which is a HANDLER. */
static void
genrtl_handler (t)
@@ -781,22 +807,7 @@ finish_handler (handler)
RECHAIN_STMTS (handler, HANDLER_BODY (handler));
}
-/* Generate the RTL for T, which is a CTOR_STMT. */
-
-static void
-genrtl_ctor_stmt (t)
- tree t;
-{
- if (CTOR_BEGIN_P (t))
- begin_protect_partials ();
- else
- /* After this point, any exceptions will cause the
- destructor to be executed, so we no longer need to worry
- about destroying the various subobjects ourselves. */
- end_protect_partials ();
-}
-
-/* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the
+/* Begin a compound-statement. If HAS_NO_SCOPE is nonzero, the
compound-statement does not define a scope. Returns a new
COMPOUND_STMT if appropriate. */
@@ -835,7 +846,7 @@ begin_compound_stmt (has_no_scope)
}
/* Finish a compound-statement, which may be given by COMPOUND_STMT.
- If HAS_NO_SCOPE is non-zero, the compound statement does not define
+ If HAS_NO_SCOPE is nonzero, the compound statement does not define
a scope. */
tree
@@ -880,9 +891,6 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
tree r;
tree t;
- if (TREE_CHAIN (string))
- string = combine_strings (string);
-
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
{
@@ -927,7 +935,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
tree operand;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
- operand = TREE_VALUE (output_operands);
+ operand = TREE_VALUE (t);
if (!parse_output_constraint (&constraint,
i, ninputs, noutputs,
@@ -948,7 +956,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
DECL_RTL for the OPERAND -- which we don't have at this
point. */
if (!allows_reg && DECL_P (operand))
- mark_addressable (operand);
+ cxx_mark_addressable (operand);
}
}
@@ -980,38 +988,28 @@ finish_label_decl (name)
add_decl_stmt (decl);
}
-/* Generate the RTL for a SUBOBJECT. */
-
-static void
-genrtl_subobject (cleanup)
- tree cleanup;
-{
- add_partial_entry (cleanup);
-}
-
-/* We're in a constructor, and have just constructed a a subobject of
- *THIS. CLEANUP is code to run if an exception is thrown before the
- end of the current function is reached. */
+/* When DECL goes out of scope, make sure that CLEANUP is executed. */
void
-finish_subobject (cleanup)
+finish_decl_cleanup (decl, cleanup)
+ tree decl;
tree cleanup;
{
- tree r = build_stmt (SUBOBJECT, cleanup);
- add_stmt (r);
+ add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
}
-/* When DECL goes out of scope, make sure that CLEANUP is executed. */
+/* If the current scope exits with an exception, run CLEANUP. */
-void
-finish_decl_cleanup (decl, cleanup)
- tree decl;
+void
+finish_eh_cleanup (cleanup)
tree cleanup;
{
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
+ CLEANUP_EH_ONLY (r) = 1;
+ add_stmt (r);
}
-/* Generate the RTL for a RETURN_INIT. */
+/* Generate the RTL for a RETURN_INIT. */
static void
genrtl_named_return_value ()
@@ -1031,7 +1029,7 @@ genrtl_named_return_value ()
the return value. */
SET_DECL_RTL (decl, gen_reg_rtx (GET_MODE (DECL_RTL (decl))));
if (TREE_ADDRESSABLE (decl))
- put_var_into_stack (decl);
+ put_var_into_stack (decl, /*rescan=*/true);
}
emit_local_var (decl);
@@ -1093,67 +1091,30 @@ finish_named_return_value (return_id, init)
DECL_UNINLINABLE (current_function_decl) = 1;
}
-/* The INIT_LIST is a list of mem-initializers, in the order they were
- written by the user. The TREE_VALUE of each node is a list of
- initializers for a particular subobject. The TREE_PURPOSE is a
- FIELD_DECL is the initializer is for a non-static data member, and
- a class type if the initializer is for a base class. */
+/* Begin processing a mem-initializer-list. */
void
-finish_mem_initializers (init_list)
- tree init_list;
+begin_mem_initializers ()
{
- tree member_init_list;
- tree base_init_list;
- tree last_base_warned_about;
- tree next;
- tree init;
+ if (! DECL_CONSTRUCTOR_P (current_function_decl))
+ error ("only constructors take base initializers");
+}
- member_init_list = NULL_TREE;
- base_init_list = NULL_TREE;
- last_base_warned_about = NULL_TREE;
+/* The MEM_INITS is a list of mem-initializers, in reverse of the
+ order they were written by the user. Each node is as for
+ emit_mem_initializers. */
- for (init = init_list; init; init = next)
- {
- next = TREE_CHAIN (init);
- if (TREE_CODE (TREE_PURPOSE (init)) == FIELD_DECL)
- {
- TREE_CHAIN (init) = member_init_list;
- member_init_list = init;
-
- /* We're running through the initializers from right to left
- as we process them here. So, if we see a data member
- initializer after we see a base initializer, that
- actually means that the base initializer preceded the
- data member initializer. */
- if (warn_reorder && last_base_warned_about != base_init_list)
- {
- tree base;
-
- for (base = base_init_list;
- base != last_base_warned_about;
- base = TREE_CHAIN (base))
- {
- warning ("base initializer for `%T'",
- TREE_PURPOSE (base));
- warning (" will be re-ordered to precede member initializations");
- }
-
- last_base_warned_about = base_init_list;
- }
- }
- else
- {
- TREE_CHAIN (init) = base_init_list;
- base_init_list = init;
- }
- }
+void
+finish_mem_initializers (tree mem_inits)
+{
+ /* Reorder the MEM_INITS so that they are in the order they appeared
+ in the source program. */
+ mem_inits = nreverse (mem_inits);
if (processing_template_decl)
- add_stmt (build_min_nt (CTOR_INITIALIZER,
- member_init_list, base_init_list));
+ add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
else
- emit_base_init (member_init_list, base_init_list);
+ emit_mem_initializers (mem_inits);
}
/* Returns the stack of SCOPE_STMTs for the current function. */
@@ -1161,7 +1122,7 @@ finish_mem_initializers (init_list)
tree *
current_scope_stmt_stack ()
{
- return &cfun->language->x_scope_stmt_stack;
+ return &cfun->language->base.x_scope_stmt_stack;
}
/* Finish a parenthesized expression EXPR. */
@@ -1171,7 +1132,7 @@ finish_parenthesized_expr (expr)
tree expr;
{
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
- /* This inhibits warnings in truthvalue_conversion. */
+ /* This inhibits warnings in c_common_truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
if (TREE_CODE (expr) == OFFSET_REF)
@@ -1263,32 +1224,87 @@ finish_stmt_expr (rtl_expr)
return result;
}
-/* Finish a call to FN with ARGS. Returns a representation of the
- call. */
+/* Generate an expression for `FN (ARGS)'.
+
+ If DISALLOW_VIRTUAL is true, the call to FN will be not generated
+ as a virtual call, even if FN is virtual. (This flag is set when
+ encountering an expression where the function name is explicitly
+ qualified. For example a call to `X::f' never generates a virtual
+ call.)
+
+ Returns code for the call. */
tree
-finish_call_expr (fn, args, koenig)
- tree fn;
- tree args;
- int koenig;
+finish_call_expr (tree fn, tree args, bool disallow_virtual)
{
- tree result;
+ if (fn == error_mark_node || args == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl)
+ return build_nt (CALL_EXPR, fn, args, NULL_TREE);
- if (koenig)
+ /* ARGS should be a list of arguments. */
+ my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+ 20020712);
+
+ if (BASELINK_P (fn))
{
- if (TREE_CODE (fn) == BIT_NOT_EXPR)
- fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
- else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
- fn = do_identifier (fn, 2, args);
- }
- result = build_x_function_call (fn, args, current_class_ref);
+ tree object;
+
+ /* A call to a member function. From [over.call.func]:
+
+ If the keyword this is in scope and refers to the class of
+ that member function, or a derived class thereof, then the
+ function call is transformed into a qualified function call
+ using (*this) as the postfix-expression to the left of the
+ . operator.... [Otherwise] a contrived object of type T
+ becomes the implied object argument.
+
+ This paragraph is unclear about this situation:
+
+ struct A { void f(); };
+ struct B : public A {};
+ struct C : public A { void g() { B::f(); }};
+
+ In particular, for `B::f', this paragraph does not make clear
+ whether "the class of that member function" refers to `A' or
+ to `B'. We believe it refers to `B'. */
+ if (current_class_type
+ && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+ current_class_type)
+ && current_class_ref)
+ object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+ NULL);
+ else
+ {
+ tree representative_fn;
- if (TREE_CODE (result) == CALL_EXPR
- && (! TREE_TYPE (result)
- || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
- result = require_complete_type (result);
+ representative_fn = BASELINK_FUNCTIONS (fn);
+ if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
+ representative_fn = TREE_OPERAND (representative_fn, 0);
+ representative_fn = get_first_fn (representative_fn);
+ object = build_dummy_object (DECL_CONTEXT (representative_fn));
+ }
- return result;
+ return build_new_method_call (object, fn, args, NULL_TREE,
+ (disallow_virtual
+ ? LOOKUP_NONVIRTUAL : 0));
+ }
+ else if (is_overloaded_fn (fn))
+ /* A call to a namespace-scope function. */
+ return build_new_function_call (fn, args);
+ else if (CLASS_TYPE_P (TREE_TYPE (fn)))
+ {
+ /* If the "function" is really an object of class type, it might
+ have an overloaded `operator ()'. */
+ tree result;
+ result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+ if (result)
+ return result;
+ }
+
+ /* A call where the function is unknown. */
+ return build_function_call (fn, args);
}
/* Finish a call to a postfix increment or decrement or EXPR. (Which
@@ -1348,14 +1364,6 @@ finish_object_call_expr (fn, object, args)
tree object;
tree args;
{
-#if 0
- /* This is a future direction of this code, but because
- build_x_function_call cannot always undo what is done in
- build_component_ref entirely yet, we cannot do this. */
-
- tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
- return finish_call_expr (real_fn, args);
-#else
if (DECL_DECLARES_TYPE_P (fn))
{
if (processing_template_decl)
@@ -1374,9 +1382,11 @@ finish_object_call_expr (fn, object, args)
return error_mark_node;
}
}
-
- return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-#endif
+
+ if (processing_template_decl || name_p (fn))
+ return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+ else
+ return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
/* Finish a qualified member function call using OBJECT and ARGS as
@@ -1417,22 +1427,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
return cp_convert (void_type_node, object);
}
-/* Finish a call to a globally qualified member function FN using
- ARGS. Returns an expression for the call. */
-
-tree
-finish_qualified_call_expr (fn, args)
- tree fn;
- tree args;
-{
- if (processing_template_decl)
- return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
- else
- return build_member_call (TREE_OPERAND (fn, 0),
- TREE_OPERAND (fn, 1),
- args);
-}
-
/* Finish an expression of the form CODE EXPR. */
tree
@@ -1467,6 +1461,20 @@ finish_id_expr (expr)
return expr;
}
+/* Return the declaration for the function-name variable indicated by
+ ID. */
+
+tree
+finish_fname (tree id)
+{
+ tree decl;
+
+ decl = fname_decl (C_RID_CODE (id), id);
+ if (processing_template_decl)
+ decl = build_min_nt (LOOKUP_EXPR, DECL_NAME (decl));
+ return decl;
+}
+
static tree current_type_lookups;
/* Perform deferred access control for types used in the type of a
@@ -1524,20 +1532,17 @@ reset_type_access_control ()
current_type_lookups = NULL_TREE;
}
-/* Begin a function definition declared with DECL_SPECS and
- DECLARATOR. Returns non-zero if the function-declaration is
- legal. */
+/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
+ and DECLARATOR. Returns nonzero if the function-declaration is
+ valid. */
int
-begin_function_definition (decl_specs, declarator)
+begin_function_definition (decl_specs, attributes, declarator)
tree decl_specs;
+ tree attributes;
tree declarator;
{
- tree specs;
- tree attrs;
-
- split_specs_attrs (decl_specs, &specs, &attrs);
- if (!start_function (specs, declarator, attrs, SF_DEFAULT))
+ if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
return 0;
deferred_type_access_control ();
@@ -1589,7 +1594,7 @@ finish_translation_unit ()
while (current_namespace != global_namespace)
pop_namespace ();
- /* Do file scope __FUNCTION__ et al. */
+ /* Do file scope __FUNCTION__ et al. */
finish_fname_decls ();
finish_file ();
@@ -1632,8 +1637,27 @@ finish_template_template_parm (aggr, identifier)
return finish_template_type_parm (aggr, tmpl);
}
+/* ARGUMENT is the default-argument value for a template template
+ parameter. If ARGUMENT is invalid, issue error messages and return
+ the ERROR_MARK_NODE. Otherwise, ARGUMENT itself is returned. */
+
+tree
+check_template_template_default_arg (tree argument)
+{
+ if (TREE_CODE (argument) != TEMPLATE_DECL
+ && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (argument) != TYPE_DECL
+ && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+ {
+ error ("invalid default template argument");
+ return error_mark_node;
+ }
+
+ return argument;
+}
+
/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is
- non-zero, the parameter list was terminated by a `...'. */
+ nonzero, the parameter list was terminated by a `...'. */
tree
finish_parmlist (parms, ellipsis)
@@ -1661,7 +1685,7 @@ begin_class_definition (t)
if (t == error_mark_node)
return error_mark_node;
- /* Check the bases are accessible. */
+ /* Check the bases are accessible. */
decl_type_access_control (TYPE_NAME (t));
reset_type_access_control ();
@@ -1731,7 +1755,8 @@ begin_class_definition (t)
TYPE_BINFO_BASETYPES (t) = NULL_TREE;
TYPE_FIELDS (t) = NULL_TREE;
TYPE_METHODS (t) = NULL_TREE;
- CLASSTYPE_TAGS (t) = NULL_TREE;
+ CLASSTYPE_DECL_LIST (t) = NULL_TREE;
+ CLASSTYPE_NESTED_UDTS (t) = NULL;
CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
TYPE_SIZE (t) = NULL_TREE;
}
@@ -1824,8 +1849,12 @@ finish_member_declaration (decl)
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
+
+ maybe_add_class_template_decl_list (current_class_type, decl,
+ /*friend_p=*/0);
}
- else
+ /* Enter the DECL into the scope of the class. */
+ else if (TREE_CODE (decl) == USING_DECL || pushdecl_class_level (decl))
{
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
go at the beginning. The reason is that lookup_field_1
@@ -1836,7 +1865,7 @@ finish_member_declaration (decl)
struct S { enum E { }; int E } s;
s.E = 3;
- is legal. In addition, the FIELD_DECLs must be maintained in
+ is valid. 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
@@ -1853,9 +1882,8 @@ finish_member_declaration (decl)
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);
+ maybe_add_class_template_decl_list (current_class_type, decl,
+ /*friend_p=*/0);
}
}
@@ -1912,16 +1940,6 @@ begin_inline_definitions ()
do_pending_inlines ();
}
-/* Finish processing the inline function definitions cached during the
- processing of a class definition. */
-
-void
-finish_inline_definitions ()
-{
- if (current_class_type == NULL_TREE)
- clear_inline_text_obstack ();
-}
-
/* Finish processing the declaration of a member class template
TYPES whose template parameters are given by PARMS. */
@@ -1969,7 +1987,7 @@ finish_template_decl (parms)
/* Finish processing 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
+ template-id. If ENTERING_SCOPE is nonzero we are about to enter
the scope of template-id indicated. */
tree
@@ -2030,7 +2048,12 @@ finish_base_specifier (access_specifier, base_class)
{
tree result;
- if (! is_aggr_type (base_class, 1))
+ if (base_class == error_mark_node)
+ {
+ error ("invalid base-class specification");
+ result = NULL_TREE;
+ }
+ else if (! is_aggr_type (base_class, 1))
result = NULL_TREE;
else
{
@@ -2058,11 +2081,9 @@ check_multiple_declarators ()
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,
+ condition since that would disallow the perfectly valid code,
like `template <class T> struct S { int i, j; };'. */
- tree scope = current_scope ();
-
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ if (at_function_scope_p ())
/* It's OK to write `template <class T> void f() { int i, j;}'. */
return;
@@ -2112,7 +2133,7 @@ finish_sizeof (t)
if (processing_template_decl)
return build_min_nt (SIZEOF_EXPR, t);
- return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t);
+ return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
}
/* Implement the __alignof keyword: Return the minimum required
@@ -2125,7 +2146,7 @@ finish_alignof (t)
if (processing_template_decl)
return build_min_nt (ALIGNOF_EXPR, t);
- return TYPE_P (t) ? c_alignof (complete_type (t)) : c_alignof_expr (t);
+ return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
}
/* Generate RTL for the statement T, and its substatements, and any
@@ -2137,10 +2158,6 @@ cp_expand_stmt (t)
{
switch (TREE_CODE (t))
{
- case CTOR_STMT:
- genrtl_ctor_stmt (t);
- break;
-
case TRY_BLOCK:
genrtl_try_block (t);
break;
@@ -2153,10 +2170,6 @@ cp_expand_stmt (t)
genrtl_handler (t);
break;
- case SUBOBJECT:
- genrtl_subobject (SUBOBJECT_CLEANUP (t));
- break;
-
case RETURN_INIT:
genrtl_named_return_value ();
break;
@@ -2211,7 +2224,7 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
{
/* Replace the first argument with the address of the third
argument to the AGGR_INIT_EXPR. */
- mark_addressable (slot);
+ cxx_mark_addressable (slot);
args = tree_cons (NULL_TREE,
build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (slot)),
@@ -2271,35 +2284,9 @@ emit_associated_thunks (fn)
enabling you to output all the thunks with the function itself. */
if (DECL_VIRTUAL_P (fn))
{
- tree binfo;
- tree v;
-
- for (binfo = TYPE_BINFO (DECL_CONTEXT (fn));
- binfo;
- binfo = TREE_CHAIN (binfo))
- for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
- if (BV_FN (v) == fn
- && (!integer_zerop (BV_DELTA (v))
- || BV_USE_VCALL_INDEX_P (v)))
- {
- tree thunk;
- tree vcall_index;
-
- if (BV_USE_VCALL_INDEX_P (v))
- {
- vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (vcall_index != NULL_TREE, 20000621);
- }
- else
- vcall_index = NULL_TREE;
-
- thunk = make_thunk (build1 (ADDR_EXPR,
- vfunc_ptr_type_node,
- fn),
- BV_DELTA (v),
- vcall_index);
- use_thunk (thunk, /*emit_p=*/1);
- }
+ tree thunk;
+ for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
+ use_thunk (thunk, /*emit_p=*/1);
}
}
@@ -2311,6 +2298,7 @@ expand_body (fn)
{
int saved_lineno;
const char *saved_input_filename;
+ tree saved_function;
/* When the parser calls us after finishing the body of a template
function, we don't really want to expand the body. When we're
@@ -2388,21 +2376,23 @@ expand_body (fn)
if (DECL_EXTERNAL (fn))
return;
- timevar_push (TV_INTEGRATION);
-
- /* Optimize the body of the function before expanding it. */
- optimize_function (fn);
-
- timevar_pop (TV_INTEGRATION);
- timevar_push (TV_EXPAND);
-
/* Save the current file name and line number. When we expand the
body of the function, we'll set LINENO and INPUT_FILENAME so that
error-mesages come out in the right places. */
saved_lineno = lineno;
saved_input_filename = input_filename;
+ saved_function = current_function_decl;
lineno = DECL_SOURCE_LINE (fn);
input_filename = DECL_SOURCE_FILE (fn);
+ current_function_decl = fn;
+
+ timevar_push (TV_INTEGRATION);
+
+ /* Optimize the body of the function before expanding it. */
+ optimize_function (fn);
+
+ timevar_pop (TV_INTEGRATION);
+ timevar_push (TV_EXPAND);
genrtl_start_function (fn);
current_function_is_thunk = DECL_THUNK_P (fn);
@@ -2435,6 +2425,7 @@ expand_body (fn)
DECL_SAVED_TREE (fn) = NULL_TREE;
/* And restore the current source position. */
+ current_function_decl = saved_function;
lineno = saved_lineno;
input_filename = saved_input_filename;
extract_interface_info ();
@@ -2462,7 +2453,7 @@ nullify_returns_r (tp, walk_subtrees, data)
if (TYPE_P (*tp))
*walk_subtrees = 0;
else if (TREE_CODE (*tp) == RETURN_STMT)
- RETURN_EXPR (*tp) = NULL_TREE;
+ RETURN_STMT_EXPR (*tp) = NULL_TREE;
else if (TREE_CODE (*tp) == CLEANUP_STMT
&& CLEANUP_DECL (*tp) == nrv)
CLEANUP_EH_ONLY (*tp) = 1;
@@ -2516,10 +2507,7 @@ genrtl_start_function (fn)
function; we need the named return value info for
cp_copy_res_decl_for_inlining. */
if (! DECL_INLINE (fn))
- {
- free (DECL_SAVED_FUNCTION_DATA (fn));
- DECL_SAVED_FUNCTION_DATA (fn) = NULL;
- }
+ DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
/* Keep track of how many functions we're presently expanding. */
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c
index 278a99a..5bd3fdf 100644
--- a/contrib/gcc/cp/spew.c
+++ b/contrib/gcc/cp/spew.c
@@ -29,7 +29,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "c-lex.h"
+#include "c-pragma.h"
#include "lex.h"
#include "parse.h"
#include "flags.h"
@@ -50,12 +50,12 @@ Boston, MA 02111-1307, USA. */
backtracking. */
/* fifo of tokens recognized and available to parser. */
-struct token
+struct token GTY(())
{
/* The values for YYCHAR will fit in a short. */
short yychar;
unsigned int lineno;
- YYSTYPE yylval;
+ YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
};
/* Since inline methods can refer to text which has not yet been seen,
@@ -68,64 +68,82 @@ struct token
This function's FUNCTION_DECL will have a bit set in its common so
that we know to watch out for it. */
-struct unparsed_text
+#define TOKEN_CHUNK_SIZE 20
+struct token_chunk GTY(())
+{
+ struct token_chunk *next;
+ struct token toks[TOKEN_CHUNK_SIZE];
+};
+
+struct unparsed_text GTY(())
{
struct unparsed_text *next; /* process this one next */
tree decl; /* associated declaration */
- const char *filename; /* name of file we were processing */
- int lineno; /* line number we got the text from */
+ location_t locus; /* location we got the text from */
int interface; /* remembering interface_unknown and interface_only */
- struct token *pos; /* current position, when rescanning */
- struct token *limit; /* end of saved text */
+ struct token_chunk * tokens; /* Start of the token list. */
+
+ struct token_chunk *last_chunk; /* End of the token list. */
+ short last_pos; /* Number of tokens used in the last chunk of
+ TOKENS. */
+
+ short cur_pos; /* Current token in 'cur_chunk', when rescanning. */
+ struct token_chunk *cur_chunk; /* Current chunk, when rescanning. */
};
/* Stack of state saved off when we return to an inline method or
default argument that has been stored for later parsing. */
-struct feed
+struct feed GTY(())
{
struct unparsed_text *input;
- const char *filename;
- int lineno;
+ location_t locus;
int yychar;
- YYSTYPE yylval;
+ YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
int first_token;
- struct obstack token_obstack;
+ struct obstack GTY ((skip (""))) token_obstack;
struct feed *next;
-};
+};
-static struct obstack feed_obstack;
-static struct feed *feed;
+static GTY(()) struct feed *feed;
static SPEW_INLINE void do_aggr PARAMS ((void));
static SPEW_INLINE int identifier_type PARAMS ((tree));
static void scan_tokens PARAMS ((int));
static void feed_defarg PARAMS ((tree));
static void finish_defarg PARAMS ((void));
+static void yylexstring PARAMS ((struct token *));
static int read_token PARAMS ((struct token *));
static SPEW_INLINE int num_tokens PARAMS ((void));
static SPEW_INLINE struct token *nth_token PARAMS ((int));
-static SPEW_INLINE int add_token PARAMS ((struct token *));
+static SPEW_INLINE int next_token PARAMS ((struct token *));
static SPEW_INLINE int shift_token PARAMS ((void));
static SPEW_INLINE void push_token PARAMS ((struct token *));
static SPEW_INLINE void consume_token PARAMS ((void));
static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *));
static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *));
-static SPEW_INLINE void snarf_block PARAMS ((const char *, int));
+static SPEW_INLINE struct token * space_for_token
+ PARAMS ((struct unparsed_text *t));
+static SPEW_INLINE struct token * remove_last_token
+ PARAMS ((struct unparsed_text *t));
+static struct unparsed_text * alloc_unparsed_text
+ PARAMS ((const location_t *, tree decl, int interface));
+
+static void snarf_block PARAMS ((struct unparsed_text *t));
static tree snarf_defarg PARAMS ((void));
-static void snarf_parenthesized_expression PARAMS ((const char *, int));
+static void snarf_parenthesized_expression (struct unparsed_text *);
static int frob_id PARAMS ((int, int, tree *));
/* The list of inline functions being held off until we reach the end of
the current class declaration. */
-static struct unparsed_text *pending_inlines;
-static struct unparsed_text *pending_inlines_tail;
+static GTY(()) struct unparsed_text *pending_inlines;
+static GTY(()) struct unparsed_text *pending_inlines_tail;
/* The list of previously-deferred inline functions currently being parsed.
This exists solely to be a GC root. */
-static struct unparsed_text *processing_these_inlines;
+static GTY(()) struct unparsed_text *processing_these_inlines;
static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *));
@@ -152,52 +170,33 @@ extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
/* The token fifo lives in this obstack. */
-struct obstack token_obstack;
-int first_token;
-
-/* Sometimes we need to save tokens for later parsing. If so, they are
- stored on this obstack. */
-struct obstack inline_text_obstack;
-char *inline_text_firstobj;
+static struct obstack token_obstack;
+static int first_token;
/* When we see a default argument in a method declaration, we snarf it as
text using snarf_defarg. When we get up to namespace scope, we then go
through and parse all of them using do_pending_defargs. Since yacc
parsers are not reentrant, we retain defargs state in these two
variables so that subsequent calls to do_pending_defargs can resume
- where the previous call left off. DEFARG_FNS is a tree_list where
+ where the previous call left off. DEFARG_FNS is a tree_list where
the TREE_TYPE is the current_class_type, TREE_VALUE is the FUNCTION_DECL,
and TREE_PURPOSE is the list unprocessed dependent functions. */
-static tree defarg_fns; /* list of functions with unprocessed defargs */
-static tree defarg_parm; /* current default parameter */
-static tree defarg_depfns; /* list of unprocessed fns met during current fn. */
-static tree defarg_fnsdone; /* list of fns with circular defargs */
+/* list of functions with unprocessed defargs */
+static GTY(()) tree defarg_fns;
+/* current default parameter */
+static GTY(()) tree defarg_parm;
+/* list of unprocessed fns met during current fn. */
+static GTY(()) tree defarg_depfns;
+/* list of fns with circular defargs */
+static GTY(()) tree defarg_fnsdone;
/* Initialize obstacks. Called once, from cxx_init. */
void
init_spew ()
{
- gcc_obstack_init (&inline_text_obstack);
- inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
gcc_obstack_init (&token_obstack);
- gcc_obstack_init (&feed_obstack);
- ggc_add_tree_root (&defarg_fns, 1);
- ggc_add_tree_root (&defarg_parm, 1);
- ggc_add_tree_root (&defarg_depfns, 1);
- ggc_add_tree_root (&defarg_fnsdone, 1);
-
- ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *),
- mark_pending_inlines);
- ggc_add_root (&processing_these_inlines, 1, sizeof (struct unparsed_text *),
- mark_pending_inlines);
-}
-
-void
-clear_inline_text_obstack ()
-{
- obstack_free (&inline_text_obstack, inline_text_firstobj);
}
/* Subroutine of read_token. */
@@ -209,23 +208,8 @@ read_process_identifier (pyylval)
if (C_IS_RESERVED_WORD (id))
{
- /* Possibly replace the IDENTIFIER_NODE with a magic cookie.
- Can't put yylval.code numbers in ridpointers[]. Bleah. */
-
- switch (C_RID_CODE (id))
- {
- case RID_BITAND: pyylval->code = BIT_AND_EXPR; return '&';
- case RID_AND_EQ: pyylval->code = BIT_AND_EXPR; return ASSIGN;
- case RID_BITOR: pyylval->code = BIT_IOR_EXPR; return '|';
- case RID_OR_EQ: pyylval->code = BIT_IOR_EXPR; return ASSIGN;
- case RID_XOR: pyylval->code = BIT_XOR_EXPR; return '^';
- case RID_XOR_EQ: pyylval->code = BIT_XOR_EXPR; return ASSIGN;
- case RID_NOT_EQ: pyylval->code = NE_EXPR; return EQCOMPARE;
-
- default:
- pyylval->ttype = ridpointers[C_RID_CODE (id)];
- return C_RID_YYCODE (id);
- }
+ pyylval->ttype = ridpointers[C_RID_CODE (id)];
+ return C_RID_YYCODE (id);
}
/* Make sure that user does not collide with our internal naming
@@ -244,6 +228,41 @@ read_process_identifier (pyylval)
return IDENTIFIER;
}
+/* Concatenate strings before returning them to the parser. This isn't quite
+ as good as having it done in the lexer, but it's better than nothing. */
+
+static void
+yylexstring (t)
+ struct token *t;
+{
+ enum cpp_ttype next_type;
+ tree next;
+
+ next_type = c_lex (&next);
+ if (next_type == CPP_STRING || next_type == CPP_WSTRING)
+ {
+ varray_type strings;
+
+ VARRAY_TREE_INIT (strings, 32, "strings");
+ VARRAY_PUSH_TREE (strings, t->yylval.ttype);
+
+ do
+ {
+ VARRAY_PUSH_TREE (strings, next);
+ next_type = c_lex (&next);
+ }
+ while (next_type == CPP_STRING || next_type == CPP_WSTRING);
+
+ t->yylval.ttype = combine_strings (strings);
+ last_token_id = t->yylval.ttype;
+ }
+
+ /* We will have always read one token too many. */
+ _cpp_backup_tokens (parse_in, 1);
+
+ t->yychar = STRING;
+}
+
/* Read the next token from the input file. The token is written into
T, and its type number is returned. */
static int
@@ -325,7 +344,7 @@ read_token (t)
case CPP_EOF:
t->yychar = 0;
break;
-
+
case CPP_NAME:
t->yychar = read_process_identifier (&t->yylval);
break;
@@ -338,7 +357,7 @@ read_token (t)
case CPP_STRING:
case CPP_WSTRING:
- t->yychar = STRING;
+ yylexstring (t);
break;
default:
@@ -360,28 +379,28 @@ feed_input (input)
abort ();
#endif
- f = obstack_alloc (&feed_obstack, sizeof (struct feed));
+ f = ggc_alloc (sizeof (struct feed));
- /* The token list starts just after the struct unparsed_text in memory. */
- input->pos = (struct token *) (input + 1);
+ input->cur_chunk = input->tokens;
+ input->cur_pos = 0;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tfeeding %s:%d [%d tokens]\n",
- input->filename, input->lineno, input->limit - input->pos);
+ input->locus.file, input->locus.line, input->limit - input->pos);
#endif
f->input = input;
- f->filename = input_filename;
- f->lineno = lineno;
+ f->locus.file = input_filename;
+ f->locus.line = lineno;
f->yychar = yychar;
f->yylval = yylval;
f->first_token = first_token;
f->token_obstack = token_obstack;
f->next = feed;
- input_filename = input->filename;
- lineno = input->lineno;
+ input_filename = input->locus.file;
+ lineno = input->locus.line;
yychar = YYEMPTY;
yylval.ttype = NULL_TREE;
first_token = 0;
@@ -394,8 +413,8 @@ end_input ()
{
struct feed *f = feed;
- input_filename = f->filename;
- lineno = f->lineno;
+ input_filename = f->locus.file;
+ lineno = f->locus.line;
yychar = f->yychar;
yylval = f->yylval;
first_token = f->first_token;
@@ -403,48 +422,12 @@ end_input ()
token_obstack = f->token_obstack;
feed = f->next;
- obstack_free (&feed_obstack, f);
-
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno);
#endif
}
-/* GC callback to mark memory pointed to by the pending inline queue. */
-void
-mark_pending_inlines (pi)
- PTR pi;
-{
- struct unparsed_text *up = * (struct unparsed_text **)pi;
-
- while (up)
- {
- struct token *t = (struct token *) (up + 1);
- struct token *l = up->limit;
-
- while (t < l)
- {
- /* Some of the possible values for yychar use yylval.code
- instead of yylval.ttype. We only have to worry about
- yychars that could have been returned by read_token. */
- switch (t->yychar)
- {
- case '+': case '-': case '*': case '/':
- case '%': case '&': case '|': case '^':
- case '>': case '<': case LSHIFT: case RSHIFT:
- case ASSIGN: case MIN_MAX: case EQCOMPARE: case ARITHCOMPARE:
- t++;
- continue;
- }
- if (t->yylval.ttype)
- ggc_mark_tree (t->yylval.ttype);
- t++;
- }
- up = up->next;
- }
-}
-
/* Token queue management. */
/* Return the number of tokens available on the fifo. */
@@ -474,16 +457,24 @@ static const struct token Tpad = { EMPTY, 0 UNION_INIT_ZERO };
/* Copy the next token into T and return its value. */
static SPEW_INLINE int
-add_token (t)
+next_token (t)
struct token *t;
{
if (!feed)
return read_token (t);
- if (feed->input->pos < feed->input->limit)
+ if (feed->input->cur_chunk != feed->input->last_chunk
+ || feed->input->cur_pos != feed->input->last_pos)
{
- memcpy (t, feed->input->pos, sizeof (struct token));
- return (feed->input->pos++)->yychar;
+ if (feed->input->cur_pos == TOKEN_CHUNK_SIZE)
+ {
+ feed->input->cur_chunk = feed->input->cur_chunk->next;
+ feed->input->cur_pos = 0;
+ }
+ memcpy (t, feed->input->cur_chunk->toks + feed->input->cur_pos,
+ sizeof (struct token));
+ feed->input->cur_pos++;
+ return t->yychar;
}
return 0;
@@ -495,7 +486,7 @@ shift_token ()
{
size_t point = obstack_object_size (&token_obstack);
obstack_blank (&token_obstack, sizeof (struct token));
- return add_token ((struct token *) (obstack_base (&token_obstack) + point));
+ return next_token ((struct token *) (obstack_base (&token_obstack) + point));
}
/* Consume the next token out of the fifo. */
@@ -572,7 +563,7 @@ scan_tokens (n)
goto pad_tokens;
}
return;
-
+
pad_tokens:
while (num_tokens () <= n)
obstack_grow (&token_obstack, &Tpad, sizeof (struct token));
@@ -598,17 +589,17 @@ identifier_type (decl)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == TYPE_DECL)
return PTYPENAME;
- else if (looking_for_template)
+ else if (looking_for_template)
return PFUNCNAME;
}
if (looking_for_template && really_overloaded_fn (decl))
{
/* See through a baselink. */
- if (TREE_CODE (decl) == TREE_LIST)
- decl = TREE_VALUE (decl);
+ if (TREE_CODE (decl) == BASELINK)
+ decl = BASELINK_FUNCTIONS (decl);
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
- if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
+ if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
@@ -642,7 +633,7 @@ static SPEW_INLINE void
do_aggr ()
{
int yc1, yc2;
-
+
scan_tokens (2);
yc1 = nth_token (1)->yychar;
if (yc1 != tTYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
@@ -672,12 +663,12 @@ do_aggr ()
default:
abort ();
}
-}
+}
void
see_typename ()
{
- /* Only types expected, not even namespaces. */
+ /* Only types expected, not even namespaces. */
looking_for_typename = 2;
if (yychar < 0)
if ((yychar = yylex ()) < 0) yychar = 0;
@@ -732,7 +723,7 @@ yylex ()
{
case EMPTY:
/* This is a lexical no-op. */
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
@@ -751,7 +742,7 @@ yylex ()
case IDENTIFIER:
{
int peek;
-
+
scan_tokens (1);
peek = nth_token (1)->yychar;
yychr = frob_id (yychr, peek, &nth_token (0)->yylval.ttype);
@@ -763,7 +754,7 @@ yylex ()
case PTYPENAME:
case PTYPENAME_DEFN:
/* If we see a SCOPE next, restore the old value.
- Otherwise, we got what we want. */
+ Otherwise, we got what we want. */
looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
break;
@@ -824,13 +815,13 @@ yylex ()
yychar = yychr;
{
struct token *tok = nth_token (0);
-
+
yylval = tok->yylval;
if (tok->lineno)
lineno = tok->lineno;
}
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
@@ -841,7 +832,7 @@ yylex ()
}
/* Unget character CH from the input stream.
- If RESCAN is non-zero, then we want to `see' this
+ If RESCAN is nonzero, then we want to `see' this
character as the next input token. */
void
@@ -854,13 +845,6 @@ yyungetc (ch, rescan)
{
struct token fake;
- /* If we're putting back a brace, undo the change in indent_level
- from the first time we saw it. */
- if (ch == '{')
- indent_level--;
- else if (ch == '}')
- indent_level++;
-
fake.yychar = ch;
fake.yylval.ttype = 0;
fake.lineno = lineno;
@@ -883,7 +867,7 @@ frob_id (yyc, peek, idp)
{
tree trrr;
int old_looking_for_typename = 0;
-
+
if (peek == SCOPE)
{
/* Don't interfere with the setting from an 'aggr' prefix. */
@@ -903,7 +887,7 @@ frob_id (yyc, peek, idp)
case NSNAME:
case PTYPENAME:
/* If this got special lookup, remember it. In these
- cases, we know it can't be a declarator-id. */
+ cases, we know it can't be a declarator-id. */
if (got_scope || got_object)
*idp = trrr;
/* FALLTHROUGH */
@@ -1030,35 +1014,80 @@ process_next_inline (i)
extract_interface_info ();
}
}
+
+/* Create a new token at the end of the token list in T. */
+static SPEW_INLINE struct token *
+space_for_token (t)
+ struct unparsed_text *t;
+{
+ if (t->last_pos != TOKEN_CHUNK_SIZE)
+ return t->last_chunk->toks + (t->last_pos++);
+ t->last_chunk->next = ggc_alloc_cleared (sizeof (*t->last_chunk->next));
+ t->last_chunk = t->last_chunk->next;
+ t->last_chunk->next = NULL;
+
+ t->last_pos = 1;
+ return t->last_chunk->toks;
+}
+
+/* Shrink the token list in T by one token. */
+static SPEW_INLINE struct token *
+remove_last_token (t)
+ struct unparsed_text *t;
+{
+ struct token *result = t->last_chunk->toks + t->last_pos - 1;
+ if (t->last_pos == 0)
+ abort ();
+ t->last_pos--;
+ if (t->last_pos == 0 && t->last_chunk != t->tokens)
+ {
+ struct token_chunk *c;
+ c = t->tokens;
+ while (c->next != t->last_chunk)
+ c = c->next;
+ c->next = NULL;
+ t->last_chunk = c;
+ t->last_pos = ARRAY_SIZE (c->toks);
+ }
+ return result;
+}
+
+/* Allocate an 'unparsed_text' structure, ready to use space_for_token. */
+static struct unparsed_text *
+alloc_unparsed_text (locus, decl, interface)
+ const location_t *locus;
+ tree decl;
+ int interface;
+{
+ struct unparsed_text *r;
+ r = ggc_alloc_cleared (sizeof (*r));
+ r->decl = decl;
+ r->locus = *locus;
+ r->interface = interface;
+ r->tokens = r->last_chunk = ggc_alloc_cleared (sizeof (*r->tokens));
+ return r;
+}
/* Accumulate the tokens that make up a parenthesized expression in T,
having already read the opening parenthesis. */
static void
-snarf_parenthesized_expression (starting_file, starting_line)
- const char *starting_file;
- int starting_line;
+snarf_parenthesized_expression (struct unparsed_text *t)
{
int yyc;
int level = 1;
while (1)
{
- size_t point;
-
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (t));
if (yyc == '(')
++level;
else if (yyc == ')' && --level == 0)
break;
else if (yyc == 0)
{
- error_with_file_and_line (starting_file, starting_line,
- "end of file read inside definition");
+ error ("%Hend of file read inside definition", &t->locus);
break;
}
}
@@ -1066,22 +1095,19 @@ snarf_parenthesized_expression (starting_file, starting_line)
/* Subroutine of snarf_method, deals with actual absorption of the block. */
-static SPEW_INLINE void
-snarf_block (starting_file, starting_line)
- const char *starting_file;
- int starting_line;
+static void
+snarf_block (t)
+ struct unparsed_text *t;
{
int blev = 1;
int look_for_semicolon = 0;
int look_for_lbrac = 0;
int look_for_catch = 0;
int yyc;
- struct token tmp;
- size_t point;
+ struct token *current;
if (yychar == '{')
- /* We incremented indent_level in yylex; undo that. */
- indent_level--;
+ ;
else if (yychar == '=')
look_for_semicolon = 1;
else if (yychar == ':' || yychar == RETURN_KEYWORD || yychar == TRY)
@@ -1095,17 +1121,14 @@ snarf_block (starting_file, starting_line)
yyerror ("parse error in method specification");
/* The current token is the first one to be recorded. */
- tmp.yychar = yychar;
- tmp.yylval = yylval;
- tmp.lineno = lineno;
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+ current = space_for_token (t);
+ current->yychar = yychar;
+ current->yylval = yylval;
+ current->lineno = lineno;
for (;;)
{
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (t));
if (yyc == '{')
{
@@ -1119,39 +1142,40 @@ snarf_block (starting_file, starting_line)
{
if (!look_for_catch)
break;
-
- if (add_token (&tmp) != CATCH)
+
+ if (next_token (space_for_token (t)) != CATCH)
{
- push_token (&tmp);
+ push_token (remove_last_token (t));
break;
}
look_for_lbrac = 1;
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
}
}
else if (yyc == ';')
{
if (look_for_lbrac)
{
+ struct token *fake;
+
error ("function body for constructor missing");
/* fake a { } to avoid further errors */
- tmp.yylval.ttype = 0;
- tmp.yychar = '{';
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
- tmp.yychar = '}';
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+ fake = space_for_token (t);
+ fake->yylval.ttype = 0;
+ fake->yychar = '{';
+ fake = space_for_token (t);
+ fake->yylval.ttype = 0;
+ fake->yychar = '}';
break;
}
else if (look_for_semicolon && blev == 0)
break;
}
else if (yyc == '(' && blev == 0)
- snarf_parenthesized_expression (starting_file, starting_line);
+ snarf_parenthesized_expression (t);
else if (yyc == 0)
{
- error_with_file_and_line (starting_file, starting_line,
- "end of file read inside definition");
+ error ("%Hend of file read inside definition", &t->locus);
break;
}
}
@@ -1163,60 +1187,43 @@ void
snarf_method (decl)
tree decl;
{
- int starting_lineno = lineno;
- const char *starting_filename = input_filename;
- size_t len;
- int i;
-
struct unparsed_text *meth;
+ location_t starting;
+ starting.file = input_filename;
+ starting.line = lineno;
- /* Leave room for the header, then absorb the block. */
- obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
- snarf_block (starting_filename, starting_lineno);
+ meth = alloc_unparsed_text (&starting, decl, (interface_unknown ? 1
+ : (interface_only ? 0 : 2)));
+
+ snarf_block (meth);
/* Add three END_OF_SAVED_INPUT tokens. We used to provide an
infinite stream of END_OF_SAVED_INPUT tokens -- but that can
cause the compiler to get stuck in an infinite loop when
encountering invalid code. We need more than one because the
parser sometimes peeks ahead several tokens. */
- for (i = 0; i < 3; ++i)
- {
- size_t point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- memcpy ((struct token *)
- (obstack_base (&inline_text_obstack) + point),
- &Teosi,
- sizeof (struct token));
- }
-
- len = obstack_object_size (&inline_text_obstack);
- meth = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
/* Happens when we get two declarations of the same function in the
same scope. */
if (decl == void_type_node
|| (current_class_type && TYPE_REDEFINED (current_class_type)))
- {
- obstack_free (&inline_text_obstack, (char *)meth);
- return;
- }
-
- meth->decl = decl;
- meth->filename = starting_filename;
- meth->lineno = starting_lineno;
- meth->limit = (struct token *) ((char *)meth + len);
- meth->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
- meth->next = 0;
+ return;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n",
- meth->limit - (struct token *) (meth + 1),
- starting_filename, starting_lineno);
+ meth->limit, starting.file, starting.line);
#endif
DECL_PENDING_INLINE_INFO (decl) = meth;
DECL_PENDING_INLINE_P (decl) = 1;
+ /* We need to know that this was defined in the class, so that
+ friend templates are handled correctly. */
+ DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
+
if (pending_inlines_tail)
pending_inlines_tail->next = meth;
else
@@ -1224,30 +1231,25 @@ snarf_method (decl)
pending_inlines_tail = meth;
}
-/* Consume a no-commas expression - a default argument - and save it
- on the inline_text_obstack. */
+/* Consume a no-commas expression - a default argument - and return
+ a DEFAULT_ARG tree node. */
static tree
snarf_defarg ()
{
- int starting_lineno = lineno;
- const char *starting_filename = input_filename;
int yyc;
int plev = 0;
- size_t point;
- size_t len;
struct unparsed_text *buf;
- int i;
tree arg;
+ location_t starting;
+ starting.file = input_filename;
+ starting.line = lineno;
- obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
+ buf = alloc_unparsed_text (&starting, 0, 0);
for (;;)
{
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (buf));
if (plev <= 0 && (yyc == ')' || yyc == ','))
break;
@@ -1257,46 +1259,27 @@ snarf_defarg ()
--plev;
else if (yyc == 0)
{
- error_with_file_and_line (starting_filename, starting_lineno,
- "end of file read inside default argument");
+ error ("%Hend of file read inside default argument", &starting);
goto done;
}
}
/* Unget the last token. */
- push_token ((struct token *) (obstack_base (&inline_text_obstack) + point));
- /* This is the documented way to shrink a growing obstack block. */
- obstack_blank (&inline_text_obstack, - (int) sizeof (struct token));
+ push_token (remove_last_token (buf));
/* Add three END_OF_SAVED_INPUT tokens. We used to provide an
infinite stream of END_OF_SAVED_INPUT tokens -- but that can
cause the compiler to get stuck in an infinite loop when
encountering invalid code. We need more than one because the
parser sometimes peeks ahead several tokens. */
- for (i = 0; i < 3; ++i)
- {
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- memcpy ((struct token *)
- (obstack_base (&inline_text_obstack) + point),
- &Teosi,
- sizeof (struct token));
- }
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
done:
- len = obstack_object_size (&inline_text_obstack);
- buf = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
-
- buf->decl = 0;
- buf->filename = starting_filename;
- buf->lineno = starting_lineno;
- buf->limit = (struct token *) ((char *)buf + len);
- buf->next = 0;
-
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n",
- buf->limit - (struct token *) (buf + 1),
- starting_filename, starting_lineno);
+ buf->limit, starting.file, starting.line);
#endif
arg = make_node (DEFAULT_ARG);
@@ -1328,7 +1311,7 @@ add_defarg_fn (decl)
TREE_VALUE (defarg_fns) = decl;
else
{
- defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);
+ defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);
TREE_TYPE (defarg_fns) = current_class_type;
}
}
@@ -1357,7 +1340,7 @@ finish_defarg ()
error ("parse error at end of saved function text");
end_input ();
-}
+}
/* Main function for deferred parsing of default arguments. Called from
the parser. */
@@ -1371,7 +1354,7 @@ do_pending_defargs ()
for (; defarg_fns;)
{
tree current = defarg_fns;
-
+
tree defarg_fn = TREE_VALUE (defarg_fns);
if (defarg_parm == NULL_TREE)
{
@@ -1411,7 +1394,7 @@ do_pending_defargs ()
poplevel (0, 0, 0);
pop_nested_class ();
-
+
defarg_fns = TREE_CHAIN (defarg_fns);
if (defarg_depfns)
{
@@ -1419,8 +1402,8 @@ do_pending_defargs ()
of defarg_fns. We will need to reprocess this function, and
check for circular dependencies. */
tree a, b;
-
- for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b;
+
+ for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b;
a = TREE_CHAIN (a), b = TREE_CHAIN (b))
if (TREE_VALUE (a) != TREE_VALUE (b))
goto different;
@@ -1436,8 +1419,8 @@ do_pending_defargs ()
cp_warning_at ("circular dependency in default args of `%#D'", defarg_fn);
/* No need to say what else is dependent, as they will be
picked up in another pass. */
-
- /* Immediately repeat, but marked so that we break the loop. */
+
+ /* Immediately repeat, but marked so that we break the loop. */
defarg_fns = current;
TREE_PURPOSE (current) = error_mark_node;
}
@@ -1449,7 +1432,7 @@ do_pending_defargs ()
}
/* After parsing all the default arguments, we must clear any that remain,
- which will be part of a circular dependency. */
+ which will be part of a circular dependency. */
void
done_pending_defargs ()
{
@@ -1457,7 +1440,7 @@ done_pending_defargs ()
{
tree fn = TREE_VALUE (defarg_fnsdone);
tree parms;
-
+
if (TREE_CODE (fn) == FUNCTION_DECL)
parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
else
@@ -1504,7 +1487,7 @@ replace_defarg (arg, init)
}
}
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
/* debug_yychar takes a yychar (token number) value and prints its name. */
static void
@@ -1542,12 +1525,17 @@ yyerror (msgid)
error ("%s at end of input", string);
else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
{
- unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
- const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
- if (val <= UCHAR_MAX && ISGRAPH (val))
- error ("%s before %s'%c'", string, ell, val);
+ if (yylval.ttype && TREE_CODE (yylval.ttype) == INTEGER_CST)
+ {
+ unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
+ const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ error ("%s before %s'%c'", string, ell, val);
+ else
+ error ("%s before %s'\\x%x'", string, ell, val);
+ }
else
- error ("%s before %s'\\x%x'", string, ell, val);
+ error ("%s", string);
}
else if (last_token == CPP_STRING
|| last_token == CPP_WSTRING)
@@ -1566,3 +1554,5 @@ yyerror (msgid)
else
error ("%s before `%s' token", string, NAME (last_token));
}
+
+#include "gt-cp-spew.h"
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index cdfa49c..ce6137e 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -22,16 +22,17 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
+#include "real.h"
#include "rtl.h"
#include "toplev.h"
#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
+#include "target.h"
static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *));
@@ -39,12 +40,11 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree));
static int list_hash_eq PARAMS ((const void *, const void *));
static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
+static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int));
static tree no_linkage_helper PARAMS ((tree *, int *, void *));
static tree build_srcloc PARAMS ((const char *, int));
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
static tree cp_unsave_r PARAMS ((tree *, int *, void *));
-static void cp_unsave PARAMS ((tree *));
static tree build_target_expr PARAMS ((tree, tree));
static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
@@ -57,12 +57,13 @@ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, boo
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- non-zero, rvalues of class type are considered lvalues. */
+ nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
tree ref;
int treat_class_rvalues_as_lvalues;
+ int allow_cast_as_lvalue;
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -85,16 +86,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- /* This shouldn't be here, but there are lots of places in the compiler
- that are sloppy about tacking on NOP_EXPRs to the same type when
- no actual conversion is happening. */
- case NOP_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+
+ case NOP_EXPR:
+ /* If expression doesn't change the type, we consider it as an
+ lvalue even when cast_as_lvalue extension isn't selected.
+ That's because parts of the compiler are alleged to be sloppy
+ about sticking in NOP_EXPR node for no good reason. */
+ if (allow_cast_as_lvalue ||
+ same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+ else
+ return clk_none;
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
@@ -135,16 +148,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case MAX_EXPR:
case MIN_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case MODIFY_EXPR:
@@ -152,7 +169,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
@@ -197,7 +215,19 @@ cp_lvalue_kind
real_lvalue_p (ref)
tree ref;
{
- return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
+}
+
+/* Returns the kind of lvalue that REF is, in the sense of
+ [basic.lval]. This function should really be named lvalue_p; it
+ computes the C++ definition of lvalue. */
+
+cp_lvalue_kind
+real_non_cast_lvalue_p (tree ref)
+{
+ return lvalue_p_1 (ref,
+ /*treat_class_rvalues_as_lvalues=*/0,
+ /*allow_cast_as_lvalue=*/0);
}
/* This differs from real_lvalue_p in that class rvalues are
@@ -208,7 +238,15 @@ lvalue_p (ref)
tree ref;
{
return
- (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none);
+}
+
+int
+non_cast_lvalue_p (ref)
+ tree ref;
+{
+ return
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 0) != clk_none);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -219,7 +257,20 @@ lvalue_or_else (ref, string)
tree ref;
const char *string;
{
- int win = lvalue_p (ref);
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1);
+ int win = (ret != clk_none);
+ if (! win)
+ error ("non-lvalue in %s", string);
+ return win;
+}
+
+int
+non_cast_lvalue_or_else (ref, string)
+ tree ref;
+ const char *string;
+{
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0);
+ int win = (ret != clk_none);
if (! win)
error ("non-lvalue in %s", string);
return win;
@@ -235,7 +286,7 @@ build_target_expr (decl, value)
tree t;
t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value,
- maybe_build_cleanup (decl), NULL_TREE);
+ cxx_maybe_build_cleanup (decl), NULL_TREE);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
ignore the TARGET_EXPR. If there really turn out to be no
side-effects, then the optimizer should be able to get rid of
@@ -293,7 +344,7 @@ build_cplus_new (type, init)
return rval;
}
-/* Buidl a TARGET_EXPR using INIT to initialize a new temporary of the
+/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
tree
@@ -471,7 +522,7 @@ build_cplus_array_type_1 (elt_type, index_type)
&& index_type && TYPE_MAX_VALUE (index_type)
&& TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
|| uses_template_parms (elt_type)
- || uses_template_parms (index_type))
+ || (index_type && uses_template_parms (index_type)))
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
@@ -496,14 +547,16 @@ build_cplus_array_type (elt_type, index_type)
{
tree t;
int type_quals = cp_type_quals (elt_type);
+ int cv_quals = type_quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
+ int other_quals = type_quals & ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
- if (type_quals != TYPE_UNQUALIFIED)
- elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
+ if (cv_quals)
+ elt_type = cp_build_qualified_type (elt_type, other_quals);
t = build_cplus_array_type_1 (elt_type, index_type);
- if (type_quals != TYPE_UNQUALIFIED)
- t = cp_build_qualified_type (t, type_quals);
+ if (cv_quals)
+ t = cp_build_qualified_type (t, cv_quals);
return t;
}
@@ -610,9 +663,12 @@ cp_build_qualified_type_real (type, type_quals, complain)
return error_mark_node;
/* See if we already have an identically qualified type. */
- t = get_qualified_type (type, type_quals);
-
- /* If we didn't already have it, create it now. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (cp_type_quals (t) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+ break;
+
if (!t)
{
/* Make a new array type, just like the old one, but with the
@@ -651,13 +707,13 @@ cp_build_qualified_type_real (type, type_quals, complain)
result = build_qualified_type (type, type_quals);
/* If this was a pointer-to-method type, and we just made a copy,
- then we need to clear the cached associated
- pointer-to-member-function type; it is not valid for the new
- type. */
+ then we need to unshare the record that holds the cached
+ pointer-to-member-function type, because these will be distinct
+ between the unqualified and qualified types. */
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- TYPE_SET_PTRMEMFUNC_TYPE (result, NULL_TREE);
+ TYPE_LANG_SPECIFIC (result) = NULL;
return result;
}
@@ -717,7 +773,7 @@ unshare_base_binfos (binfo)
While all these live in the same table, they are completely independent,
and the hash code is computed differently for each of these. */
-static htab_t list_hash_table;
+static GTY ((param_is (union tree_node))) htab_t list_hash_table;
struct list_proxy
{
@@ -955,7 +1011,7 @@ is_overloaded_fn (x)
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
- x = TREE_VALUE (x);
+ x = BASELINK_FUNCTIONS (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -970,10 +1026,25 @@ really_overloaded_fn (x)
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
- || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
+ x = BASELINK_FUNCTIONS (x);
+
+ return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x))
+ || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
+ || TREE_CODE (x) == TEMPLATE_ID_EXPR);
+}
+
+/* Return the OVERLOAD or FUNCTION_DECL inside FNS. FNS can be an
+ OVERLOAD, FUNCTION_DECL, TEMPLATE_ID_EXPR, or baselink. */
+
+tree
+get_overloaded_fn (fns)
+ tree fns;
+{
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ fns = TREE_OPERAND (fns, 0);
+ if (BASELINK_P (fns))
+ fns = BASELINK_FUNCTIONS (fns);
+ return fns;
}
tree
@@ -981,9 +1052,9 @@ get_first_fn (from)
tree from;
{
my_friendly_assert (is_overloaded_fn (from), 9);
- /* A baselink is also considered an overloaded function. */
+ /* A baselink is also considered an overloaded function. */
if (BASELINK_P (from))
- from = TREE_VALUE (from);
+ from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
@@ -998,7 +1069,7 @@ bound_pmf_p (t)
&& TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
}
-/* Return a new OVL node, concatenating it with the old one. */
+/* Return a new OVL node, concatenating it with the old one. */
tree
ovl_cons (decl, chain)
@@ -1037,7 +1108,7 @@ is_aggr_type_2 (t1, t2)
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-/* Returns non-zero if CODE is the code for a statement. */
+/* Returns nonzero if CODE is the code for a statement. */
int
cp_statement_code_p (code)
@@ -1045,8 +1116,6 @@ cp_statement_code_p (code)
{
switch (code)
{
- case SUBOBJECT:
- case CTOR_STMT:
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:
@@ -1064,7 +1133,7 @@ cp_statement_code_p (code)
#define PRINT_RING_SIZE 4
const char *
-lang_printable_name (decl, v)
+cxx_printable_name (decl, v)
tree decl;
int v;
{
@@ -1500,19 +1569,19 @@ build_min VPARAMS ((enum tree_code code, tree tt, ...))
same node; therefore, callers should never modify the node
returned. */
+static GTY(()) tree shared_int_cache[256];
+
tree
build_shared_int_cst (i)
int i;
{
- static tree cache[256];
-
if (i >= 256)
return build_int_2 (i, 0);
- if (!cache[i])
- cache[i] = build_int_2 (i, 0);
+ if (!shared_int_cache[i])
+ shared_int_cache[i] = build_int_2 (i, 0);
- return cache[i];
+ return shared_int_cache[i];
}
tree
@@ -1680,8 +1749,10 @@ cp_tree_equal (t1, t2)
return 0;
case TEMPLATE_PARM_INDEX:
- return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
- && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
+ return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+ && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+ && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
+ TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -1729,25 +1800,15 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Build a wrapper around some pointer PTR so we can use it as a tree. */
+/* Build a wrapper around a 'struct z_candidate' so we can use it as a
+ tree. */
tree
-build_ptr_wrapper (ptr)
- void *ptr;
+build_zc_wrapper (ptr)
+ struct z_candidate *ptr;
{
tree t = make_node (WRAPPER);
- WRAPPER_PTR (t) = ptr;
- return t;
-}
-
-/* Build a wrapper around some integer I so we can use it as a tree. */
-
-tree
-build_int_wrapper (i)
- int i;
-{
- tree t = make_node (WRAPPER);
- WRAPPER_INT (t) = i;
+ WRAPPER_ZC (t) = ptr;
return t;
}
@@ -1861,7 +1922,12 @@ maybe_dummy_object (type, binfop)
if (binfop)
*binfop = binfo;
- if (current_class_ref && context == current_class_type)
+ if (current_class_ref && context == current_class_type
+ /* Kludge: Make sure that current_class_type is actually
+ correct. It might not be if we're in the middle of
+ tsubst_default_argument. */
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+ current_class_type))
decl = current_class_ref;
else
decl = build_dummy_object (context);
@@ -1889,6 +1955,8 @@ pod_type_p (t)
{
t = strip_array_types (t);
+ if (t == error_mark_node)
+ return 1;
if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
@@ -1912,24 +1980,27 @@ pod_type_p (t)
int
zero_init_p (t)
- tree t ATTRIBUTE_UNUSED;
+ tree t;
{
- /* This is not a correct implementation of this function. As a
- result, pointers-to-members will not be correctly
- zero-initialized.
+ t = strip_array_types (t);
+
+ if (t == error_mark_node)
+ return 1;
- However, using a correct implementation of this function results
- in many other failures. Correcting these other failures required
- a major infrastructure improvement, which was undertaken in the
- GCC 3.3 source base.
+ /* NULL pointers to data members are initialized with -1. */
+ if (TYPE_PTRMEM_P (t))
+ return 0;
+
+ /* Classes that contain types that can't be zero-initialized, cannot
+ be zero-initialized themselves. */
+ if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t))
+ return 0;
- In order to reduce risk, these changes were not ported to the GCC
- 3.2 source base. */
return 1;
}
/* Table of valid C++ attributes. */
-const struct attribute_spec cp_attribute_table[] =
+const struct attribute_spec cxx_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
@@ -2031,7 +2102,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
/* 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. */
+ init_priority value, so don't allow it. */
|| current_function_decl)
{
error ("can only use `%s' attribute on file-scope definitions of objects of class type",
@@ -2181,6 +2252,14 @@ cp_cannot_inline_tree_fn (fnp)
return 1;
}
+ /* Don't auto-inline anything that might not be bound within
+ this unit of translation. */
+ if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
if (varargs_function_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
@@ -2290,8 +2369,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
- DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
- DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+ DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
/* Don't lose initialization info. */
DECL_INITIAL (var) = DECL_INITIAL (nrv);
@@ -2307,7 +2385,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
return var;
}
-/* Record that we're about to start inlining FN, and return non-zero if
+/* Record that we're about to start inlining FN, and return nonzero if
that's OK. Used for lang_hooks.tree_inlining.start_inlining. */
int
@@ -2336,14 +2414,8 @@ cp_end_inlining (fn)
void
init_tree ()
{
- make_lang_type_fn = cp_make_lang_type;
- lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p;
- lang_set_decl_assembler_name = mangle_decl;
- list_hash_table = htab_create (31, list_hash, list_hash_eq, NULL);
- ggc_add_root (&list_hash_table, 1,
- sizeof (list_hash_table),
- mark_tree_hashtable);
+ list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
/* Called via walk_tree. If *TP points to a DECL_STMT for a local
@@ -2429,12 +2501,11 @@ cp_unsave_r (tp, walk_subtrees, data)
return NULL_TREE;
}
-/* Called by unsave_expr_now whenever an expression (*TP) needs to be
- unsaved. */
+/* Called whenever an expression needs to be unsaved. */
-static void
-cp_unsave (tp)
- tree *tp;
+tree
+cxx_unsave_expr_now (tp)
+ tree tp;
{
splay_tree st;
@@ -2443,18 +2514,20 @@ cp_unsave (tp)
st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
/* Walk the tree once figuring out what needs to be remapped. */
- walk_tree (tp, mark_local_for_remap_r, st, NULL);
+ walk_tree (&tp, mark_local_for_remap_r, st, NULL);
/* Walk the tree again, copying, remapping, and unsaving. */
- walk_tree (tp, cp_unsave_r, st, NULL);
+ walk_tree (&tp, cp_unsave_r, st, NULL);
/* Clean up. */
splay_tree_delete (st);
+
+ return tp;
}
/* Returns the kind of special function that DECL (a FUNCTION_DECL)
- is. Note that this sfk_none is zero, so this function can be used
- as a predicate to test whether or not DECL is a special function. */
+ is. Note that sfk_none is zero, so this function can be used as a
+ predicate to test whether or not DECL is a special function. */
special_function_kind
special_function_p (decl)
@@ -2483,7 +2556,23 @@ special_function_p (decl)
return sfk_none;
}
-/* Returns non-zero if TYPE is a character type, including wchar_t. */
+/* Returns true if and only if NODE is a name, i.e., a node created
+ by the parser when processing an id-expression. */
+
+bool
+name_p (tree node)
+{
+ if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
+ node = TREE_OPERAND (node, 0);
+ return (/* An ordinary unqualified name. */
+ TREE_CODE (node) == IDENTIFIER_NODE
+ /* A destructor name. */
+ || TREE_CODE (node) == BIT_NOT_EXPR
+ /* A qualified name. */
+ || TREE_CODE (node) == SCOPE_REF);
+}
+
+/* Returns nonzero if TYPE is a character type, including wchar_t. */
int
char_type_p (type)
@@ -2537,3 +2626,53 @@ decl_linkage (decl)
/* Everything else has internal linkage. */
return lk_internal;
}
+
+/* EXP is an expression that we want to pre-evaluate. Returns via INITP an
+ expression to perform the pre-evaluation, and returns directly an
+ expression to use the precalculated result. */
+
+tree
+stabilize_expr (exp, initp)
+ tree exp;
+ tree *initp;
+{
+ tree init_expr;
+
+ if (!TREE_SIDE_EFFECTS (exp))
+ {
+ init_expr = void_zero_node;
+ }
+ else if (!real_lvalue_p (exp)
+ || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
+ {
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ }
+ else
+ {
+ exp = build_unary_op (ADDR_EXPR, exp, 1);
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ exp = build_indirect_ref (exp, 0);
+ }
+
+ *initp = init_expr;
+ return exp;
+}
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Complain that some language-specific thing hanging off a tree
+ node has been accessed improperly. */
+
+void
+lang_check_failed (file, line, function)
+ const char *file;
+ int line;
+ const char *function;
+{
+ internal_error ("lang_* check: failed in %s, at %s:%d",
+ function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
+
+#include "gt-cp-tree.h"
diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c
index 82867eb..c161e11 100644
--- a/contrib/gcc/cp/typeck.c
+++ b/contrib/gcc/cp/typeck.c
@@ -57,7 +57,6 @@ static int comp_array_types PARAMS ((int (*) (tree, tree, int), tree,
static tree common_base_type PARAMS ((tree, tree));
static tree lookup_anon_field PARAMS ((tree, tree));
static tree pointer_diff PARAMS ((tree, tree, tree));
-static tree build_component_addr PARAMS ((tree, tree));
static tree qualify_type_recursive PARAMS ((tree, tree));
static tree get_delta_difference PARAMS ((tree, tree, int));
static int comp_cv_target_types PARAMS ((tree, tree, int));
@@ -156,14 +155,16 @@ complete_type (type)
return type;
}
-/* Like complete_type, but issue an error if the TYPE cannot be
- completed. VALUE is used for informative diagnostics.
+/* Like complete_type, but issue an error if the TYPE cannot be completed.
+ VALUE is used for informative diagnostics. DIAG_TYPE indicates the type
+ of diagnostic: 0 for an error, 1 for a warning, 2 for a pedwarn.
Returns NULL_TREE if the type cannot be made complete. */
tree
-complete_type_or_else (type, value)
+complete_type_or_diagnostic (type, value, diag_type)
tree type;
tree value;
+ int diag_type;
{
type = complete_type (type);
if (type == error_mark_node)
@@ -171,7 +172,7 @@ complete_type_or_else (type, value)
return NULL_TREE;
else if (!COMPLETE_TYPE_P (type))
{
- incomplete_type_error (value, type);
+ cxx_incomplete_type_diagnostic (value, type, diag_type);
return NULL_TREE;
}
else
@@ -202,28 +203,33 @@ qualify_type_recursive (t1, t2)
if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
|| (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
{
- tree tt1 = TREE_TYPE (t1);
- tree tt2 = TREE_TYPE (t2);
+ tree tt1;
+ tree tt2;
tree b1;
int type_quals;
tree tgt;
tree attributes = (*targetm.merge_type_attributes) (t1, t2);
- if (TREE_CODE (tt1) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (t1))
{
- b1 = TYPE_OFFSET_BASETYPE (tt1);
- tt1 = TREE_TYPE (tt1);
- tt2 = TREE_TYPE (tt2);
+ b1 = TYPE_PTRMEM_CLASS_TYPE (t1);
+ tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
+ tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
}
else
- b1 = NULL_TREE;
+ {
+ b1 = NULL_TREE;
+ tt1 = TREE_TYPE (t1);
+ tt2 = TREE_TYPE (t2);
+ }
type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
tgt = qualify_type_recursive (tt1, tt2);
tgt = cp_build_qualified_type (tgt, type_quals);
if (b1)
- tgt = build_offset_type (b1, tgt);
- t1 = build_pointer_type (tgt);
+ t1 = build_ptrmem_type (b1, tgt);
+ else
+ t1 = build_pointer_type (tgt);
t1 = build_type_attribute_variant (t1, attributes);
}
return t1;
@@ -485,7 +491,7 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
return t1;
/* Deal with pointer-to-member functions in the same way as we deal
- with pointers to functions. */
+ with pointers to functions. */
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TYPE_PTRMEMFUNC_P (t2))
@@ -777,7 +783,7 @@ comp_except_types (a, b, exact)
}
/* Return 1 if TYPE1 and TYPE2 are equivalent exception specifiers.
- If EXACT is 0, T2 can be a subset of T1 (according to 15.4/7),
+ If EXACT is 0, T2 can be stricter than T1 (according to 15.4/7),
otherwise it must be exact. Exception lists are unordered, but
we've already filtered out duplicates. Most lists will be in order,
we should try to make use of that. */
@@ -794,13 +800,13 @@ comp_except_specs (t1, t2, exact)
if (t1 == t2)
return 1;
- if (t1 == NULL_TREE) /* T1 is ... */
+ if (t1 == NULL_TREE) /* T1 is ... */
return t2 == NULL_TREE || !exact;
if (!TREE_VALUE (t1)) /* t1 is EMPTY */
return t2 != NULL_TREE && !TREE_VALUE (t2);
- if (t2 == NULL_TREE) /* T2 is ... */
+ if (t2 == NULL_TREE) /* T2 is ... */
return 0;
- if (TREE_VALUE(t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
+ if (TREE_VALUE (t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
return !exact;
/* Neither set is ... or EMPTY, make sure each part of T2 is in T1.
@@ -856,7 +862,7 @@ comp_array_types (cmp, t1, t2, strict)
return 1;
/* If one of the arrays is dimensionless, and the other has a
- dimension, they are of different types. However, it is legal to
+ dimension, they are of different types. However, it is valid to
write:
extern int a[];
@@ -896,7 +902,7 @@ comptypes (t1, t2, strict)
extern int (*i)[];
int (*i)[8];
- is not legal, for example. */
+ is invalid, for example. */
strict &= ~COMPARE_REDECLARATION;
/* Suppress errors caused by previously reported errors */
@@ -924,9 +930,9 @@ comptypes (t1, t2, strict)
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
if (t1 == t2)
return 1;
@@ -1484,73 +1490,44 @@ comp_target_parms (parms1, parms2)
return warn_contravariance ? -1 : 1;
}
-/* Compute the value of the `sizeof' operator. */
-
tree
-c_sizeof (type)
+cxx_sizeof_or_alignof_type (type, op, complain)
tree type;
+ enum tree_code op;
+ int complain;
{
- enum tree_code code = TREE_CODE (type);
- tree size;
+ enum tree_code type_code;
+ tree value;
+ const char *op_name;
+ my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
if (processing_template_decl)
- return build_min_nt (SIZEOF_EXPR, type);
+ return build_min_nt (op, type);
+
+ op_name = operator_name_info[(int) op].name;
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ type_code = TREE_CODE (type);
- if (code == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to a function type");
- size = size_one_node;
- }
- else if (code == METHOD_TYPE)
+ if (type_code == METHOD_TYPE)
{
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to a member function");
- size = size_one_node;
+ if (complain && (pedantic || warn_pointer_arith))
+ pedwarn ("invalid application of `%s' to a member function", op_name);
+ value = size_one_node;
}
- else if (code == VOID_TYPE)
+ else if (type_code == OFFSET_TYPE)
{
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to type `void' which is an incomplete type");
- size = size_one_node;
+ if (complain)
+ error ("invalid application of `%s' to non-static member", op_name);
+ value = size_zero_node;
}
- else if (code == ERROR_MARK)
- size = size_one_node;
else
- {
- /* ARM $5.3.2: ``When applied to a reference, the result is the
- size of the referenced object.'' */
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ value = c_sizeof_or_alignof_type (complete_type (type), op, complain);
- if (code == OFFSET_TYPE)
- {
- error ("`sizeof' applied to non-static member");
- size = size_zero_node;
- }
- else if (!COMPLETE_TYPE_P (complete_type (type)))
- {
- error ("`sizeof' applied to incomplete type `%T'", type);
- size = size_zero_node;
- }
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
- }
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, size_type_node, size));
- my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
- 20001021);
- return size;
+ return value;
}
-
tree
expr_sizeof (e)
tree e;
@@ -1568,10 +1545,10 @@ expr_sizeof (e)
}
else if (type_unknown_p (e))
{
- incomplete_type_error (e, TREE_TYPE (e));
+ cxx_incomplete_type_error (e, TREE_TYPE (e));
return c_sizeof (char_type_node);
}
- /* It's illegal to say `sizeof (X::i)' for `i' a non-static data
+ /* It's invalid to say `sizeof (X::i)' for `i' a non-static data
member unless you're in a non-static member of X. So hand off to
resolve_offset_ref. [expr.prim] */
else if (TREE_CODE (e) == OFFSET_REF)
@@ -1580,44 +1557,9 @@ expr_sizeof (e)
if (e == error_mark_node)
return e;
- return c_sizeof (TREE_TYPE (e));
+ return cxx_sizeof (TREE_TYPE (e));
}
-tree
-c_sizeof_nowarn (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE
- || code == METHOD_TYPE
- || code == VOID_TYPE
- || code == ERROR_MARK)
- size = size_one_node;
- else
- {
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (!COMPLETE_TYPE_P (type))
- size = size_zero_node;
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
- }
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, size_type_node, size));
- my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
- 20001021);
- return size;
-}
/* Perform the array-to-pointer and function-to-pointer conversions
for EXP.
@@ -1650,7 +1592,7 @@ decay_conversion (exp)
if (type_unknown_p (exp))
{
- incomplete_type_error (exp, TREE_TYPE (exp));
+ cxx_incomplete_type_error (exp, TREE_TYPE (exp));
return error_mark_node;
}
@@ -1723,7 +1665,7 @@ decay_conversion (exp)
is not the target type of the type of the ADDR_EXPR itself.
Question is, can this lossage be avoided? */
adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (mark_addressable (exp) == 0)
+ if (!cxx_mark_addressable (exp))
return error_mark_node;
TREE_CONSTANT (adr) = staticp (exp);
TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
@@ -1820,46 +1762,6 @@ string_conv_p (totype, exp, warn)
return 1;
}
-
-tree
-build_object_ref (datum, basetype, field)
- tree datum, basetype, field;
-{
- tree dtype;
- if (datum == error_mark_node)
- return error_mark_node;
-
- dtype = TREE_TYPE (datum);
- if (TREE_CODE (dtype) == REFERENCE_TYPE)
- dtype = TREE_TYPE (dtype);
- if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
- {
- error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
- basetype, field, dtype);
- return error_mark_node;
- }
- else if (is_aggr_type (basetype, 1))
- {
- tree binfo = binfo_or_else (basetype, dtype);
- if (binfo)
- return build_x_component_ref (build_scoped_ref (datum, basetype),
- field, binfo, 1);
- }
- return error_mark_node;
-}
-
-/* Like `build_component_ref, but uses an already found field, and converts
- from a reference. Must compute access for current_class_ref.
- Otherwise, ok. */
-
-tree
-build_component_ref_1 (datum, field, protect)
- tree datum, field;
- int protect;
-{
- return convert_from_reference
- (build_component_ref (datum, field, NULL_TREE, protect));
-}
/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
can, for example, use as an lvalue. This code used to be in
@@ -1909,7 +1811,7 @@ lookup_anon_field (t, type)
{
if (TREE_STATIC (field))
continue;
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
/* If we find it directly, return the field. */
@@ -1931,333 +1833,448 @@ lookup_anon_field (t, type)
return NULL_TREE;
}
-/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.
- COMPONENT can be an IDENTIFIER_NODE that is the name of the member
- that we are interested in, or it can be a FIELD_DECL. */
+/* Build an expression representing OBJECT.MEMBER. OBJECT is an
+ expression; MEMBER is a DECL or baselink. If ACCESS_PATH is
+ non-NULL, it indicates the path to the base used to name MEMBER.
+ If PRESERVE_REFERENCE is true, the expression returned will have
+ REFERENCE_TYPE if the MEMBER does. Otherwise, the expression
+ returned will have the type referred to by the reference.
+
+ This function does not perform access control; that is either done
+ earlier by the parser when the name of MEMBER is resolved to MEMBER
+ itself, or later when overload resolution selects one of the
+ functions indicated by MEMBER. */
tree
-build_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
+build_class_member_access_expr (tree object, tree member,
+ tree access_path, bool preserve_reference)
{
- register tree basetype;
- register enum tree_code code;
- register tree field = NULL;
- register tree ref;
- tree field_type;
- int type_quals;
- tree old_datum;
- tree old_basetype;
+ tree object_type;
+ tree member_scope;
+ tree result = NULL_TREE;
- if (processing_template_decl)
- return build_min_nt (COMPONENT_REF, datum, component);
-
- if (datum == error_mark_node
- || TREE_TYPE (datum) == error_mark_node)
+ if (object == error_mark_node || member == 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))
+ my_friendly_assert (DECL_P (member) || BASELINK_P (member),
+ 20020801);
+
+ /* Transform `(a, b).x' into `a, b.x' and `(a ? b : c).x' into
+ `a ? b.x : c.x'. These transformations should not really be
+ necessary, but they are. */
+ if (TREE_CODE (object) == COMPOUND_EXPR)
+ {
+ result = build_class_member_access_expr (TREE_OPERAND (object, 1),
+ member, access_path,
+ preserve_reference);
+ return build (COMPOUND_EXPR, TREE_TYPE (result),
+ TREE_OPERAND (object, 0), result);
+ }
+ else if (TREE_CODE (object) == COND_EXPR)
+ return (build_conditional_expr
+ (TREE_OPERAND (object, 0),
+ build_class_member_access_expr (TREE_OPERAND (object, 1),
+ member, access_path,
+ preserve_reference),
+ build_class_member_access_expr (TREE_OPERAND (object, 2),
+ member, access_path,
+ preserve_reference)));
+
+ /* [expr.ref]
+
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ object_type = TREE_TYPE (object);
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
{
- case COMPOUND_EXPR:
- {
- tree value = build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect);
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (datum, 0), value);
- }
- case COND_EXPR:
- return build_conditional_expr
- (TREE_OPERAND (datum, 0),
- build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect),
- build_component_ref (TREE_OPERAND (datum, 2), component,
- basetype_path, protect));
-
- case TEMPLATE_DECL:
- error ("invalid use of `%D'", datum);
- datum = error_mark_node;
- break;
-
- default:
- break;
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ member, object, object_type);
+ return error_mark_node;
}
- code = TREE_CODE (basetype);
-
- if (code == REFERENCE_TYPE)
+ /* The standard does not seem to actually say that MEMBER must be a
+ member of OBJECT_TYPE. However, that is clearly what is
+ intended. */
+ if (DECL_P (member))
{
- datum = convert_from_reference (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
+ member_scope = DECL_CLASS_CONTEXT (member);
+ mark_used (member);
+ if (TREE_DEPRECATED (member))
+ warn_deprecated_use (member);
}
- if (TREE_CODE (datum) == OFFSET_REF)
- {
- datum = resolve_offset_ref (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
+ else
+ member_scope = BINFO_TYPE (BASELINK_BINFO (member));
+ /* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
+ presently be the anonymous union. Go outwards until we find a
+ type related to OBJECT_TYPE. */
+ while (ANON_AGGR_TYPE_P (member_scope)
+ && !same_type_ignoring_top_level_qualifiers_p (member_scope,
+ object_type))
+ member_scope = TYPE_CONTEXT (member_scope);
+ if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
+ {
+ error ("`%D' is not a member of `%T'", member, object_type);
+ return error_mark_node;
}
- /* First, see if there is a field or component with name COMPONENT. */
- if (TREE_CODE (component) == TREE_LIST)
+ /* In [expr.ref], there is an explicit list of the valid choices for
+ MEMBER. We check for each of those cases here. */
+ if (TREE_CODE (member) == VAR_DECL)
{
- /* I could not trigger this code. MvL */
- abort ();
-#ifdef DEAD
- my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
-#endif
- return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
+ /* A static data member. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
}
-
- if (! IS_AGGR_TYPE_CODE (code))
+ else if (TREE_CODE (member) == FIELD_DECL)
{
- if (code != ERROR_MARK)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- component, datum, basetype);
- return error_mark_node;
- }
+ /* A non-static data member. */
+ bool null_object_p;
+ int type_quals;
+ tree member_type;
- if (!complete_type_or_else (basetype, datum))
- return error_mark_node;
+ null_object_p = (TREE_CODE (object) == INDIRECT_REF
+ && integer_zerop (TREE_OPERAND (object, 0)));
- if (TREE_CODE (component) == BIT_NOT_EXPR)
- {
- if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))
+ /* Convert OBJECT to the type of MEMBER. */
+ if (!same_type_p (TYPE_MAIN_VARIANT (object_type),
+ TYPE_MAIN_VARIANT (member_scope)))
{
- error ("destructor specifier `%T::~%T' must have matching names",
- basetype, TREE_OPERAND (component, 0));
- return error_mark_node;
+ tree binfo;
+ base_kind kind;
+
+ binfo = lookup_base (access_path ? access_path : object_type,
+ member_scope, ba_ignore, &kind);
+ if (binfo == error_mark_node)
+ return error_mark_node;
+
+ /* It is invalid to try to get to a virtual base of a
+ NULL object. The most common cause is invalid use of
+ offsetof macro. */
+ if (null_object_p && kind == bk_via_virtual)
+ {
+ error ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ error ("(perhaps the `offsetof' macro was used incorrectly)");
+ return error_mark_node;
+ }
+
+ /* Convert to the base. */
+ object = build_base_path (PLUS_EXPR, object, binfo,
+ /*nonnull=*/1);
+ /* If we found the base successfully then we should be able
+ to convert to it successfully. */
+ my_friendly_assert (object != error_mark_node,
+ 20020801);
}
- if (! TYPE_HAS_DESTRUCTOR (basetype))
+
+ /* Complain about other invalid uses of offsetof, even though they will
+ give the right answer. Note that we complain whether or not they
+ actually used the offsetof macro, since there's no way to know at this
+ point. So we just give a warning, instead of a pedwarn. */
+ if (null_object_p && CLASSTYPE_NON_POD_P (object_type))
{
- error ("type `%T' has no destructor", basetype);
- return error_mark_node;
+ warning ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ warning ("(perhaps the `offsetof' macro was used incorrectly)");
+ }
+
+ /* If MEMBER is from an anonymous aggregate, we have converted
+ OBJECT so that it refers to the class containing the
+ anonymous union. Generate a reference to the anonymous union
+ itself, and recur to find MEMBER. */
+ if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))
+ /* When this code is called from build_field_call, the
+ object already has the type of the anonymous union.
+ That is because the COMPONENT_REF was already
+ constructed, and was then disassembled before calling
+ build_field_call. After the function-call code is
+ cleaned up, this waste can be eliminated. */
+ && (!same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (object), DECL_CONTEXT (member))))
+ {
+ tree anonymous_union;
+
+ anonymous_union = lookup_anon_field (TREE_TYPE (object),
+ DECL_CONTEXT (member));
+ object = build_class_member_access_expr (object,
+ anonymous_union,
+ /*access_path=*/NULL_TREE,
+ preserve_reference);
}
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
- }
- /* Look up component name in the structure type definition. */
- if (TYPE_VFIELD (basetype)
- && DECL_NAME (TYPE_VFIELD (basetype)) == component)
- /* Special-case this because if we use normal lookups in an ambiguous
- hierarchy, the compiler will abort (because vptr lookups are
- not supposed to be ambiguous. */
- field = TYPE_VFIELD (basetype);
- else if (TREE_CODE (component) == FIELD_DECL)
- field = component;
- else if (TREE_CODE (component) == TYPE_DECL)
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ member_type = TREE_TYPE (member);
+ if (TREE_CODE (member_type) != REFERENCE_TYPE)
+ {
+ type_quals = (cp_type_quals (member_type)
+ | cp_type_quals (object_type));
+
+ /* 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_MUTABLE_P (member))
+ type_quals &= ~TYPE_QUAL_CONST;
+ member_type = cp_build_qualified_type (member_type, type_quals);
+ }
+
+ result = fold (build (COMPONENT_REF, member_type, object, member));
+
+ /* 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 (result) = 1;
+ else if (type_quals & TYPE_QUAL_VOLATILE)
+ TREE_THIS_VOLATILE (result) = 1;
+ }
+ else if (BASELINK_P (member))
{
- error ("invalid use of type decl `%#D' as expression", component);
- return error_mark_node;
+ /* The member is a (possibly overloaded) member function. */
+ tree functions;
+
+ /* If the MEMBER is exactly one static member function, then we
+ know the type of the expression. Otherwise, we must wait
+ until overload resolution has been performed. */
+ functions = BASELINK_FUNCTIONS (member);
+ if (TREE_CODE (functions) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (functions))
+ {
+ /* A static member function. */
+ result = functions;
+ mark_used (result);
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
+ }
+ else
+ /* Note that we do not convert OBJECT to the BASELINK_BINFO
+ base. That will happen when the function is called. */
+ result = build (COMPONENT_REF, unknown_type_node, object, member);
}
- else if (TREE_CODE (component) == TEMPLATE_DECL)
+ else if (TREE_CODE (member) == CONST_DECL)
{
- error ("invalid use of template `%#D' as expression", component);
- return error_mark_node;
+ /* The member is an enumerator. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
}
else
{
- tree name = component;
-
- if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- name = TREE_OPERAND (component, 0);
- else if (TREE_CODE (component) == VAR_DECL)
- name = DECL_NAME (component);
- if (TREE_CODE (component) == NAMESPACE_DECL)
- /* Source is in error, but produce a sensible diagnostic. */
- name = DECL_NAME (component);
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, name,
- protect && !VFIELD_NAME_P (name), 0);
- if (field == error_mark_node)
- return error_mark_node;
+ error ("invalid use of `%D'", member);
+ return error_mark_node;
+ }
- if (field == NULL_TREE)
- {
- /* Not found as a data field, look for it as a method. If found,
- then if this is the only possible one, return it, else
- report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, name, 1);
- if (fndecls == error_mark_node)
- 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 (!preserve_reference)
+ /* [expr.ref]
+
+ If E2 is declared to have type "reference to T", then ... the
+ type of E1.E2 is T. */
+ result = convert_from_reference (result);
- if (TREE_CHAIN (fndecls) == NULL_TREE
- && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)
- {
- if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
- {
- tree fndecl = TREE_VALUE (fndecls);
- enforce_access (basetype_path, fndecl);
- mark_used (fndecl);
- return fndecl;
- }
- else
- {
- /* 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)
- = ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
- }
- }
+ return result;
+}
- fndecls = TREE_VALUE (fndecls);
-
- if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- fndecls = build_nt (TEMPLATE_ID_EXPR,
- fndecls, TREE_OPERAND (component, 1));
-
- ref = build (COMPONENT_REF, unknown_type_node,
- datum, fndecls);
- return ref;
- }
+/* This function is called by the parser to process a class member
+ access expression of the form OBJECT.NAME. NAME is a node used by
+ the parser to represent a name; it is not yet a DECL. It may,
+ however, be a BASELINK where the BASELINK_FUNCTIONS is a
+ TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and
+ there is no reason to do the lookup twice, so the parser keeps the
+ BASELINK. */
- error ("`%#T' has no member named `%D'", basetype, name);
- return error_mark_node;
- }
- else if (TREE_TYPE (field) == error_mark_node)
- return error_mark_node;
+tree
+finish_class_member_access_expr (tree object, tree name)
+{
+ tree object_type;
+ tree member;
+ tree access_path = NULL_TREE;
- if (TREE_CODE (field) != FIELD_DECL)
- {
- if (TREE_CODE (field) == TYPE_DECL)
- pedwarn ("invalid use of type decl `%#D' as expression", field);
- else if (DECL_RTL (field) != 0)
- mark_used (field);
- else
- TREE_USED (field) = 1;
+ if (object == error_mark_node || name == error_mark_node)
+ return error_mark_node;
- /* Do evaluate the object when accessing a static member. */
- if (TREE_SIDE_EFFECTS (datum))
- field = build (COMPOUND_EXPR, TREE_TYPE (field), datum, field);
+ if (processing_template_decl)
+ return build_min_nt (COMPONENT_REF, object, name);
+
+ if (TREE_CODE (object) == OFFSET_REF)
+ object = resolve_offset_ref (object);
- return field;
- }
+ object_type = TREE_TYPE (object);
+ if (TREE_CODE (object_type) == REFERENCE_TYPE)
+ {
+ object = convert_from_reference (object);
+ object_type = TREE_TYPE (object);
}
- if (TREE_DEPRECATED (field))
- warn_deprecated_use (field);
+ /* [expr.ref]
- old_datum = datum;
- old_basetype = basetype;
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
+ {
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ name, object, object_type);
+ return error_mark_node;
+ }
- /* See if we have to do any conversions so that we pick up the field from the
- right context. */
- if (DECL_FIELD_CONTEXT (field) != basetype)
+ if (BASELINK_P (name))
+ {
+ /* A member function that has already been looked up. */
+ my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))
+ == TEMPLATE_ID_EXPR),
+ 20020805);
+ member = name;
+ }
+ else
{
- tree context = DECL_FIELD_CONTEXT (field);
- tree base = context;
- while (!same_type_p (base, basetype) && TYPE_NAME (base)
- && ANON_AGGR_TYPE_P (base))
- base = TYPE_CONTEXT (base);
+ bool is_template_id = false;
+ tree template_args = NULL_TREE;
- /* Handle base classes here... */
- if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
- base_kind kind;
- tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, &kind);
+ is_template_id = true;
+ template_args = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ }
- /* Complain about use of offsetof which will break. */
- if (TREE_CODE (datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (datum, 0))
- && kind == bk_via_virtual)
+ if (TREE_CODE (name) == SCOPE_REF)
+ {
+ tree scope;
+
+ /* A qualified name. The qualifying class or namespace `S' has
+ already been looked up; it is either a TYPE or a
+ NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE
+ or a BIT_NOT_EXPR. */
+ scope = TREE_OPERAND (name, 0);
+ name = TREE_OPERAND (name, 1);
+ my_friendly_assert ((CLASS_TYPE_P (scope)
+ || TREE_CODE (scope) == NAMESPACE_DECL),
+ 20020804);
+ my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
+ || TREE_CODE (name) == BIT_NOT_EXPR),
+ 20020804);
+
+ /* If SCOPE is a namespace, then the qualified name does not
+ name a member of OBJECT_TYPE. */
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ {
+ error ("`%D::%D' is not a member of `%T'",
+ scope, name, object_type);
+ return error_mark_node;
+ }
+
+ /* Find the base of OBJECT_TYPE corresponding to SCOPE. */
+ access_path = lookup_base (object_type, scope, ba_check, NULL);
+ if (!access_path || access_path == error_mark_node)
+ return error_mark_node;
+
+ /* Look up the member. */
+ member = lookup_member (access_path, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == NULL_TREE)
{
- error ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
+ error ("'%D' has no member named '%E'", object_type, name);
return error_mark_node;
}
- datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
- if (datum == error_mark_node)
+ else if (member == error_mark_node)
return error_mark_node;
}
- basetype = base;
-
- /* Handle things from anon unions here... */
- if (TYPE_NAME (context) && ANON_AGGR_TYPE_P (context))
+ else if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ /* A destructor. */
+ if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0))
+ {
+ error ("destructor specifier `%T::~%T' must have matching names",
+ object_type, TREE_OPERAND (name, 0));
+ return error_mark_node;
+ }
+ if (! TYPE_HAS_DESTRUCTOR (object_type))
+ {
+ error ("type `%T' has no destructor", object_type);
+ return error_mark_node;
+ }
+ member = CLASSTYPE_DESTRUCTORS (object_type);
+ }
+ else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
- tree subfield = lookup_anon_field (basetype, context);
- tree subdatum = build_component_ref (datum, subfield,
- basetype_path, protect);
- return build_component_ref (subdatum, field, basetype_path, protect);
+ /* An unqualified name. */
+ member = lookup_member (object_type, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == NULL_TREE)
+ {
+ error ("'%D' has no member named '%E'", object_type, name);
+ return error_mark_node;
+ }
+ else if (member == error_mark_node)
+ return error_mark_node;
+ }
+ else
+ {
+ /* The YACC parser sometimes gives us things that are not names.
+ These always indicate errors. The recursive-descent parser
+ does not do this, so this code can go away once that parser
+ replaces the YACC parser. */
+ error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ if (is_template_id)
+ {
+ tree template = member;
+
+ if (BASELINK_P (template))
+ BASELINK_FUNCTIONS (template)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (template),
+ template_args);
+ else
+ {
+ error ("`%D' is not a member template function", name);
+ return error_mark_node;
+ }
}
}
- /* Complain about other invalid uses of offsetof, even though they will
- give the right answer. Note that we complain whether or not they
- actually used the offsetof macro, since there's no way to know at this
- point. So we just give a warning, instead of a pedwarn. */
- if (protect
- && CLASSTYPE_NON_POD_P (old_basetype)
- && TREE_CODE (old_datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (old_datum, 0)))
- warning ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
-
- /* 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_MUTABLE_P (field))
- type_quals &= ~TYPE_QUAL_CONST;
- field_type = cp_build_qualified_type (field_type, type_quals);
- }
-
- ref = fold (build (COMPONENT_REF, field_type, datum, 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;
- else if (type_quals & TYPE_QUAL_VOLATILE)
- TREE_THIS_VOLATILE (ref) = 1;
-
- return ref;
+ return build_class_member_access_expr (object, member, access_path,
+ /*preserve_reference=*/false);
}
-/* Variant of build_component_ref for use in expressions, which should
- never have REFERENCE_TYPE. */
+/* Return an expression for the MEMBER_NAME field in the internal
+ representation of PTRMEM, a pointer-to-member function. (Each
+ pointer-to-member function type gets its own RECORD_TYPE so it is
+ more convenient to access the fields by name than by FIELD_DECL.)
+ This routine converts the NAME to a FIELD_DECL and then creates the
+ node for the complete expression. */
tree
-build_x_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
+build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
{
- tree t = build_component_ref (datum, component, basetype_path, protect);
-
- if (! processing_template_decl)
- t = convert_from_reference (t);
-
- return t;
+ tree ptrmem_type;
+ tree member;
+ tree member_type;
+
+ /* This code is a stripped down version of
+ build_class_member_access_expr. It does not work to use that
+ routine directly because it expects the object to be of class
+ type. */
+ ptrmem_type = TREE_TYPE (ptrmem);
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
+ member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
+ /*want_type=*/0);
+ member_type = cp_build_qualified_type (TREE_TYPE (member),
+ cp_type_quals (ptrmem_type));
+ return fold (build (COMPONENT_REF, member_type, ptrmem, member));
}
-
+
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
ERRORSTRING is the name of the operator to appear in error messages.
@@ -2319,8 +2336,8 @@ build_indirect_ref (ptr, errorstring)
return error_mark_node;
}
else if (TREE_CODE (pointer) == ADDR_EXPR
- && !flag_volatile
- && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
+ && !flag_volatile
+ && 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);
@@ -2434,7 +2451,7 @@ build_array_ref (array, idx)
&& (TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))))
!= INTEGER_CST)))
{
- if (mark_addressable (array) == 0)
+ if (!cxx_mark_addressable (array))
return error_mark_node;
}
@@ -2446,7 +2463,7 @@ build_array_ref (array, idx)
&& TYPE_VALUES (TREE_TYPE (array))
&& ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array))))
{
- if (mark_addressable (array) == 0)
+ if (!cxx_mark_addressable (array))
return error_mark_node;
}
@@ -2509,306 +2526,15 @@ build_array_ref (array, idx)
}
}
-/* Build a function call to function FUNCTION with parameters PARAMS.
- PARAMS is a list--a chain of TREE_LIST nodes--in which the
- TREE_VALUE of each node is a parameter-expression. The PARAMS do
- not include any object pointer that may be required. FUNCTION's
- data type may be a function type or a pointer-to-function.
-
- For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
- is the list of possible methods that FUNCTION could conceivably
- be. If the list of methods comes from a class, then it will be
- a list of lists (where each element is associated with the class
- that produced it), otherwise it will be a simple list (for
- functions overloaded in global scope).
-
- In the first case, TREE_VALUE (function) is the head of one of those
- lists, and TREE_PURPOSE is the name of the function.
-
- In the second case, TREE_PURPOSE (function) is the function's
- name directly.
-
- DECL is the class instance variable, usually CURRENT_CLASS_REF.
-
- When calling a TEMPLATE_DECL, we don't require a complete return
- type. */
-
-tree
-build_x_function_call (function, params, decl)
- tree function, params, decl;
-{
- tree type;
- tree template_id = NULL_TREE;
- int is_method;
-
- if (function == error_mark_node)
- return error_mark_node;
-
- if (processing_template_decl)
- return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
-
- /* Save explicit template arguments if found */
- if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
- {
- template_id = function;
- function = TREE_OPERAND (function, 0);
- }
-
- type = TREE_TYPE (function);
-
- if (TREE_CODE (type) == OFFSET_TYPE
- && TREE_TYPE (type) == unknown_type_node
- && TREE_CODE (function) == TREE_LIST
- && TREE_CHAIN (function) == NULL_TREE)
- {
- /* Undo (Foo:bar)()... */
- type = TYPE_OFFSET_BASETYPE (type);
- function = TREE_VALUE (function);
- my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999);
- my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999);
- function = TREE_VALUE (function);
- if (TREE_CODE (function) == OVERLOAD)
- function = OVL_FUNCTION (function);
- my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999);
- function = DECL_NAME (function);
- return build_method_call (decl, function, params,
- TYPE_BINFO (type), LOOKUP_NORMAL);
- }
-
- if (TREE_CODE (function) == OFFSET_REF
- && TREE_CODE (type) != METHOD_TYPE)
- function = resolve_offset_ref (function);
-
- if ((TREE_CODE (function) == FUNCTION_DECL
- && DECL_STATIC_FUNCTION_P (function))
- || (DECL_FUNCTION_TEMPLATE_P (function)
- && DECL_STATIC_FUNCTION_P (DECL_TEMPLATE_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));
-
- /* A friend template. Make it look like a toplevel declaration. */
- if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
- function = ovl_cons (function, NULL_TREE);
-
- /* Handle methods, friends, and overloaded functions, respectively. */
- if (is_method)
- {
- tree basetype = NULL_TREE;
-
- if (TREE_CODE (function) == OVERLOAD)
- function = OVL_CURRENT (function);
-
- if (TREE_CODE (function) == FUNCTION_DECL
- || DECL_FUNCTION_TEMPLATE_P (function))
- {
- basetype = DECL_CONTEXT (function);
-
- if (DECL_NAME (function))
- function = DECL_NAME (function);
- else
- function = TYPE_IDENTIFIER (DECL_CONTEXT (function));
- }
- else if (TREE_CODE (function) == TREE_LIST)
- {
- my_friendly_assert (TREE_CODE (TREE_VALUE (function))
- == FUNCTION_DECL, 312);
- basetype = DECL_CONTEXT (TREE_VALUE (function));
- function = TREE_PURPOSE (function);
- }
- else if (TREE_CODE (function) != IDENTIFIER_NODE)
- {
- if (TREE_CODE (function) == OFFSET_REF)
- {
- if (TREE_OPERAND (function, 0))
- decl = TREE_OPERAND (function, 0);
- }
- /* Call via a pointer to member function. */
- if (decl == NULL_TREE)
- {
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- /* What other type of POINTER_TYPE could this be? */
- if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function))
- && TREE_CODE (function) != OFFSET_REF)
- function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE,
- function);
- goto do_x_function;
- }
-
- /* this is an abbreviated method call.
- must go through here in case it is a virtual function.
- @@ Perhaps this could be optimized. */
-
- if (basetype && (! current_class_type
- || ! DERIVED_FROM_P (basetype, current_class_type)))
- return build_member_call (basetype, function, params);
-
- if (decl == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("object missing in call to method `%D'", function);
- return error_mark_node;
- }
- /* Yow: call from a static member function. */
- decl = build_dummy_object (current_class_type);
- }
-
- /* Put back explicit template arguments, if any. */
- if (template_id)
- function = template_id;
- return build_method_call (decl, function, params,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (TREE_CODE (function) == COMPONENT_REF
- && type == unknown_type_node)
- {
- /* Undo what we did in build_component_ref. */
- decl = TREE_OPERAND (function, 0);
- function = TREE_OPERAND (function, 1);
-
- if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
- {
- my_friendly_assert (!template_id, 20011228);
-
- template_id = function;
- }
- else
- {
- 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);
- }
- else if (really_overloaded_fn (function))
- {
- if (OVL_FUNCTION (function) == NULL_TREE)
- {
- error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?",
- TREE_PURPOSE (function));
- return error_mark_node;
- }
- else
- {
- /* Put back explicit template arguments, if any. */
- if (template_id)
- function = template_id;
- return build_new_function_call (function, params);
- }
- }
- else
- /* Remove a potential OVERLOAD around it */
- function = OVL_CURRENT (function);
-
- do_x_function:
- if (TREE_CODE (function) == OFFSET_REF)
- {
- /* If the component is a data element (or a virtual function), we play
- games here to make things work. */
- tree decl_addr;
-
- if (TREE_OPERAND (function, 0))
- decl = TREE_OPERAND (function, 0);
- else
- decl = current_class_ref;
-
- decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
-
- /* Sigh. OFFSET_REFs are being used for too many things.
- They're being used both for -> and ->*, and we want to resolve
- the -> cases here, but leave the ->*. We could use
- resolve_offset_ref for those, too, but it would call
- get_member_function_from_ptrfunc and decl_addr wouldn't get
- updated properly. Nasty. */
- if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL)
- function = resolve_offset_ref (function);
- else
- function = TREE_OPERAND (function, 1);
-
- function = get_member_function_from_ptrfunc (&decl_addr, function);
- params = tree_cons (NULL_TREE, decl_addr, params);
- return build_function_call (function, params);
- }
-
- type = TREE_TYPE (function);
- if (type != error_mark_node)
- {
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (IS_AGGR_TYPE (type))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
- }
-
- if (is_method)
- {
- tree fntype = TREE_TYPE (function);
- tree ctypeptr = NULL_TREE;
-
- /* Explicitly named method? */
- if (TREE_CODE (function) == FUNCTION_DECL)
- ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function));
- /* Expression with ptr-to-method type? It could either be a plain
- usage, or it might be a case where the ptr-to-method is being
- passed in as an argument. */
- else if (TYPE_PTRMEMFUNC_P (fntype))
- {
- tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE
- (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
- ctypeptr = build_pointer_type (rec);
- }
- /* Unexpected node type? */
- else
- abort ();
- if (decl == NULL_TREE)
- {
- if (current_function_decl
- && DECL_STATIC_FUNCTION_P (current_function_decl))
- error ("invalid call to member function needing `this' in static member function scope");
- else
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
- {
- tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr),
- ba_check, NULL);
-
- decl = build_unary_op (ADDR_EXPR, decl, 0);
- decl = build_base_path (PLUS_EXPR, decl, binfo, 1);
- }
- else
- decl = build_c_cast (ctypeptr, decl);
- params = tree_cons (NULL_TREE, decl, params);
- }
-
- return build_function_call (function, params);
-}
-
/* Resolve a pointer to member function. INSTANCE is the object
- instance to use, if the member points to a virtual member. */
+ instance to use, if the member points to a virtual member.
+
+ This used to avoid checking for virtual functions if basetype
+ has no virtual functions, according to an earlier ANSI draft.
+ With the final ISO C++ rules, such an optimization is
+ incorrect: A pointer to a derived member can be static_cast
+ to pointer-to-base-member, as long as the dynamic object
+ later has the right member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, function)
@@ -2820,92 +2546,79 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree fntype, idx, e1, delta, delta2, e2, e3, vtbl;
- tree instance, basetype;
+ tree idx, delta, e1, e2, e3, vtbl, basetype;
+ tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (function) == PTRMEM_CST)
+ tree instance_save_expr = 0;
+ if (instance_ptr == error_mark_node)
{
- /* Extracting the function address from a pmf is only
- allowed with -Wno-pmf-conversions. It only works for
- pmf constants. */
- e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
- e1 = convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)), e1);
- return e1;
+ if (TREE_CODE (function) == PTRMEM_CST)
+ {
+ /* Extracting the function address from a pmf is only
+ allowed with -Wno-pmf-conversions. It only works for
+ pmf constants. */
+ e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
+ e1 = convert (fntype, e1);
+ return e1;
+ }
+ else
+ {
+ error ("object missing in use of `%E'", function);
+ return error_mark_node;
+ }
}
if (TREE_SIDE_EFFECTS (instance_ptr))
- instance_ptr = save_expr (instance_ptr);
+ instance_ptr = instance_save_expr = save_expr (instance_ptr);
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
- basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
-
- /* Convert down to the right base, before using the instance. */
- instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype,
- ba_check, NULL);
- instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1);
- if (instance == error_mark_node && instance_ptr != error_mark_node)
- return instance;
-
+ /* Start by extracting all the information from the PMF itself. */
e3 = PFN_FROM_PTRMEMFUNC (function);
-
- vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance);
- TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance);
-
- delta = cp_convert (ptrdiff_type_node,
- build_component_ref (function, delta_identifier,
- NULL_TREE, 0));
-
- /* This used to avoid checking for virtual functions if basetype
- has no virtual functions, according to an earlier ANSI draft.
- With the final ISO C++ rules, such an optimization is
- incorrect: A pointer to a derived member can be static_cast
- to pointer-to-base-member, as long as the dynamic object
- later has the right member. */
-
- /* 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 = cp_build_binary_op (TRUNC_DIV_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- TYPE_SIZE_UNIT (vtable_entry_type));
+ delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+ idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- integer_one_node);
+ e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node);
+ idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
break;
case ptrmemfunc_vbit_in_delta:
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- delta, integer_one_node);
- delta = cp_build_binary_op (RSHIFT_EXPR,
- build1 (NOP_EXPR, vtable_index_type,
- delta),
- integer_one_node);
+ e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node);
+ delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node);
break;
default:
abort ();
}
- /* DELTA2 is the amount by which to adjust the `this' pointer
- to find the vtbl. */
- delta2 = delta;
- vtbl = build
- (PLUS_EXPR,
- build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, cp_convert (ptrdiff_type_node, delta2));
+ /* Convert down to the right base before using the instance. First
+ use the type... */
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
+ basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
+ basetype, ba_check, NULL);
+ instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
+ if (instance_ptr == error_mark_node)
+ return error_mark_node;
+ /* ...and then the delta in the PMF. */
+ instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, delta);
+
+ /* Hand back the adjusted 'this' argument to our caller. */
+ *instance_ptrptr = instance_ptr;
+
+ /* Next extract the vtable pointer from the object. */
+ vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
+ instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
- e2 = build_array_ref (vtbl, idx);
+
+ /* Finally, extract the function pointer from the vtable. */
+ e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
+ e2 = build_indirect_ref (e2, NULL);
+ TREE_CONSTANT (e2) = 1;
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
@@ -2918,17 +2631,9 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
- if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ if (instance_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 (instance_ptr == error_mark_node
- && TREE_CODE (e1) != ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
- error ("object missing in `%E'", function);
+ instance_save_expr, e1);
function = e1;
}
@@ -2941,7 +2646,6 @@ build_function_call_real (function, params, require_complete, flags)
int require_complete, flags;
{
register tree fntype, fndecl;
- register tree value_type;
register tree coerced_params;
tree result;
tree name = NULL_TREE, assembler_name = NULL_TREE;
@@ -3046,20 +2750,7 @@ build_function_call_real (function, params, require_complete, flags)
return result;
}
- /* Some built-in function calls will be evaluated at
- compile-time in fold (). */
- result = fold (build_call (function, coerced_params));
- value_type = TREE_TYPE (result);
-
- if (require_complete)
- {
- if (TREE_CODE (value_type) == VOID_TYPE)
- return result;
- result = require_complete_type (result);
- }
- if (IS_AGGR_TYPE (value_type))
- result = build_cplus_new (value_type, result);
- return convert_from_reference (result);
+ return build_cxx_call (function, params, coerced_params);
}
tree
@@ -3176,11 +2867,7 @@ convert_arguments (typelist, values, fndecl, flags)
parmval = convert_for_initialization
(NULL_TREE, type, val, flags,
"argument passing", fndecl, i);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type)
- < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
+ parmval = convert_for_arg_passing (type, parmval);
}
if (parmval == error_mark_node)
@@ -3590,7 +3277,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
- op0 = build_component_ref (op0, pfn_identifier, NULL_TREE, 0);
+ op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
result_type = TREE_TYPE (op0);
}
@@ -3624,10 +3311,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
DELTA field is unspecified. */
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
- delta0 = build_component_ref (op0, delta_identifier,
- NULL_TREE, 0);
- delta1 = build_component_ref (op1, delta_identifier,
- NULL_TREE, 0);
+ delta0 = build_ptrmemfunc_access_expr (op0,
+ delta_identifier);
+ delta1 = build_ptrmemfunc_access_expr (op1,
+ delta_identifier);
e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
e2 = cp_build_binary_op (EQ_EXPR,
pfn0,
@@ -3765,24 +3452,22 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
- result_type
- = signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0),
- TREE_TYPE (arg1)));
+ result_type = c_common_signed_or_unsigned_type
+ (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)),
+ && (type = c_common_signed_or_unsigned_type
+ (unsigned1, TREE_TYPE (arg1)),
int_fits_type_p (arg0, type)))
result_type = type;
else if (TREE_CODE (arg1) == INTEGER_CST
&& (unsigned0 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)),
+ && (type = c_common_signed_or_unsigned_type
+ (unsigned0, TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
@@ -3817,8 +3502,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
+ = c_common_signed_or_unsigned_type (unsigned_arg,
+ TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert (result_type, op0);
@@ -3891,11 +3576,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
not use the most significant bit of result_type. */
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST
- && int_fits_type_p (orig_op1,
- signed_type (result_type)))
+ && int_fits_type_p (orig_op1, c_common_signed_type
+ (result_type)))
|| (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST
- && int_fits_type_p (orig_op0,
- signed_type (result_type)))))
+ && int_fits_type_p (orig_op0, c_common_signed_type
+ (result_type)))))
/* OK */;
else
warning ("comparison between signed and unsigned integer expressions");
@@ -3968,7 +3653,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
return error_mark_node;
}
- /* Issue warnings about peculiar, but legal, uses of NULL. */
+ /* Issue warnings about peculiar, but valid, 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)
@@ -4089,50 +3774,6 @@ pointer_diff (op0, op1, ptrtype)
return folded;
}
-/* Handle the case of taking the address of a COMPONENT_REF.
- Called by `build_unary_op'.
-
- ARG is the COMPONENT_REF whose address we want.
- ARGTYPE is the pointer type that this address should have. */
-
-static tree
-build_component_addr (arg, argtype)
- tree arg, argtype;
-{
- tree field = TREE_OPERAND (arg, 1);
- tree basetype = decl_type_context (field);
- tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
-
- my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
-
- if (DECL_C_BIT_FIELD (field))
- {
- error ("attempt to take address of bit-field structure member `%D'",
- field);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL
- && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
- {
- /* Can't convert directly to ARGTYPE, since that
- may have the same pointer type as one of our
- baseclasses. */
- tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), basetype,
- ba_check, NULL);
-
- rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
- rval = build1 (NOP_EXPR, argtype, rval);
- TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
- }
- else
- /* This conversion is harmless. */
- rval = convert_force (argtype, rval, 0);
-
- return fold (build (PLUS_EXPR, argtype, rval,
- cp_convert (argtype, byte_position (field))));
-}
-
/* Construct and perhaps optimize a tree representation
for a unary operation. CODE, a tree_code, specifies the operation
and XARG is the operand. */
@@ -4212,8 +3853,9 @@ build_x_unary_op (code, xarg)
return exp;
}
-/* Like truthvalue_conversion, but handle pointer-to-member constants, where
- a null value is represented by an INTEGER_CST of -1. */
+/* Like c_common_truthvalue_conversion, but handle pointer-to-member
+ constants, where a null value is represented by an INTEGER_CST of
+ -1. */
tree
cp_truthvalue_conversion (expr)
@@ -4223,7 +3865,7 @@ cp_truthvalue_conversion (expr)
if (TYPE_PTRMEM_P (type))
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
else
- return truthvalue_conversion (expr);
+ return c_common_truthvalue_conversion (expr);
}
/* Just like cp_truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */
@@ -4241,7 +3883,45 @@ condition_conversion (expr)
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
-
+
+/* Return an ADDR_EXPR giving the address of T. This function
+ attempts no optimizations or simplifications; it is a low-level
+ primitive. */
+
+tree
+build_address (tree t)
+{
+ tree addr;
+
+ if (error_operand_p (t) || !cxx_mark_addressable (t))
+ return error_mark_node;
+
+ addr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (t)),
+ t);
+ if (staticp (t))
+ TREE_CONSTANT (addr) = 1;
+
+ return addr;
+}
+
+/* Return a NOP_EXPR converting EXPR to TYPE. */
+
+tree
+build_nop (tree type, tree expr)
+{
+ tree nop;
+
+ if (type == error_mark_node || error_operand_p (expr))
+ return expr;
+
+ nop = build1 (NOP_EXPR, type, expr);
+ if (TREE_CONSTANT (expr))
+ TREE_CONSTANT (nop) = 1;
+
+ return nop;
+}
+
/* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion
@@ -4428,7 +4108,7 @@ build_unary_op (code, xarg, noconvert)
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), argtype);
- inc = c_sizeof_nowarn (TREE_TYPE (argtype));
+ inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
}
else
inc = integer_one_node;
@@ -4543,7 +4223,7 @@ build_unary_op (code, xarg, noconvert)
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
- if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
+ if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1));
@@ -4563,7 +4243,7 @@ build_unary_op (code, xarg, noconvert)
}
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
- && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
+ && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
{
/* They're trying to take the address of a unique non-static
member function. This is ill-formed (except in MS-land),
@@ -4576,7 +4256,7 @@ build_unary_op (code, xarg, noconvert)
a useful error here. */
tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
- tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
+ tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
if (! flag_ms_extensions)
{
@@ -4625,27 +4305,40 @@ build_unary_op (code, xarg, noconvert)
is an error. */
else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
- && !lvalue_or_else (arg, "unary `&'"))
+ && !non_cast_lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
if (argtype != error_mark_node)
argtype = build_pointer_type (argtype);
- if (mark_addressable (arg) == 0)
- return error_mark_node;
-
{
tree addr;
- if (TREE_CODE (arg) == COMPONENT_REF)
- addr = build_component_addr (arg, argtype);
+ if (TREE_CODE (arg) != COMPONENT_REF)
+ addr = build_address (arg);
+ else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ error ("attempt to take address of bit-field structure member `%D'",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
else
- addr = build1 (ADDR_EXPR, argtype, arg);
-
- /* Address of a static or external variable or
- function counts as a constant */
- if (staticp (arg))
- TREE_CONSTANT (addr) = 1;
+ {
+ /* Unfortunately we cannot just build an address
+ expression here, because we would not handle
+ address-constant-expressions or offsetof correctly. */
+ tree field = TREE_OPERAND (arg, 1);
+ tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
+ tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)),
+ decl_type_context (field),
+ ba_check, NULL);
+
+ rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
+ rval = build1 (NOP_EXPR, argtype, rval);
+ TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
+ addr = fold (build (PLUS_EXPR, argtype, rval,
+ cp_convert (argtype, byte_position (field))));
+ }
if (TREE_CODE (argtype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@@ -4778,9 +4471,7 @@ unary_complex_lvalue (code, arg)
return error_mark_node;
}
- type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
- type = build_pointer_type (type);
-
+ type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
return t;
}
@@ -4815,12 +4506,12 @@ unary_complex_lvalue (code, arg)
/* Mark EXP saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Value is 1 if successful.
+ Value is true if successful.
C++: we do not allow `current_class_ptr' to be addressable. */
-int
-mark_addressable (exp)
+bool
+cxx_mark_addressable (exp)
tree exp;
{
register tree x = exp;
@@ -4841,7 +4532,7 @@ mark_addressable (exp)
{
error ("cannot take the address of `this', which is an rvalue expression");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
- return 1;
+ return true;
}
/* FALLTHRU */
@@ -4861,25 +4552,25 @@ mark_addressable (exp)
warning ("address requested for `%D', which is declared `register'",
x);
TREE_ADDRESSABLE (x) = 1;
- put_var_into_stack (x);
- return 1;
+ put_var_into_stack (x, /*rescan=*/true);
+ return true;
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
- return 1;
+ return true;
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return 1;
+ return true;
case TARGET_EXPR:
TREE_ADDRESSABLE (x) = 1;
- mark_addressable (TREE_OPERAND (x, 0));
- return 1;
+ cxx_mark_addressable (TREE_OPERAND (x, 0));
+ return true;
default:
- return 1;
+ return true;
}
}
@@ -4919,7 +4610,7 @@ build_x_compound_expr (list)
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
- /* FIXME: This test should be in the implicit cast to void of the LHS. */
+ /* FIXME: This test should be in the implicit cast to void of the LHS. */
/* the left-hand operand of a comma expression is like an expression
statement: we should warn if it doesn't have any side-effects,
unless it was explicitly cast to (void). */
@@ -4978,12 +4669,25 @@ build_compound_expr (list)
return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
}
+/* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
+ away constness. */
+
+static void
+check_for_casting_away_constness (tree src_type, tree dest_type)
+{
+ if (casts_away_constness (src_type, dest_type))
+ error ("static_cast from type `%T' to type `%T' casts away constness",
+ src_type, dest_type);
+}
+
+/* Return an expression representing static_cast<TYPE>(EXPR). */
+
tree
build_static_cast (type, expr)
tree type, expr;
{
tree intype;
- int ok;
+ tree result;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -5004,89 +4708,162 @@ build_static_cast (type, expr)
&& TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
expr = TREE_OPERAND (expr, 0);
- if (TREE_CODE (type) == VOID_TYPE)
- {
- expr = convert_to_void (expr, /*implicit=*/NULL);
- return expr;
+ intype = TREE_TYPE (expr);
+
+ /* [expr.static.cast]
+
+ An lvalue of type "cv1 B", where B is a class type, can be cast
+ to type "reference to cv2 D", where D is a class derived (clause
+ _class.derived_) from B, if a valid standard conversion from
+ "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the
+ same cv-qualification as, or greater cv-qualification than, cv1,
+ and B is not a virtual base class of D. */
+ /* We check this case before checking the validity of "TYPE t =
+ EXPR;" below because for this case:
+
+ struct B {};
+ struct D : public B { D(const B&); };
+ extern B& b;
+ void f() { static_cast<const D&>(b); }
+
+ we want to avoid constructing a new D. The standard is not
+ completely clear about this issue, but our interpretation is
+ consistent with other compilers. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (intype)
+ && real_non_cast_lvalue_p (expr)
+ && DERIVED_FROM_P (intype, TREE_TYPE (type))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type))))
+ && at_least_as_qualified_p (TREE_TYPE (type), intype))
+ {
+ /* At this point we have checked all of the conditions except
+ that B is not a virtual base class of D. That will be
+ checked by build_base_path. */
+ tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
+
+ /* Convert from B* to D*. */
+ expr = build_base_path (MINUS_EXPR, build_address (expr),
+ base, /*nonnull=*/false);
+ /* Convert the pointer to a reference -- but then remember that
+ there are no expressions with reference type in C++. */
+ return convert_from_reference (build_nop (type, expr));
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
- return (convert_from_reference
- (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
- LOOKUP_COMPLAIN, NULL_TREE)));
+ /* [expr.static.cast]
- if (IS_AGGR_TYPE (type))
- return build_cplus_new (type, (build_method_call
- (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type), LOOKUP_NORMAL)));
+ An expression e can be explicitly converted to a type T using a
+ static_cast of the form static_cast<T>(e) if the declaration T
+ t(e);" is well-formed, for some invented temporary variable
+ t. */
+ result = perform_direct_initialization_if_possible (type, expr);
+ if (result)
+ return convert_from_reference (result);
- intype = TREE_TYPE (expr);
+ /* [expr.static.cast]
- /* FIXME handle casting to array type. */
+ Any expression can be explicitly converted to type cv void. */
+ if (TREE_CODE (type) == VOID_TYPE)
+ return convert_to_void (expr, /*implicit=*/NULL);
- ok = 0;
- if (IS_AGGR_TYPE (intype)
- ? can_convert_arg (type, intype, expr)
- : can_convert_arg (strip_all_pointer_quals (type),
- strip_all_pointer_quals (intype), expr))
- /* This is a standard conversion. */
- ok = 1;
- else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
- {
- /* They're pointers to objects. They must be aggregates that
- are related non-virtually. */
- base_kind kind;
-
- if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
- && lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_ignore | ba_quiet, &kind)
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
- {
- /* They're pointers to members. The pointed to objects must be
- the same (ignoring CV qualifiers), and the containing classes
- must be related non-virtually. */
- base_kind kind;
-
- if (same_type_p
- (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))),
- strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype))))
- && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)),
- TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
- ba_ignore | ba_quiet, &kind))
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TREE_CODE (intype) != BOOLEAN_TYPE
- && TREE_CODE (type) != ARRAY_TYPE
- && TREE_CODE (type) != FUNCTION_TYPE
- && can_convert (intype, strip_all_pointer_quals (type)))
- ok = 1;
- else if (TREE_CODE (intype) == ENUMERAL_TYPE
- && TREE_CODE (type) == ENUMERAL_TYPE)
- /* DR 128: "A value of integral _or enumeration_ type can be explicitly
- converted to an enumeration type."
- The integral to enumeration will be accepted by the previous clause.
- We need to explicitly check for enumeration to enumeration. */
- ok = 1;
+ /* [expr.static.cast]
+ The inverse of any standard conversion sequence (clause _conv_),
+ other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
+ (_conv.array_), function-to-pointer (_conv.func_), and boolean
+ (_conv.bool_) conversions, can be performed explicitly using
+ static_cast subject to the restriction that the explicit
+ conversion does not cast away constness (_expr.const.cast_), and
+ the following additional rules for specific cases: */
+ /* For reference, the conversions not excluded are: integral
+ promotions, floating point promotion, integral conversions,
+ floating point conversions, floating-integral conversions,
+ pointer conversions, and pointer to member conversions. */
+ if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype))
+ /* DR 128
+
+ A value of integral _or enumeration_ type can be explicitly
+ converted to an enumeration type. */
+ || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
+ /* Really, build_c_cast should defer to this function rather
+ than the other way around. */
+ return build_c_cast (type, expr);
+ if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (TREE_TYPE (intype))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (intype))),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type)))))
+ {
+ tree base;
+
+ check_for_casting_away_constness (intype, type);
+ base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
+ ba_check | ba_quiet, NULL);
+ return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+ }
+ if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ {
+ tree c1;
+ tree c2;
+ tree t1;
+ tree t2;
+
+ c1 = TYPE_PTRMEM_CLASS_TYPE (intype);
+ c2 = TYPE_PTRMEM_CLASS_TYPE (type);
+
+ if (TYPE_PTRMEM_P (type))
+ {
+ t1 = (build_ptrmem_type
+ (c1,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
+ t2 = (build_ptrmem_type
+ (c2,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
+ }
+ else
+ {
+ t1 = intype;
+ t2 = type;
+ }
+ if (can_convert (t1, t2))
+ {
+ check_for_casting_away_constness (intype, type);
+ if (TYPE_PTRMEM_P (type))
+ {
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ expr = cplus_expand_constant (expr);
+ expr = cp_build_binary_op (PLUS_EXPR,
+ cp_convert (ptrdiff_type_node, expr),
+ get_delta_difference (c1, c2,
+ /*force=*/1));
+ return build_nop (type, expr);
+ }
+ else
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
+ /*force=*/1);
+ }
+ }
+
/* [expr.static.cast]
- The static_cast operator shall not be used to cast away
- constness. */
- if (ok && casts_away_constness (intype, type))
+ An rvalue of type "pointer to cv void" can be explicitly
+ converted to a pointer to object type. A value of type pointer
+ to object converted to "pointer to cv void" and back to the
+ original pointer type will have its original value. */
+ if (TREE_CODE (intype) == POINTER_TYPE
+ && VOID_TYPE_P (TREE_TYPE (intype))
+ && TYPE_PTROB_P (type))
{
- error ("static_cast from type `%T' to type `%T' casts away constness",
- intype, type);
- return error_mark_node;
+ check_for_casting_away_constness (intype, type);
+ return build_nop (type, expr);
}
- if (ok)
- return build_c_cast (type, expr);
-
error ("invalid static_cast from type `%T' to type `%T'", intype, type);
return error_mark_node;
}
@@ -5310,6 +5087,10 @@ build_c_cast (type, expr)
value = convert_to_void (value, /*implicit=*/NULL);
return value;
}
+
+ if (!complete_type_or_else (type, NULL_TREE))
+ return error_mark_node;
+
/* Convert functions and arrays to pointers and
convert references to their expanded types,
but don't convert any other types. If, however, we are
@@ -5468,11 +5249,9 @@ build_modify_expr (lhs, modifycode, rhs)
except that the RHS goes through a save-expr
so the code to compute it is only emitted once. */
tree cond;
+ tree preeval = NULL_TREE;
- if (lvalue_p (rhs))
- rhs = stabilize_reference (rhs);
- else
- rhs = save_expr (rhs);
+ rhs = stabilize_expr (rhs, &preeval);
/* Check this here to avoid odd errors when trying to convert
a throw to the type of the COND_EXPR. */
@@ -5492,10 +5271,7 @@ build_modify_expr (lhs, modifycode, rhs)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
- return build (COMPOUND_EXPR, TREE_TYPE (lhs),
- /* Cast to void to suppress warning
- from warn_if_unused_value. */
- cp_convert (void_type_node, rhs), cond);
+ return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
}
case OFFSET_REF:
@@ -5522,9 +5298,10 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else
{
- result = build_method_call (lhs, complete_ctor_identifier,
- build_tree_list (NULL_TREE, rhs),
- TYPE_BINFO (lhstype), LOOKUP_NORMAL);
+ result = build_special_member_call (lhs, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, rhs),
+ TYPE_BINFO (lhstype),
+ LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -5693,7 +5470,7 @@ build_modify_expr (lhs, modifycode, rhs)
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
- return build_vec_init (lhs, newrhs, from_array);
+ return build_vec_init (lhs, NULL_TREE, newrhs, from_array);
}
if (modifycode == INIT_EXPR)
@@ -5850,7 +5627,7 @@ get_delta_difference (from, to, force)
if (virt_binfo)
{
- /* This is a reinterpret cast, we choose to do nothing. */
+ /* This is a reinterpret cast, we choose to do nothing. */
warning ("pointer to member cast via virtual base `%T' of `%T'",
BINFO_TYPE (virt_binfo),
BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
@@ -5868,7 +5645,7 @@ get_delta_difference (from, to, force)
virt_binfo = binfo_from_vbase (binfo);
if (virt_binfo)
{
- /* This is a reinterpret cast, we choose to do nothing. */
+ /* This is a reinterpret cast, we choose to do nothing. */
if (force)
warning ("pointer to member cast via virtual base `%T' of `%T'",
BINFO_TYPE (virt_binfo),
@@ -5920,7 +5697,7 @@ build_ptrmemfunc1 (type, delta, pfn)
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
want to be.
- If FORCE is non-zero, then force this conversion, even if
+ If FORCE is nonzero, then force this conversion, even if
we would rather not do it. Usually set when using an explicit
cast.
@@ -5932,11 +5709,17 @@ build_ptrmemfunc (type, pfn, force)
int force;
{
tree fn;
- tree pfn_type = TREE_TYPE (pfn);
- tree to_type = build_ptrmemfunc_type (type);
+ tree pfn_type;
+ tree to_type;
+
+ if (error_operand_p (pfn))
+ return error_mark_node;
+
+ pfn_type = TREE_TYPE (pfn);
+ to_type = build_ptrmemfunc_type (type);
/* Handle multiple conversions of pointer to member functions. */
- if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
+ if (TYPE_PTRMEMFUNC_P (pfn_type))
{
tree delta = NULL_TREE;
tree npfn = NULL_TREE;
@@ -5971,8 +5754,8 @@ build_ptrmemfunc (type, pfn, force)
expand_ptrmemfunc_cst (pfn, &delta, &npfn);
else
{
- npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
- delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
+ npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
+ delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
}
/* Just adjust the DELTA field. */
@@ -6035,7 +5818,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
/* 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 orig_class = DECL_CONTEXT (fn);
tree binfo = binfo_or_else (orig_class, fn_class);
*delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
*delta, BINFO_OFFSET (binfo)));
@@ -6087,7 +5870,7 @@ pfn_from_ptrmemfunc (t)
return pfn;
}
- return build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ return build_ptrmemfunc_access_expr (t, pfn_identifier);
}
/* Expression EXPR is about to be implicitly converted to TYPE. Warn
@@ -6105,7 +5888,7 @@ dubious_conversion_warnings (type, expr, errtype, fndecl, parmnum)
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- /* Issue warnings about peculiar, but legal, uses of NULL. */
+ /* Issue warnings about peculiar, but valid, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && expr == null_node)
{
if (fndecl)
@@ -6243,7 +6026,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
/* Convert RHS to be of type TYPE.
- If EXP is non-zero, it is the target of the initialization.
+ If EXP is nonzero, it is the target of the initialization.
ERRTYPE is a string to use in error messages.
Two major differences between the behavior of
@@ -6317,7 +6100,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl)
savew = warningcount, savee = errorcount;
- rhs = initialize_reference (type, rhs);
+ rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
if (fndecl)
{
if (warningcount > savew)
@@ -6393,9 +6176,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
else
{
tree type = TREE_TYPE (o[i]);
- if (CP_TYPE_CONST_P (type)
- || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
- && C_TYPE_FIELDS_READONLY (type)))
+ if (type != error_mark_node
+ && (CP_TYPE_CONST_P (type)
+ || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
+ && C_TYPE_FIELDS_READONLY (type))))
readonly_error (o[i], "modification by `asm'", 1);
}
}
@@ -6465,7 +6249,7 @@ maybe_warn_about_returning_address_of_local (retval)
}
}
-/* Check that returning RETVAL from the current function is legal.
+/* Check that returning RETVAL from the current function is valid.
Return an expression explicitly showing all conversions required to
change RETVAL into the function return type, and to assign it to
the DECL_RESULT for the function. */
@@ -6497,7 +6281,7 @@ check_return_expr (retval)
{
if (in_function_try_handler)
/* If a return statement appears in a handler of the
- function-try-block of a constructor, the program is ill-formed. */
+ function-try-block of a constructor, the program is ill-formed. */
error ("cannot return from a handler of a function-try-block of a constructor");
else if (retval)
/* You can't return a value from a constructor. */
@@ -6618,7 +6402,7 @@ check_return_expr (retval)
/* First convert the value to the function's return type, then
to the type of return value's location to handle the
- case that functype is smaller than the valtype. */
+ case that functype is smaller than the valtype. */
retval = convert_for_initialization
(NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
"return", NULL_TREE, 0);
@@ -6645,9 +6429,9 @@ check_return_expr (retval)
}
-/* Returns non-zero if the pointer-type FROM can be converted to the
+/* Returns nonzero if the pointer-type FROM can be converted to the
pointer-type TO via a qualification conversion. If CONSTP is -1,
- then we return non-zero if the pointers are similar, and the
+ then we return nonzero if the pointers are similar, and the
cv-qualification signature of FROM is a proper subset of that of TO.
If CONSTP is positive, then all outer pointers have been
@@ -6808,10 +6592,12 @@ cp_type_quals (type)
tree type;
{
type = strip_array_types (type);
+ if (type == error_mark_node)
+ return TYPE_UNQUALIFIED;
return TYPE_QUALS (type);
}
-/* Returns non-zero if the TYPE contains a mutable member */
+/* Returns nonzero if the TYPE contains a mutable member */
int
cp_has_mutable_p (type)
@@ -6884,7 +6670,7 @@ casts_away_constness_r (t1, t2)
*t2 = cp_build_qualified_type (*t2, quals2);
}
-/* Returns non-zero if casting from TYPE1 to TYPE2 casts away
+/* Returns nonzero if casting from TYPE1 to TYPE2 casts away
constness. */
static int
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index f8e612b..0e70e2b 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -133,6 +133,12 @@ abstract_virtuals_error (decl, type)
tree u;
tree tu;
+ if (processing_template_decl)
+ /* If we are processing a template, TYPE may be a template
+ class where CLASSTYPE_PURE_VIRTUALS always contains
+ inline friends. */
+ return 0;
+
if (!CLASS_TYPE_P (type) || !CLASSTYPE_PURE_VIRTUALS (type))
return 0;
@@ -182,14 +188,35 @@ abstract_virtuals_error (decl, type)
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. */
+ and TYPE is the type that was invalid. DIAG_TYPE indicates the
+ type of diagnostic: 0 for an error, 1 for a warning, 2 for a
+ pedwarn. */
void
-incomplete_type_error (value, type)
+cxx_incomplete_type_diagnostic (value, type, diag_type)
tree value;
tree type;
+ int diag_type;
{
int decl = 0;
+ void (*p_msg) PARAMS ((const char *, ...));
+ void (*p_msg_at) PARAMS ((const char *, ...));
+
+ if (diag_type == 1)
+ {
+ p_msg = warning;
+ p_msg_at = cp_warning_at;
+ }
+ else if (diag_type == 2)
+ {
+ p_msg = pedwarn;
+ p_msg_at = cp_pedwarn_at;
+ }
+ else
+ {
+ p_msg = error;
+ p_msg_at = cp_error_at;
+ }
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
@@ -199,7 +226,7 @@ incomplete_type_error (value, type)
|| TREE_CODE (value) == PARM_DECL
|| TREE_CODE (value) == FIELD_DECL))
{
- cp_error_at ("`%D' has incomplete type", value);
+ (*p_msg_at) ("`%D' has incomplete type", value);
decl = 1;
}
retry:
@@ -211,15 +238,15 @@ retry:
case UNION_TYPE:
case ENUMERAL_TYPE:
if (!decl)
- error ("invalid use of undefined type `%#T'", type);
+ (*p_msg) ("invalid use of undefined type `%#T'", type);
if (!TYPE_TEMPLATE_INFO (type))
- cp_error_at ("forward declaration of `%#T'", type);
+ (*p_msg_at) ("forward declaration of `%#T'", type);
else
- cp_error_at ("declaration of `%#T'", type);
+ (*p_msg_at) ("declaration of `%#T'", type);
break;
case VOID_TYPE:
- error ("invalid use of `%T'", type);
+ (*p_msg) ("invalid use of `%T'", type);
break;
case ARRAY_TYPE:
@@ -228,27 +255,27 @@ retry:
type = TREE_TYPE (type);
goto retry;
}
- error ("invalid use of array with unspecified bounds");
+ (*p_msg) ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
- error ("invalid use of member (did you forget the `&' ?)");
+ (*p_msg) ("invalid use of member (did you forget the `&' ?)");
break;
case TEMPLATE_TYPE_PARM:
- error ("invalid use of template type parameter");
+ (*p_msg) ("invalid use of template type parameter");
break;
case UNKNOWN_TYPE:
if (value && TREE_CODE (value) == COMPONENT_REF)
goto bad_member;
else if (value && TREE_CODE (value) == ADDR_EXPR)
- error ("address of overloaded function with no contextual type information");
+ (*p_msg) ("address of overloaded function with no contextual type information");
else if (value && TREE_CODE (value) == OVERLOAD)
- error ("overloaded function with no contextual type information");
+ (*p_msg) ("overloaded function with no contextual type information");
else
- error ("insufficient contextual information to determine type");
+ (*p_msg) ("insufficient contextual information to determine type");
break;
default:
@@ -256,6 +283,17 @@ retry:
}
}
+/* Backward-compatibility interface to incomplete_type_diagnostic;
+ required by ../tree.c. */
+#undef cxx_incomplete_type_error
+void
+cxx_incomplete_type_error (value, type)
+ tree value;
+ tree type;
+{
+ cxx_incomplete_type_diagnostic (value, type, 0);
+}
+
/* Perform appropriate conversions on the initial value of a variable,
store it in the declaration DECL,
@@ -288,12 +326,6 @@ store_init_value (decl, init)
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
-#if 0
- /* This breaks arrays, and should not have any effect for other decls. */
- /* Take care of C++ business up here. */
- type = TYPE_MAIN_VARIANT (type);
-#endif
-
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
@@ -305,35 +337,6 @@ store_init_value (decl, init)
error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
-#if 0
- if (TREE_CODE (init) == CONSTRUCTOR)
- {
- tree field;
-
- /* Check that we're really an aggregate as ARM 8.4.1 defines it. */
- if (CLASSTYPE_N_BASECLASSES (type))
- cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
- if (CLASSTYPE_VTBL_PTR (type))
- cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- error ("due to the presence of a constructor");
- }
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- }
-#endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
@@ -370,15 +373,8 @@ store_init_value (decl, init)
/* End of special C++ code. */
- /* We might have already run this bracketed initializer through
- digest_init. Don't do so again. */
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
- && TREE_TYPE (init)
- && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
- value = init;
- else
- /* Digest the specified initializer into an expression. */
- value = digest_init (type, init, (tree *) 0);
+ /* Digest the specified initializer into an expression. */
+ value = digest_init (type, init, (tree *) 0);
/* Store the expression if valid; else report error. */
@@ -391,32 +387,8 @@ store_init_value (decl, init)
return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
- || ! initializer_constant_valid_p (value, TREE_TYPE (value))
-#if 0
- /* A STATIC PUBLIC int variable doesn't have to be
- run time inited when doing pic. (mrs) */
- /* Since ctors and dtors are the only things that can
- reference vtables, and they are always written down
- the vtable definition, we can leave the
- vtables in initialized data space.
- However, other initialized data cannot be initialized
- this way. Instead a global file-level initializer
- must do the job. */
- || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
-#endif
- ))
-
+ || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
return value;
-#if 0 /* No, that's C. jason 9/19/94 */
- else
- {
- if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
- {
- if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
- pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions");
- }
- }
-#endif
/* Store the VALUE in DECL_INITIAL. If we're building a
statement-tree we will actually expand the initialization later
@@ -425,27 +397,6 @@ store_init_value (decl, init)
return NULL_TREE;
}
-/* Same as store_init_value, but used for known-to-be-valid static
- initializers. Used to introduce a static initializer even in data
- structures that may require dynamic initialization. */
-
-tree
-force_store_init_value (decl, init)
- tree decl, init;
-{
- tree type = TREE_TYPE (decl);
- int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
-
- TYPE_NEEDS_CONSTRUCTING (type) = 0;
-
- init = store_init_value (decl, init);
- if (init)
- abort ();
-
- TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
-
- return init;
-}
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
@@ -463,8 +414,7 @@ digest_init (type, init, tail)
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
+ /* Nonzero if INIT is a braced grouping. */
int raw_constructor;
/* By default, assume we use one element from a list.
@@ -482,7 +432,7 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == ERROR_MARK)
/* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
- a template function. This gets substituted during instantiation. */
+ a template function. This gets substituted during instantiation. */
return init;
/* We must strip the outermost array type when completing the type,
@@ -495,10 +445,8 @@ 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;
+ raw_constructor = (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init));
if (raw_constructor
&& CONSTRUCTOR_ELTS (init) != 0
@@ -759,7 +707,9 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
- next1 = build_forced_zero_init (TREE_TYPE (type));
+ next1 = build_zero_init (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -808,7 +758,7 @@ process_init_constructor (type, init, elts)
continue;
}
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (tail)
@@ -876,7 +826,9 @@ process_init_constructor (type, init, elts)
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
- next1 = build_forced_zero_init (TREE_TYPE (field));
+ next1 = build_zero_init (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -900,8 +852,7 @@ process_init_constructor (type, init, elts)
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
- while (field && (DECL_NAME (field) == 0
- || TREE_CODE (field) != FIELD_DECL))
+ while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
@@ -986,7 +937,7 @@ process_init_constructor (type, init, elts)
/* Given a structure or union value DATUM, construct and return
the structure or union component which results from narrowing
- that value by the type specified in BASETYPE. For example, given the
+ that value to the base specified in BASETYPE. For example, given the
hierarchy
class L { int ii; };
@@ -1007,29 +958,36 @@ process_init_constructor (type, init, elts)
I used to think that this was nonconformant, that the standard specified
that first we look up ii in A, then convert x to an L& and pull out the
ii part. But in fact, it does say that we convert x to an A&; A here
- is known as the "naming class". (jason 2000-12-19) */
+ is known as the "naming class". (jason 2000-12-19)
+
+ BINFO_P points to a variable initialized either to NULL_TREE or to the
+ binfo for the specific base subobject we want to convert to. */
tree
-build_scoped_ref (datum, basetype)
+build_scoped_ref (datum, basetype, binfo_p)
tree datum;
tree basetype;
+ tree *binfo_p;
{
- tree ref;
tree binfo;
if (datum == error_mark_node)
return error_mark_node;
- binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+ if (*binfo_p)
+ binfo = *binfo_p;
+ else
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (!binfo)
- return error_not_base_type (TREE_TYPE (datum), basetype);
-
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
+ if (!binfo || binfo == error_mark_node)
+ {
+ *binfo_p = NULL_TREE;
+ if (!binfo)
+ error_not_base_type (basetype, TREE_TYPE (datum));
+ return error_mark_node;
+ }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
+ *binfo_p = binfo;
+ return build_base_path (PLUS_EXPR, datum, binfo, 1);
}
/* Build a reference to an object specified by the C++ `->' operator.
@@ -1164,8 +1122,8 @@ build_m_component_ref (datum, component)
| cp_type_quals (TREE_TYPE (datum)));
/* There's no such thing as a mutable pointer-to-member, so
- we don't need to deal with that here like we do in
- build_component_ref. */
+ things are not as complex as they are for references to
+ non-static data members. */
field_type = cp_build_qualified_type (field_type, type_quals);
}
}
@@ -1277,8 +1235,8 @@ build_functional_cast (exp, parms)
return get_target_expr (exp);
}
- exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
- TYPE_BINFO (type), LOOKUP_NORMAL);
+ exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
if (exp == error_mark_node)
return error_mark_node;
@@ -1313,6 +1271,7 @@ add_exception_specifier (list, spec, complain)
int ok;
tree core = spec;
int is_ptr;
+ int diag_type = -1; /* none */
if (spec == error_mark_node)
return list;
@@ -1334,7 +1293,15 @@ add_exception_specifier (list, spec, complain)
else if (processing_template_decl)
ok = 1;
else
- ok = COMPLETE_TYPE_P (complete_type (core));
+ {
+ ok = 1;
+ /* 15.4/1 says that types in an exception specifier must be complete,
+ but it seems more reasonable to only require this on definitions
+ and calls. So just give a pedwarn at this point; we will give an
+ error later if we hit one of those two cases. */
+ if (!COMPLETE_TYPE_P (complete_type (core)))
+ diag_type = 2; /* pedwarn */
+ }
if (ok)
{
@@ -1344,19 +1311,19 @@ add_exception_specifier (list, spec, complain)
if (same_type_p (TREE_VALUE (probe), spec))
break;
if (!probe)
- {
- spec = build_tree_list (NULL_TREE, spec);
- TREE_CHAIN (spec) = list;
- list = spec;
- }
+ list = tree_cons (NULL_TREE, spec, list);
}
- else if (complain)
- incomplete_type_error (NULL_TREE, core);
+ else
+ diag_type = 0; /* error */
+
+ if (diag_type >= 0 && complain)
+ cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
+
return list;
}
/* Combine the two exceptions specifier lists LIST and ADD, and return
- their union. */
+ their union. */
tree
merge_exception_specifiers (list, add)
@@ -1390,3 +1357,34 @@ merge_exception_specifiers (list, add)
}
return list;
}
+
+/* Subroutine of build_call. Ensure that each of the types in the
+ exception specification is complete. Technically, 15.4/1 says that
+ they need to be complete when we see a declaration of the function,
+ but we should be able to get away with only requiring this when the
+ function is defined or called. See also add_exception_specifier. */
+
+void
+require_complete_eh_spec_types (fntype, decl)
+ tree fntype, decl;
+{
+ tree raises;
+ /* Don't complain about calls to op new. */
+ if (decl && DECL_ARTIFICIAL (decl))
+ return;
+ for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises;
+ raises = TREE_CHAIN (raises))
+ {
+ tree type = TREE_VALUE (raises);
+ if (type && !COMPLETE_TYPE_P (type))
+ {
+ if (decl)
+ error
+ ("call to function `%D' which throws incomplete type `%#T'",
+ decl, type);
+ else
+ error ("call to function which throws incomplete type `%#T'",
+ decl);
+ }
+ }
+}
OpenPOWER on IntegriCloud