diff -Nrcpad gcc-3.4.3/gcc/cp/ChangeLog gcc-4.0.0/gcc/cp/ChangeLog *** gcc-3.4.3/gcc/cp/ChangeLog Fri Nov 5 03:33:53 2004 --- gcc-4.0.0/gcc/cp/ChangeLog Thu Apr 21 05:18:31 2005 *************** *** 1,13 **** ! 2004-11-04 Release Manager ! * GCC 3.4.3 released. 2004-10-31 Mark Mitchell PR c++/15172 * typeck2.c (store_init_value): Use split_nonconstant_init even for types that require construction. ! 2004-10-28 Mark Mitchell PR c++/17132 --- 1,1776 ---- ! 2005-04-20 Release Manager ! * GCC 4.0.0 released. ! ! 2005-04-16 Mark Mitchell ! ! PR c++/21025 ! * typeck.c (cxx_sizeof_or_alignof_type): Check whether the type to ! which sizeof/alignof is dependent, rather than just whether we are ! processing_template_decl. ! ! 2005-04-14 Dale Johannesen ! ! * tree.c (cp_tree_equal): Handle SSA_NAME. ! ! 2005-04-08 Mark Mitchell ! ! PR c++/20905 ! * parser.c (cp_parser_type_specifier_seq): Add is_condition ! parameter. ! (cp_parser_new_type_id): Pass it. ! (cp_parser_condition): Likewise. ! (cp_parser_conversion_type_id): Likewise. ! (cp_parser_type_id): Likewise. ! (cp_parser_type_specifier_seq): In a condition, do not allow ! invalid type-specifier combinations. ! (cp_parser_exception_declaration): Adjust call to ! cp_parser_type_specifier_seq. ! ! * cp-tree.def (TINST_LEVEL): Document TINST_IN_SYSTEM_HEADER_P. ! * cp-tree.h (struct tinst_level): Add in_system_header_p. ! (TINST_IN_SYSTEM_HEADER_P): New macro. ! (make_tinst_level): Remove. ! * pt.c (lookup_template_class): Preserve DECL_IN_SYSTEM_HEADER on ! the instantiated class. ! (push_tinst_level): Do not use make_tinst_level. Set ! TINST_IN_SYSTEM_HEADER_P. ! (pop_tinst_level): Likewise. ! (instantiate_class_template): Set in_system_header. ! (instantiate_pending_templates): Likewise. ! * tree.c (make_tinst_level): Remove. ! ! 2005-04-06 Joseph S. Myers ! ! * decl.c (start_decl): Apply pending #pragma weak regardless of ! scope. ! ! 2005-04-06 Mark Mitchell ! ! PR c++/20212 ! * pt.c (regenerate_decl_from_template): Copy attributes for ! parameters from the pattern to the instantiation. ! ! 2005-04-05 Mark Mitchell ! ! PR c++/20734 ! * cp-tree.def (OFFSET_REF): Correct comments. ! * init.c (build_offset_ref): Remove misleading comment. ! * typeck.c (build_unary_op): Handle pointer-to-member creation ! here, rather than ... ! (unary_complex_lvalue): ... here. ! ! 2005-04-06 Jason Merrill ! ! PR c++/19312 ! * tree.c (stabilize_init): Don't bother trying to stabilize ! something with no side-effects. ! ! 2005-04-05 Mark Mitchell ! ! PR c++/20763 ! * decl.c (grokdeclarator): Correct attribute handling. ! ! PR c++/19159 ! * decl2.c (import_export_decl): Use non-COMDAT external linkage ! for virtual tables, typeinfo, etc. that will be emitted in only ! one translation unit on systems without weak symbols. ! ! 2005-04-05 Steven Bosscher ! ! * typeck.c (comptypes): First determine if the types are compatible ! from a target-independent point of view. Check target attributes ! last. ! ! 2005-04-04 Mark Mitchell ! ! PR c++/20679 ! * parser.c (cp_parser_template_name): Fix thinko. ! ! 2005-04-03 Gabriel Dos Reis ! ! PR c++/18644 ! * call.c (build_new_op): Remove check for -Wsynth. ! ! 2005-03-29 Richard Henderson ! ! PR c/20519 ! * decl.c (cp_complete_array_type): Rename from complete_array_type. ! Use the new complete_array_type in c-common.c. Update all callers. ! * cp-tree.h (cp_complete_array_type): Update to match. ! ! 2005-03-24 Geoffrey Keating ! ! * typeck.c (build_static_cast_1): Allow scalar_cast between ! any integral, floating, or enumeration type. ! ! 2005-03-22 Mark Mitchell ! ! * parser.c (cp_parser_warn_min_max): New function. ! (cp_parser_binary_expression): Use it. ! (cp_parser_assignment_operator_opt): Likewise. ! (cp_parser_operator): Likewise. ! ! 2005-03-22 Volker Reichelt ! ! PR c++/19980 ! * decl.c (start_preparsed_function): Robustify. ! ! 2005-03-22 Volker Reichelt ! ! PR c++/20499 ! * parser.c (cp_parser_class_head): Return NULL_TREE when ! encountering a redefinition. ! ! 2005-03-22 Nathan Sidwell ! ! PR c++/20465 ! PR c++/20381 ! * typeck.c (build_ptrmemfunc): Allow OFFSET_REF when processing a ! template. ! ! 2005-03-22 Paolo Carlini ! ! PR c++/20461 ! PR c++/20536 ! * init.c (emit_mem_initializers): Don't crash on undefined ! types. ! ! 2005-03-22 Paolo Carlini ! ! PR c++/20463 ! * parser.c (cp_parser_diagnose_invalid_type_name): ! Check TYPE_BINFO (current_class_type) before attempting ! to emit inform messages. ! ! 2005-03-21 Paolo Carlini ! ! PR c++/20147 ! * semantics.c (finish_stmt_expr_expr): Return immediately ! if error_operand_p (expr). ! ! 2005-03-19 Kriang Lerdsuwanakij ! ! PR c++/20240 ! * decl.c (decls_match): Compare context of VAR_DECL. ! ! 2005-03-19 Kriang Lerdsuwanakij ! ! PR c++/20333 ! * parser.c (cp_parser_postfix_expression) : ! Check the return value of cp_parser_nested_name_specifier. ! ! 2005-03-17 Nathan Sidwell ! ! PR c++/20186 ! * pt.c (contains_dependent_cast_p): Remove. ! (fold_non_dependent_expr): Don't use it. ! (value_dependent_expression_p): Reference_exprs can be dependent. ! ! 2005-03-13 Mark Mitchell ! ! PR c++/20157 ! * pt.c (determine_specialization): Reject non-specializations. ! ! 2005-03-10 Jakub Jelinek ! ! PR c++/18384, c++/18327 ! * decl.c (reshape_init_array): Use UHWI type for max_index_cst ! and index. Convert max_index to size_type_node if it isn't ! host_integerp (, 1). ! ! 2005-03-09 Mark Mitchell ! ! PR c++/20208 ! * pt.c (tsubst_decl): Apply array-to-pointer and ! function-to-pointer conversions to function arguments. ! (regenerate_decl_from_template): Likewise. ! ! 2005-03-08 Nathan Sidwell ! ! PR c++/20186 ! * pt.c (contains_dependent_cast_p): New. ! (fold_non_dependent_expr): Call it. ! ! 2005-03-08 Mark Mitchell ! ! PR c++/20142 ! * init.c (build_vec_init): When determining whether or not the ! element type has an asignment operator, look through all array ! dimensions. ! ! 2005-03-07 Mark Mitchell ! ! * class.c (finish_struct_1): Do not warn about non-virtual ! destructors in Java classes. ! ! 2005-03-06 Kriang Lerdsuwanakij ! ! PR c++/19311 ! * init.c (build_offset_ref): Don't build non-dependent SCOPE_REF. ! * pt.c (build_non_dependent_expr): Don't build NON_DEPENDENT_EXPR ! for OFFSET_TYPE. ! * typeck.c (build_x_unary_op): Don't build non-dependent SCOPE_REF. ! Also set PTRMEM_OK_P for NON_DEPENDENT_EXPR. ! (build_unary_op): Handle building ADDR_EXPR of OFFSET_REF inside ! template. ! ! 2005-03-02 Alexandre Oliva ! ! * name-lookup.c (push_overloaded_decl): Don't error if the new ! decl matches the old one. ! * decl.c (redeclaration_error_message): Likewise. ! ! 2005-03-01 Nathan Sidwell ! ! PR c++/20232 ! * class.c (update_vtable_entry_for_fn): Don't crash on invalid ! covariancy. ! ! * cp-tree.g (THUNK_TARGET): Expand comment. ! * method.c (use_thunk): Make sure we also use the target, if that ! is a thunk. ! ! 2005-02-27 Jakub Jelinek ! ! PR c++/20206 ! * decl.c (cxx_comdat_group): Put thunks for ! TARGET_USE_LOCAL_THUNK_ALIAS_P (function) functions into the same ! comdat group as the thunk target. ! ! 2005-02-24 Volker Reichelt ! ! * call.c, class.c, cp-tree.h, decl2.c, error.c, init.c, mangle.c, ! parser.c: Fix comment typo(s). ! ! 2005-02-24 Jakub Jelinek ! ! PR c++/20175 ! * decl.c (reshape_init): Don't warn about missing braces if STRING_CST ! initializes a char/wchar_t array. ! ! 2005-02-23 Mark Mitchell ! ! PR c++/19878 ! * decl.c (grokvardecl): Set DECL_INTERFACE_KNOWN for declarations ! with internal linkage. ! ! 2005-02-23 Alexandre Oliva ! ! * decl.c (grokvardecl): Don't exempt anonymous types from having ! linkage for variables that have linkage other than "C". ! ! 2005-02-23 Kazu Hirata ! ! * cp-objcp-common.h, error.c: Update copyright. ! ! 2005-02-22 Mark Mitchell ! ! PR c++/20073 ! * decl.c (start_decl_1): Don't clear TREE_READONLY. ! (cp_finish_decl): Likewise. ! (complete_vars): Call cp_apply_type_quals_to_decl. ! * typeck.c (cp_apply_type_quals): Avoid setting TREE_READONLY in ! cases where that's not valid. ! ! PR c++/19991 ! * init.c (integral_constant_value): Iterate if the value of a decl ! is itself a constant. ! ! PR c++/20152 ! * parser.c (cp_parser_class_head): Check for redefintions here. ! * semantics.c (begin_class_definition): Not here. ! ! PR c++/20153 ! * decl2.c (build_anon_union_vars): Add type parameter. ! (finish_anon_union): Pass it. ! ! PR c++/20148 ! * error.c (dump_expr): Do not print the body of a BIND_EXPR. ! Handle STATEMENT_LIST. ! ! PR c++/19883 ! * parser.c (cp_parser_direct_declarator): Always complain about ! non-constant array bounds when in a function scope. ! * semantics.c (finish_id_expression): Do not mark dependent names ! as non-constant. ! ! 2005-02-21 Douglas Gregor ! ! PR c++/19076 ! PR c++/6628 ! * cp-tree.h (cp_apply_type_quals_to_decl): Declared. ! * decl.c (grokdeclarator): Pedwarn about qualifying a function ! type. ! Add qualifiers when declaring a typedef of a function type. ! Member function pointers pick up the qualifiers of the typedef ! used to declare them. ! Don't complain about creating cv-qualified function types. ! Complain about qualified function typedefs that are used to ! declare non-static member functions or free functions. ! Use cp_apply_type_quals_to_decl. ! (start_preparsed_function): Use cp_apply_type_quals_to_decl. ! (grokclassfn): Use cp_apply_type_quals_to_decl. ! * error.c (dump_type_suffix): Print qualifiers for function ! types. ! * pt.c (tsubst_decl): Use cp_apply_type_quals_to_decl. ! (tsubst): When substituting a function type into a member ! pointer type, pass along the qualifiers. ! (unify): Unify member pointers to member function pointers. ! * tree.c (cp_build_qualified_type_real): Function types may be ! qualified. This includes restrict qualifiers. ! * typeck.c (cp_apply_type_quals_to_decl): New function to replace ! use of c_apply_type_quals_to_decl. Drops qualifiers that are being ! added to function types. ! ! 2005-02-20 Zack Weinberg ! ! PR 18785 ! * cp-objcp-common.h (LANG_HOOKS_TO_TARGET_CHARSET): Set to ! c_common_to_target_charset. Delete bogus comment. ! ! 2005-02-18 Richard Henderson ! ! PR libstdc++/10606 ! * except.c (do_get_exception_ptr): New. ! (expand_start_catch_block): Use it. ! ! 2005-02-19 Jakub Jelinek ! ! * decl.c (start_decl_1): Only check TYPE_NEEDS_CONSTRUCTING ! if type is not error_mark_node. ! ! 2005-01-20 Giovanni Bajo ! ! PR c++/19508 ! * decl2.c (grokfield): Do not apply attributes to template parameters ! as they are ignored by tsubst anyway. ! ! 2005-02-18 Jakub Jelinek ! ! PR c++/19813 ! * decl.c (start_decl_1): Clear TREE_READONLY flag if ! its type has TYPE_NEEDS_CONSTRUCTING. ! (complete_vars): Likewise. ! ! 2005-02-17 Alexandre Oliva ! ! PR c++/20028 ! * class.c (finish_struct): Initialize TYPE_SIZE_UNIT of a ! template along with TYPE_SIZE. ! ! PR c++/20022 ! * semantics.c (perform_deferred_access_checks): Use ! get_deferred_access_checks to get the top of the stack. ! ! 2005-02-15 Alexandre Oliva ! ! PR c++/17788 ! * class.c (add_implicitly_declared_members, check_field_decl) ! (check_field_decls, check_bases): Remove arguments, tests and ! assignments of cant_have_default_ctor-related variables. ! ! 2005-02-15 Alexandre Oliva ! ! * decl2.c (mark_used): Set the source location of the used decl to ! the current input location here... ! * method.c (synthesize_method): ... not here. Set input_location ! from the decl instead. ! ! 2005-02-14 Nathan Sidwell ! ! PR c++/19608 ! * parser.c (cp_parser_late_parsing_for_member): Use ! current_function_decl as scope to push to and from. ! ! PR c++/19884 ! * pt.c (check_explicit_specialization): Make sure namespace ! binding lookup found an overloaded function. ! (lookup_template_function): Just assert FNS is an overloaded ! function. ! ! PR c++/19895 ! * decl.c (grokdeclarator): Check for error mark node in ptrmem ! construction. ! ! 2005-02-14 Alexandre Oliva ! ! PR c++/17816 ! * decl.c (redeclaration_error_message): Report redefinition of ! pure virtual function. ! ! 2005-02-14 Nathan Sidwell ! ! PR c++/19891 ! * class.c (build_simple_base_path): Build the component_ref ! directly. ! (update_vtable_entry_for_fn): Walk the covariant's binfo chain ! rather than using lookup_base. ! * search.c (dfs_walk_once): Add non-recursive assert check. ! * typeck.c (build_class_member_access_expr): It is possible for ! the member type to be both const and volatile. ! ! 2005-02-12 Kriang Lerdsuwanakij ! ! PR c++/14479 ! PR c++/19487 ! * pt.c (maybe_check_template_type): Remove. ! * cp-tree.h (maybe_check_template_type): Remove prototype. ! * name-lookup.c (maybe_process_template_type_declaration): Don't ! use maybe_check_template_type. ! ! 2005-02-11 Richard Henderson ! ! PR c++/19632 ! * pt.c (get_mostly_instantiated_function_type): Save and restore ! flag_access_control instead of push/pop_access_scope. ! ! 2005-02-10 Mark Mitchell ! ! PR c++/19755 ! * decl.c (reshape_init): Issue warnings about missing braces. ! ! 2005-02-11 Kazu Hirata ! ! * cp-tree.def, except.c, ptree.c: Update copyright. ! ! 2005-02-09 Mark Mitchell ! ! PR c++/19811 ! * call.c (build_op_delete_call): Check COMPLETE_TYPE_P before ! attempting name lookup. ! ! * parser.c (cp_parser_unqualified_id): Initialize type_decl. ! ! PR c++/19787 ! * call.c (initialize_reference): Robustify. ! ! PR ++/19732 ! * decl.c (grokdeclarator): Check for invalid use of destructor ! names. ! ! PR c++/19762 ! * parser.c (cp_parser_unqualified_id): Avoid creating destructor ! names with invalid types. ! ! PR c++/19826 ! * parser.c (cp_parser_direct_declarator): Allow type-dependent ! expressions as array bounds. ! ! PR c++/19739 ! * parser.c (cp_parser_attributes_list): Allow empty lists. ! ! 2005-02-08 Mark Mitchell ! ! PR c++/19733 ! * class.c (add_method): Don't set TYPE_HAS_DESTRUCTOR. ! (check_bases): Give warnings about a base class with a ! non-virtual destructor, even if it is implicit. ! (finish_struct_bits): Don't copy TYPE_HAS_DESTRUCTOR. ! (maybe_warn_about_overly_private_class): Don't use ! TYPE_HAS_DESTRUCTOR. ! (finish_struct_methods): Don't set TYPE_HAS_DESTRUCTOR. ! (check_for_override): Give it external linkage. ! (add_implicitly_declared_members): Generate destructors lazily. ! (check_field_decls): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not ! TYPE_HAS_DESTRUCTOR. ! (check_bases_and_members): Call check_methods before ! check_field_decls. ! (check_bases_and_members): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not ! TYPE_HAS_DESTRUCTOR. ! (finish_struct_1): Do not use TYPE_HAS_DESTRUCTOR. ! * cp-tree.def (PSEUDO_DTOR_EXPR): Document. ! * cp-tree.h (TYPE_HAS_DESTRUCTOR): Remove. ! (lang_type_class): Add lazy_destructor. ! (CLASSTYPE_LAZY_DESTRUCTOR): New macro. ! (CLASSTYPE_DESTRUCTORS): Robustify. ! (TYPE_HAS_DESTRUCTOR): Remove. ! (check_for_override): Declare. ! (build_vbase_delete): Remove. ! * cvt.c (convert_to_void): Issue errors about pseudo-destructor ! expressions. ! * decl.c (cxx_maybe_build_cleanup): Remove dead code. ! * except.c (dtor_nothrow): Lazily create destructors if necessary. ! (build_throw): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR. ! * init.c (build_delete): Lazily create destructors, if necessary. ! (build_vbase_delete): Remove. ! * method.c (locate_dtor): Simplify. ! (implicitly_declare_fn): Add support for destructors. ! * parser.c (cp_parser_lookup_name): Lazily create destructors, if ! necessary. ! * pt.c (check_explicit_specialization): Don't use ! TYPE_HAS_DESTRUCTOR. ! (instantiate_class_template): Likewise. ! * ptree.c (cxx_print_type): Don't print TYPE_HAS_DESTRUCTOR. ! * rtti.c (emit_support_tinfos): Robustify. ! * search.c (lookup_fnfields_1): Lazily create destructors. ! * typeck.c (build_class_member_access_expr): Remove ! PSEUDO_DTOR_EXPR handling. ! (lookup_destructor): Likewise. ! ! 2005-02-08 Kazu Hirata ! ! * cxx-pretty-print.c, cxx-pretty-print.h, decl.h: Update ! copyright. ! ! 2005-02-07 Mark Mitchell ! ! * parser.c (cp_lexer_start_debugging): Avoid arithmetic operations ! on boolean variables. ! (cp_lexer_stop_debugging): Likewise. ! ! 2005-02-03 Giovanni Bajo ! ! PR c++/17401 ! * parser.c (cp_parser_pure_specifier): Emit a specific error ! message with an invalid pure specifier. ! * decl2.c (grok_function_init): Remove. ! (grokfield): An initializer for a method is a always a pure ! specifier. ! ! 2005-02-02 Matt Austern ! ! PR c++/19628 ! * cp-tree.h (builtin_valid_in_constant_expr_p): Declare. ! * parser.c (cp_parser_postfix_expression): Accept function call in ! constant expression if builtin_valid_in_constant_expr_p is true ! for that function. ! * pt.c (value_dependent_expression_p): Handle CALL_EXPRs properly. ! * semantics.c (finish_id_expression): Accept function call in constant ! expression if builtin_valid_in_constant_expr_p is true for that ! function. ! * tree.c (builtin_valid_in_constant_expr_p): New. ! ! 2005-02-02 Volker Reichelt ! ! PR c++/17413 ! * pt.c (check_instantiated_args): Improve error message. ! Fix logic when to print its second part. ! ! 2005-02-02 Volker Reichelt ! ! * cp-tree.h (complete_type_or_else): Remove macro. ! (complete_type_or_diagnostic): Rename to complete_type_or_else ! and remove last argument. ! * typeck.c (complete_type_or_diagnostic): Rename to ! complete_type_or_else and remove last argument. ! ! 2005-02-02 Volker Reichelt ! ! * cp-tree.h (commonparms): Remove prototype. ! (convert_arguments): Likewise. ! (PFN_FROM_PTRMEMFUNC): Remove. ! * typeck.c (commonparms): Make static. ! (convert_arguments): Add prototype. Make static. ! (PFN_FROM_PTRMEMFUNC): Replace by pfn_from_ptrmemfunc. ! ! 2005-01-31 Mark Mitchell ! ! * parser.c (cp_parser_primary_expression): Don't complain about ! floating-point literals in integral constant expressions when ! !pedantic. ! ! 2005-02-01 Alexandre Oliva ! ! * parser.c (cp_parser_template_id): Revert comment patch too. ! ! PR c++/18757 ! PR c++/19366 ! PR c++/19499 ! * parser.c (cp_parser_template_id): Revert 2004-12-09's patch. ! Issue an error when creating the template id. ! * pt.c (fn_type_unification): Return early if the explicit ! template arg list is an error_mark_node. ! ! 2005-01-31 Mark Mitchell ! ! * decl.c (build_enumerator): Do not issue duplicate error messages ! about invalid enumeration constants. ! * parser.c (cp_parser_non_integral_constant_expression): Always ! set parser->non_integral_constant_expression_p. ! (cp_parser_primary_expression): Add cast_p parameter. Issue ! errors about invalid uses of floating-point literals in ! cast-expressions. ! (cp_parser_postfix_expression): Add cast_p parameter. ! (cp_parser_open_square_expression): Pass it. ! (cp_parser_parenthesized_expression_list): Add cast_p parameter. ! (cp_parser_unary_expression): Likewise. ! (cp_parser_new_placement): Pass it. ! (cp_parser_direct_new_declarator): Likewise. ! (cp_parser_new_initializer): Likewise. ! (cp_parser_cast_expression): Add cast_p parameter. ! (cp_parser_binary_expression): Likewise. ! (cp_parser_question_colon_clause): Likewise. ! (cp_parser_assignment_expression): Likewise. ! (cp_parser_expression): Likewise. ! (cp_parser_constant_expression): If an integral constant ! expression is invalid, return error_mark_node. ! (cp_parser_expression_statement): Pass cast_p. ! (cp_parser_condition): Likewise. ! (cp_parser_iteration_statement): Likewise. ! (cp_parser_jump_statement): Likewise. ! (cp_parser_mem_initializer): Likewise. ! (cp_parser_template_argument): Likewise. ! (cp_parser_parameter_declaration): Likewise. ! (cp_parser_initializer): Likewise. ! (cp_parser_throw_expression): Likewise. ! (cp_parser_attribute_list): Likewise. ! (cp_parser_simple_cast_expression): Likewise. ! (cp_parser_functional_cast): Likewise. ! (cp_parser_late_parsing_default_args): Likewise. ! (cp_parser_sizeof_operand): Save/restore ! non_integral_constant_expression_p. ! ! 2005-01-31 Mike Stump ! ! * parser.c (cp_lexer_new_main): Get the first token, first, before ! doing anything. ! ! 2005-01-31 Mark Mitchell ! ! * decl.c (start_decl): Add missing parentheses. ! ! 2005-01-30 Mark Mitchell ! ! PR c++/19555 ! * cp-tree.h (DECL_USE_TEMPLATE): Expand documentation. ! * decl.c (duplicate_decls): Do not discard ! DECL_IMPLICIT_INSTANTIATION when merging declarations. ! (start_decl): Do not SET_DECL_TEMPLATE_SPECIALIZATION for ! variables that do not have DECL_USE_TEMPLATE. ! ! PR c++/19395 ! * decl.c (grokdeclarator): Refactor code so that qualified names ! are never allowed as the declarator in a typedef. ! ! PR c++/19367 ! * name-lookup.c (do_nonmember_using_decl): Avoid overloading ! builtin declarations. ! ! PR c++/19457 ! * call.c (convert_like_real): Inline call to ! dubious_conversion_warnings here. ! * cp-tree.h (dubious_conversion_warnings): Remove. ! * semantics.c (finish_unary_op_expr): Copy INTEGER_CSTs before ! setting TREE_NEGATED_INT. ! * typeck.c (dubious_conversion_warnings): Remove. ! ! PR c++/19349 ! * name-lookup.c (pushdecl_namespace_level): Avoid accessing free'd ! memory. ! ! 2005-01-28 Mark Mitchell ! ! PR c++/19253 ! * parser.c (cp_parser_diagnose_invalid_type_name): Commit to ! tentative parses. ! ! PR c++/19667 ! * pt.c (redeclare_class_template): Robustify. ! ! 2005-01-27 Steven Bosscher ! ! * decl.c (finish_case_label): Use SWITCH_STMT accessor macros ! instead of SWITCH_EXPR ones. ! * pt.c (tsubst_expr): Likewise. ! * semantics.c (begin_switch_stmt, finish_switch_cond, ! finish_switch_stmt): Likewise. ! ! 2005-01-26 J"orn Rennecke ! ! PR c++/18370 ! * parser.c (cp_parser_initializer_clause): Initialize *non_constant_p. ! ! 2005-01-25 Andrew Pinski ! ! * class.c (abort_fndecl_addr): New variable. ! (build_vtbl_initializer): If we have a pure virtual function ! share the abort function's address. ! Include gt-cp-class.h at the end. ! * config-lang.in (gtfiles): Add cp/class.c. ! ! 2005-01-25 Volker Reichelt ! ! * cxx-pretty-print.c (pp_cxx_statement): Add prototype. Make static. ! (pp_cxx_function_definition): Make static. ! * cxx-pretty-print.h (pp_cxx_statement): Remove prototype. ! (pp_cxx_function_definition): Likewise. ! ! 2005-01-25 Volker Reichelt ! ! * name-lookup.c (print_binding_level): Make static. ! (constructor_name_full): Make static inline. ! (current_decl_namespace): Make static. ! * name-lookup.h (constructor_name_full): Remove prototype. ! (print_binding_level): Likewise. ! (current_decl_namespace): Likewise. ! ! 2005-01-25 Volker Reichelt ! ! * decl.h (debug_bindings_indentation): Remove. ! ! 2005-01-23 Kazu Hirata ! ! * typeck.c: Fix a comment typo. ! ! 2005-01-21 Giovanni Bajo ! ! PR c++/19208 ! * pt.c (fold_decl_constant_value): Always call fold_non_dependent_expr ! at least once. ! (tsubst): Use fold_decl_constant_value in place of a bare call to ! integral_constant_value. ! ! 2005-01-20 Kazu Hirata ! ! * typeck.c (more_qualified_p): Remove. ! * cp-tree.h: Remove the corresponding prototype. ! ! 2005-01-19 Matt Austern ! ! * typeck.c (comptypes): Handle return code from objc_comptypes ! correctly. ! ! 2005-01-19 Kazu Hirata ! ! * cp-tree.h, name-lookup.h: Remove unused prototypes. ! ! 2005-01-19 Kriang Lerdsuwanakij ! ! PR c++/19375 ! * semantics.c (finish_id_expression): Disable access checking for ! already lookuped FIELD_DECL. ! ! 2005-01-18 Kazu Hirata ! ! * decl.c (delete_block): Remove. ! * cp-tree.h: Remove the corresponding prototype. ! ! * decl.c (vtable_decl_p, vtype_decl_p, walk_globals_data, ! walk_vtables_r, walk_vtables, walk_globals_r, walk_globals): ! Remove. ! * cp-tree.h: Remove the corresponding prototypes. ! ! * tree.c (count_functions, bound_pmf_p, cp_is_overload_p, ! cp_update_decl_after_saving, name_p): Remove. ! * cp-tree.h: Remove the corresponding prototypes. ! ! 2005-01-18 Andrew Pinski ! ! PR c/19472 ! * semantics.c (finish_asm_stmt): Strip nops off ! input memory operands. ! ! 2005-01-18 Kazu Hirata ! ! * Make-lang.in, call.c, cvt.c, init.c, rtti.c, tree.c, ! typeck2.c: Update copyright. ! ! 2005-01-16 Kazu Hirata ! ! * class.c (get_enclosing_class): Remove. ! * cp-tree.h: Remove the corresponding prototypes. ! ! * cvt.c (convert_lvalue): Remove. ! * cp-tree.h: Remove the corresponding prototype. ! ! * pt.c (tinst_for_decl): Remove. ! * cp-tree.h: Remove the corresponding prototypes. ! ! * tree.c (hash_chainon): Remove. ! * cp-tree.h: Remove the corresponding prototypes. ! ! 2005-01-15 Jakub Jelinek ! ! PR c++/19263 ! * typeck2.c (split_nonconstant_init_1) : Put a copy ! of CONSTRUCTOR's node into MODIFY_EXPR, as the original is modified. ! ! 2005-01-12 Kaveh R. Ghazi ! ! * Make-lang.in (cp-warn): Don't append $(WERROR). ! ! 2005-01-10 Kazu Hirata ! ! * cp-tree.h: Fix a comment typo. ! ! 2005-01-07 Nathan Sidwell ! ! PR c++/19298 ! * pt.c (tsubst_qualified_id): Call convert_from_reference. ! ! 2005-01-06 Mark Mitchell ! ! PR c++/19244 ! * class.c (add_implicitly_declared_members): Remove dead code. ! * decl.c (grokfndecl): Add sfk parameter. Use it do set ! DECL_CONSTRUCTOR_P. ! (grokdeclarator): Adjust calls to grokfndecl. ! * method.c (implicitly_declare_fn): Improve documentation. ! * parser.c (cp_parser_direct_declarator): Do not consider a ! function to be a constructor if the containing class was ! originally anonymous. ! ! 2005-01-06 Kriang Lerdsuwanakij ! ! PR c++/17154 ! * search.c (lookup_field_1): Handle using declaration in ! class template partial specialization. ! ! 2005-01-06 Kriang Lerdsuwanakij ! ! PR c++/19258 ! * pt.c (push_access_scope): Handle friend defined in class. ! (pop_access_scope): Likewise. ! ! 2005-01-06 Nathan Sidwell ! ! PR c++/19270 ! * pt.c (tsubst_copy) : Handle separately. ! (tsubst_copy_and_build) : Remove obsolete ! array-new handling code. Use build_x_binary_op. ! ! 2005-01-05 Nathan Sidwell ! ! PR c++/19030 ! * cp-tree.h (start_decl): Take pointer to pushed scope, not bool. ! * name-lookup.h (push_scope): Return pushed scope, not flag. ! * name-lookup.c (push_scope): Return scope that should be popped, ! not a flag. ! * decl.c (start_decl): Adjust. ! (grokfndecl): Adjust scope push and pop. ! * decl2.c (check_classfn): Likewise. ! * parser.c (cp_parser_condition, cp_parser_conversion_function_id, ! cp_parser_init_declarator, cp_parser_direct_declarator, ! cp_parser_class_specifier, cp_parser_class_head, ! cp_parser_lookup_name, ! cp_parser_constructor_declarator_p): Likewise. ! * pt.c (instantiate_class_template, ! resolve_typename_type): Likewise. ! ! 2005-01-03 Volker Reichelt ! ! PR c++/14136 ! * parser.c (cp_parser_unqualified_id): Do not issue error message ! for typedef-name as destructor declarator when performing an ! uncommitted tentative parse. ! ! 2005-01-01 Steven Bosscher ! ! PR middle-end/17544 ! * decl.c (finish_function): Fix comment. Annotate the compiler ! generated return with the current file name and line 0. ! ! 2004-12-31 Richard Henderson ! ! PR middle-end/17799 ! * call.c (make_temporary_var_for_ref_to_temp): Set DECL_IGNORED_P. ! * class.c (build_vtable): Don't conditionallize setting it ! based on DWARF2_DEBUG. ! (layout_class_type): Set DECL_IGNORED_P. ! * decl2.c (get_guard): Likewise. ! * rtti.c (get_tinfo_decl, build_lang_decl): Likewise. ! * tree.c (build_local_temp): Likewise. ! ! 2004-12-30 Mark Mitchell ! ! * cp-tree.h (cp_declarator): Split "name" field into ! qualifying_scope and unqualified_name. ! * decl.c (get_scope_of_declarator): Adjust accordingly. ! (grokdeclarator): Likewise. ! * decl2.c (grokfield): Likewise, and adjust call to ! do_class_using_decl. ! * name-lookup.c (do_class_using_decl): Split "decl" into ! "scope" and "name". Remove unnecessary code. ! * name-lookup.h (do_class_using_decl): Adjust declaration. ! * parser.c (make_id_declarator): Split "id" into qualifying_scope ! and unqualified_name. ! (cp_parser_using_declaration): Adjust call to do_class_using_decl. ! (cp_parser_direct_declarator): Adjust to handle the fact that ! cp_parser_declarator_id no longer returns a SCOPE_REF. ! (cp_parser_direct_declarator): Likewise. ! (cp_parser_declarator_id): Do not create a SCOPE_REF for qualified ! names. ! (cp_parser_member_declaration): Adjust call to make_id_declarator. ! (cp_parser_check_declarator_template_parameters): Do not expect a ! SCOPE_REF. ! ! * decl.c (duplicate_decls): Call ggc_free on declarations we will ! not be needing any longer. ! ! PR c++/19190 ! * cvt.c (convert_to_void): Do not use STRIP_NOPs. ! ! 2004-12-28 Richard Henderson ! ! PR inline-asm/15740 ! * semantics.c (finish_asm_stmt): Resolve asm names. Validate input ! constraints. Mark memory inputs addressable. ! ! 2004-12-27 Jason Merrill ! ! * decl.c (expand_static_init): Don't use shortcut if ! targetm.relaxed_ordering. ! ! 2004-12-27 Mark Mitchell ! ! PR c++/19149 ! * decl.c (check_tag_decl): Robustify. ! ! 2004-12-23 Mark Mitchell ! ! PR c++/17595 ! * parser.c (cp_parser_error): Issue better messages about ! #pragma in locations where it is not permitted. ! ! PR c++/17413 ! * pt.c (check_instantiated_args): Remove bogus SFINAE code. ! ! * cvt.c (convert_to_void): Fix typo in comment. ! ! 2004-12-23 Alexandre Oliva ! ! PR c++/18962 ! * pt.c (check_explicit_specialization): Use the argument list from ! the definition in a template function specialization definition. ! ! 2004-12-23 Giovanni Bajo ! ! PR c++/18733 ! * pt.c (check_explicit_specialization): Use special logic to validate ! befriended specializations. ! ! 2004-12-22 Mark Mitchell ! ! * rtti.c (emit_support_tinfos): Avoid using C99 semantics. ! ! PR c++/18464 ! * call.c (build_this): In templates, do not bother with ! build_unary_op. ! * typeck.c (unary_complex_lvalue): In a template, always refuse ! simplifications. ! ! PR c++/18492 ! * cp-gimplify.c (cp_genericize): Relax assertion. ! ! PR c++/11224 ! * cvt.c (convert_to_void): Warn about unused values. ! ! PR c++/18257 ! * rtti.c (emit_support_tinfos): On systems without weak symbols, ! emit the runtime library type-info objects as non-COMDAT. ! ! 2004-12-21 Mark Mitchell ! ! PR c++/18378 ! * call.c (convert_like_real): Do not permit the use of a copy ! constructor to copy a packed field. ! ! PR c++/19063 ! * decl.c (grokdeclarator): Return error_mark_node, not ! void_type_node, to indicate errors. ! * parser.c (cp_parser_template_parameter_list): Robustify. ! (cp_parser_template_parameter): Likewise. ! ! PR c++/19034 ! * tree.c (cp_tree_equal): Handle OVERLOAD. ! ! 2004-12-22 Volker Reichelt ! ! * decl.c (define_label): Use POP_TIMEVAR_AND_RETURN. ! * name-lookup.c (pushdecl_class_level): Likewise. ! ! 2004-12-21 Volker Reichelt ! ! * name-lookup.c (pushtag): Add missing POP_TIMEVAR_AND_RETURN. ! ! 2004-12-21 Andrew Pinski ! ! PR c++/18984 ! * cp-gimplify.c (cp_genericize_r): Don't insert first but instead ! check to see if contains the pointer. Insert the statement before ! returning. ! ! 2004-12-21 Nathan Sidwell ! ! PR c++/14075 ! * decl.c (check_initializer): Check string initializer of array is ! not parenthesized. ! * cp-tree.h (PAREN_STRING_LITERAL_P): New. ! * semantics.c (finish_parenthesized_expr): Mark a STRING_CST. ! * error.c (dump_expr): Add parens, if needed. ! ! * cp-tree.def (TEMPLATE_TYPE_PARM, ! BOUND_TEMPLATE_TEMPLATE_PARM, TYPE_OF_TYPE, TYPENAME_TYPE): Reorder ! for better code efficiency. ! * cp-tree.h (CLASS_TYPE_P): Short circuit IS_AGGR_TYPE check. ! (CAN_HAVE_FULL_LANG_DECL_P): Reorder for better optimization. ! (INTEGRAL_CODE_P, CP_INTEGRAL_TYPE_P, ! INTEGRAL_OR_ENUMERATION_TYPE_P, SCALAR_TYPE_P, ! CP_AGGREGATE_TYPE_P, TYPE_PTROB_P, TYPE_REF_OBJ_P, ! TYPE_PTROBV_P): Likewise. ! ! PR c++/18975 ! * method.c (do_build_copy_constructor): Refactor. Don't const ! qualify a mutable field. ! (do_build_assign_ref): Likewise. ! ! 2004-12-20 Matt Austern ! ! PR c++/19044 ! * decl.c (make_rtl_for_nonlocal_decl): Use ! set_builtin_user_assembler_name. ! ! 2004-12-19 Mark Mitchell ! ! * cp-tree.h (note_decl_for_pch): New function. ! * class.c (build_clone): Call note_decl_for_pch. ! * semantics.c (finish_member_declaration): Likewise. ! (note_decl_for_pch): New function. ! ! 2004-12-17 Steven Bosscher ! ! * init.c (build_zero_init): max_index is the number of ! elements, minus 1. ! ! 2004-12-17 Nathan Sidwell ! ! PR c++/18721 ! * class.c (add_method): Do not push conversion operators into a ! binding level. ! ! * cp-tree.h (CLASSTYPE_PRIMARY_TEMPLATE_TYPE): Reformat. ! * error.c (dump_decl): Remove extraneous braces. ! ! 2004-12-16 Nathan Sidwell ! ! PR c++/18905 ! * cp-tree.h (integral_constant_value): Declare. ! * call.c (null_ptr_cst_p): Use integral_constant_value, not ! decl_constant_value. ! (convert_like_real): Likewise. ! * class.c (check_bitfield_decl): Likewise. ! * cvt.c (ocp_convert): Likewise. ! (convert): Remove unnecessary decl_constant_value call. ! * decl.c (compute_array_index_type): Use integral_constant_value, ! not decl_constant_value. ! (build_enumerator): Likewise. ! * decl2.c (grokfield): Likewise. ! * init.c (decl_constant_value): Simplify. ! (integral_constant_value): New. ! * pt.c (fold_decl_constant_value): Use integral_constant_value, ! remove subsequent check. ! (tsubst): Use integral_constant_value, not decl_constant_value. ! (tsubst_copy, unify): Likewise. ! * typeck.c (decay_conversion): Likewise. ! (build_compound_expr): Remove unnecessary decl_constant_value ! calls. ! (build_static_cast_1, build_reinterpret_cast_1): ! (convert_for_assignment): Remove comment about not calling ! decl_constant_value. ! ! 2004-12-15 Kriang Lerdsuwanakij ! ! PR c++/18825 ! * pt.c (instantiate_class_template): Set input_location for ! friend function. ! (tsubst_friend_function): Don't set input_location here. ! Make sure the context is complete if necessary. ! ! 2004-12-15 Nathan Sidwell ! ! PR c++/18981 ! * parser.c (cp_parser_lookup_name): Remove unneeded TYPENAME_TYPE ! flag setting. ! ! 2004-12-14 Mark Mitchell ! ! PR c++/18738 ! * decl.c (make_typename_type): Do not handle namespace-scoped ! names here. ! (tag_name): Handle typename_type. ! (check_elaborated_type_specifier): Handle typenames. ! * parser.c (cp_parser_diagnose_invalid_type_name): Improve ! comment. ! (cp_parser_elaborated_type_specifier): Use ! cp_parser_diagnose_invalid_type_name. ! ! 2004-12-14 Andrew Pinski ! ! PR c++/18965 ! * init.c (build_zero_init): If the max_index is 0, there is no ! need to create a RANGE_EXPR. ! ! 2004-12-14 Mark Mitchell ! ! PR c++/18793 ! * cp-objcp-common.c (cp_expr_size): Loosen assertion. ! ! 2004-12-14 Nathan Sidwell ! ! PR c++/18949 ! * pt.c (tsubst_copy_and_build): Check that a ! REFERENCE_REF_P is dereferencing a reference type. ! * typeck.c (build_static_cast): Convert from reference even in a ! template. ! (build_reinterpret_cast, build_const_cast, build_c_cast): Likewise. ! ! 2004-12-14 Volker Reichelt ! ! * parser.c (cp_parser_uncommitted_to_tentative_parse_p): New function. ! (cp_parser_name_lookup_error): Use it. ! (cp_parser_check_for_invalid_template_id): Likewise. ! (cp_parser_skip_to_closing_parenthesis): Likewise. ! (cp_parser_nested_name_specifier_opt): Likewise. ! (cp_parser_simple_declaration, cp_parser_template_id): Likewise. ! (cp_parser_parameter_declaration_list): Likewise. ! (cp_parser_parameter_declaration): Likewise. ! (cp_parser_template_name): Let cp_parser_simulate_error perform ! the checking. ! (cp_parser_committed_to_tentative_parse): Remove. ! ! 2004-12-13 Andrew Pinski ! ! PR c++/18968 ! * class.c (build_base_path): Convert the zero constant to the correct ! type when comparing. ! ! 2004-12-13 Mark Mitchell ! ! PR c++/18925 ! * class.c (layout_class_type): Determine the visibility of static ! data members. ! ! 2004-12-12 Roger Sayle ! ! PR middle-end/12454 ! * cp-gimplify.c (gimplify_if_stmt): Optimize the case where the ! condition is a constant and the unexecuted clause is empty. ! ! 2004-12-10 Volker Reichelt ! ! PR c++/18731 ! * parser.c (cp_parser_class_head): Reject typedef-name in class head. ! ! 2004-12-09 Matt Austern ! ! PR c++/18514 ! * name-lookup.c (do_nonmember_using_decl): A real function ! declaration takes precedence over an anticipated declaration. ! ! 2004-12-09 Volker Reichelt ! ! * parser.c (cp_parser_member_declaration): Fix comment typo. ! ! 2004-12-09 Alexandre Oliva ! ! PR c++/18757 ! * parser.c (cp_parser_template_id): Don't create a CPP_TEMPLATE_ID ! if parsing failed. ! ! 2004-12-09 Volker Reichelt ! ! PR c++/18073 ! * typeck.c (build_reinterpret_cast_1): Allow cast from vector type. ! ! 2004-12-09 Nathan Sidwell ! ! PR c++/16681 ! * init.c (build_zero_init): Build a RANGE_EXPR for an array ! initializer. ! ! 2004-12-08 Kelley Cook ! ! * typeck.c: Remove DOS line endings. ! ! 2004-12-08 Kriang Lerdsuwanakij ! ! PR c++/18100 ! * decl.c (lookup_and_check_tag): Diagnose nested class with ! the same name as enclosing class. ! ! 2004-12-08 Nathan Sidwell ! ! PR c++/18803 ! * cp-tree.h (REFERENCE_REF_P): New. ! (CPTI_TYPE_INFO_TYPE): Rename to ... ! (CPTI_CONST_TYPE_INFO_TYPE): ... here. ! (CPTI_TYPE_INFO_REF_TYPE): Remove. ! (type_info_type_node): Rename to ... ! (const_type_info_type_node): ... here. ! (type_info_ref_type): Remove. ! * call.c (build_user_type_conversion): Reformat. ! (resolve_args): Do not convert_from_reference. ! (build_object_call): Call convert_from_reference. ! (prep_operand): Do not convert_from_reference. ! (build_new_method_call): Likewise. ! * class.c (build_vfield_ref): Likewise. ! * cvt.c (convert_to_reference): Likewise. ! (convert_from_reference): Build INDIRECT_REF here, not with ! build_indirect_ref. ! (convert_force): Do not convert_from_reference. ! (build_expr_type_conversion): Likewise. ! * decl.c (grok_reference_init): Likewise. ! * decl2.c (delete_sanity): Likewise. ! * except.c (initialize_handler_parm): Use POINTER_TYPE_P. ! * init.c (build_dtor_call): Do not convert_from_reference. ! * parser.c (cp_parser_template_argument): Unwrap indirected ! reference. Allow TEMPLATE_PARM_INDEX as an object parm. ! * pt.c (tsubst_copy_and_build) : Use ! convert_from_reference, if indicated. ! : Do not convert_from_reference. ! : Convert_from_reference if needed. ! (tsubst_initializer_list): Do not convert_from_reference. ! * rtti.c (init_rtti_processing): Adjust node creation. ! (throw_bad_typeid): Use const_type_info_type_node. ! Do not convert_from_reference. ! (typeid_ok_p): Use const_type_info_type_node. ! (build_typeid, get_typeid): Always return type_info typed node. ! (build_dynamic_cast_1): Dont convert_from_reference. Refactor. ! * semantics.c (finish_stmt_expr_expr): Do not ! convert_from_reference. ! (finish_id_expression): Convert_from_reference as appropriate. ! * typeck.c (decay_conversion): Do not convert_from_reference. ! (finish_class_member_access_expr): Likewise. ! (build_indirect_ref): Use POINTER_TYPE_P. ! (convert_arguments): Do not convert_from_reference. ! (build_modify_expr): Likewise. ! (convert_for_initialization): Likewise. ! * typeck2.c (build_x_arrow): Likewise. ! ! 2004-12-07 Ziemowit Laski ! ! * cp-tree.h (struct lang_type_class): Rename 'objc_protocols' ! field to 'objc_info'. ! ! 2004-12-07 Kazu Hirata ! ! * pt.c: Replace a use of first_rtl_op with TREE_CODE_LENGTH. ! ! 2004-12-07 Roger Sayle ! ! * name-lookup.c (leave_scope): We only need to update ! class_binding_level when leaving a class scope. ! ! 2004-12-06 Ziemowit Laski ! ! * cp-tree.h (struct lang_type_class): Add 'objc_protocols' field. ! ! 2004-12-04 Kriang Lerdsuwanakij ! ! PR c++/17011, c++/17971 ! * pt.c (tsubst_copy) : Check and diagnose ! invalid field. ! (tsubst_copy_and_build) : Check ! error_mark_node after member substitution. ! * semantics.c (finish_id_expression): Call ! finish_non_static_data_member for non-dependent FIELD_DECL. ! ! 2004-12-03 Nathan Sidwell ! ! PR c++/18782 ! * decl.c (grokdeclarator): Make sure class in pointer to member is ! not a namespace. ! ! 2004-12-02 Nathan Sidwell ! ! PR c++/18318 ! * parser.c (cp_parser_new_type_id): Move array size expression ! checks from here ... ! * init.c (build_new): ... to here. ! ! 2004-12-02 Nathan Sidwell ! ! PR c++/18758 ! * parser.c (cp_parser_class_head): Return NULL_TREE when ! push_template_decl fails. Update comment. ! ! 2004-12-02 Kriang Lerdsuwanakij ! ! PR c++/15664, c++/18276 ! * pt.c (tsubst_decl) : Reorganize. Correctly ! tsubst TEMPLATE_DECL that is a TEMPLATE_TEMPLATE_PARM. ! ! 2004-12-02 Kriang Lerdsuwanakij ! ! PR c++/18123 ! * parser.c (cp_parser_type_specifier): Catch template declaration ! of enum. ! ! 2004-12-01 Matt Austern ! ! * name-lookup.c (namespace_binding): Omit alias check for global ! namespace. ! ! 2004-12-01 Nathan Sidwell ! ! PR c++/18729 ! * parser.c (cp_parser_class_name): Check decl's type is not ! error_mark_node. ! ! PR c++/17431 ! * call.c (standard_conversion): Add FLAGS parameter. Do not allow ! derived to base conversion when checking constructor ! accessibility. ! (implicit_conversion): Pass FLAGS to standard_conversion. ! (check_constructir_callable): Disallow conversion functions. ! ! 2004-11-30 Kazu Hirata ! ! * parser.c: Fix comment typos. ! ! 2004-11-27 Mark Mitchell ! ! PR c++/18368 ! * parser.c (cp_parser_check_for_definition_in_return_type): Take ! the defined type as a parameter, and inform the user about the ! possibility of a missing semicolon. ! (cp_parser_explicit_instantiation): Adjust call to ! cp_parser_check_for_definition_in_return_type. ! (cp_parser_init_declarator): Likewise. ! (cp_parser_member_declaration): Likewise. ! ! PR c++/18674 ! * cp-tree.def (TYPENAME_TYPE): Remove discussion of implicit ! typename from comments. ! * cp-tree.h (TYPENAME_IS_ENUM_P): New macro. ! (TYPENAME_IS_CLASS_P): Likewise. ! (make_typename_type): Change prototype. ! * decl.c (struct_typename_info): New type. ! (typename_compare): Expect the second argument to be a ! typename_info, not a tree. ! (build_typename_type): Add tag_type parameter. Do not create a ! new type until necessary. ! (make_typename_type): Add tag_type parameter. ! * error.c (TYPENAME_TYPE): Print tags other than "typename" if ! appropriate. ! * friend.c (make_friend_class): Adjust call to make_typename_type. ! * parser.c (cp_parser_make_typename_type): Likewise. ! (cp_parser_primary_expression): Adjust call to ! cp_parser_lookup_name. ! (cp_parser_unqualified_id): Adjust calls to cp_parser_class_name. ! (cp_parser_class_or_namespace_name): Likewise. ! (cp_parser_postfix_expression): Adjust calls to ! make_typename_type. ! (cp_parser_mem_initializer_id): Adjust calls to ! cp_parser_class_name. ! (cp_parser_type_parameter): Adjust calls to cp_parser_lookup_name. ! (cp_parser_template_name): Likewise. ! (cp_parser_template_argument): Likewise. ! (cp_parser_type_name): Adjust call to cp_parser_class_name. ! (cp_parser_elaborated_type_specifier): Adjust calls to ! make_typename_type and cp_parser_lookup_name. ! (cp_parser_namespace_name): Likewise. ! (cp_parser_class_name): Replace type_p parameter with tag_type. ! Adjust calls to make_typename_type and cp_parser_lookup_name. ! (cp_parser_class_head): Adjust calls to cp_parser_class_name. ! (cp_parser_base_specifier): Likewise. ! (cp_parser_lookup_name): Replace is_type parameter with tag_type. ! Adjust calls to make_typename_type and lookup_qualified_name. ! (cp_parser_lookup_name_simple): Adjust call to ! cp_parser_lookup_name. ! (cp_parser_constructor_declarator_p): Adjust call to ! cp_parser_class_name. ! * pt.c (convert_template_argument): Adjust all to ! make_typename_type. ! (tsubst_decl): Do not pre-substitute the type of the declaration. ! (tsubst): Hand off declarations more quickly. Adjust call to ! make_typename_type. ! ! PR c++/18512 ! * parser.c (cp_parser_postfix_dot_deref_expression): Robustify. ! ! 2004-11-29 Daniel Jacobowitz ! ! PR c/7544 ! * Make-lang.in (cp/decl2.o): Update dependencies. ! * decl2.c (finish_file): Call maybe_apply_pending_pragma_weaks. ! ! 2004-11-29 Kriang Lerdsuwanakij ! ! PR c++/18652 ! * name-lookup.c (pushtag): Change return type to tree. ! * cp-tree.h (pushtag): Adjust declaration. ! * decl.c (xref_tag, start_enum): Use return value of pushtag. ! * pt.c (push_template_decl_real): Return immediately if ! pushdecl_namespace_level returns error_mark_node. ! ! 2004-11-27 Kazu Hirata ! ! * pt.c: Fix a comment typo. ! ! 2004-11-27 Kriang Lerdsuwanakij ! ! Friend class name lookup 4/n ! * class.c (pushclass): Don't call cxx_remember_type_decls. ! * cp-tree.h (clear_anon_tags): Remove declaration. ! * decl.c (grokdeclarator): Don't call lookup_tag_reverse. ! * name-lookup.c (binding_entry_free, binding_table_free): Comment ! out functions. ! (binding_table_find_anon_type, binding_table_reverse_maybe_remap, ! binding_table_remove_anonymous_types, cxx_remember_type_decls, ! bt_print_entry, clear_anon_tags, follow_tag_typedef, lookup_tag, ! lookup_tag_reverse): Remove ! (begin_scope, leave_scope, kept_level_p, print_binding_level): ! Don't use type_decls field in cp_binding_level. ! (maybe_process_template_type_declaration, pushtag): Set ! CLASSTYPE_NESTED_UTDS directly. ! * name-lookup.h (binding_table_remove_anonymous_types, ! cxx_remember_type_decls, lookup_tag, lookup_tag_reverse): Remove ! declaration. ! (cp_binding_level): Remove type_decls field. ! ! 2004-11-26 Kazu Hirata ! ! * typeck.c: Fix a comment typo. ! ! 2004-11-25 Mark Mitchell ! ! PR c++/18445 ! * class.c (instantiate_type): Treat NON_DEPENDENT_EXPRs with ! unknown_type as non matching. Tidy up. ! * pt.c (build_non_dependent_expr): Do not build a ! NON_DEPENDENT_EXPR for a VAR_DECL. ! ! PR c++/18001 ! * cp-tree.h (lvalue_or_else): Remove declaration. ! * tree.c (lvalue_or_else): Remove. ! * typeck.c (build_unary_op): Adjust call to lvalue_or_else. ! (build_modify_expr): Likewise. ! ! PR c++/18625 ! * decl.c (duplicate_decls): Return error_mark_node on error, as ! specified. ! ! PR c++/18466 ! * decl.c (grokvardecl): Keep track of whether or not a there was ! explicit qualification. ! * name-lookup.c (set_decl_namespace): Complain about explicit ! qualification of a name within its own namespace. ! ! PR c++/18545 ! * typeck.c (check_return_expr): Robustify. ! ! 2004-11-25 Kriang Lerdsuwanakij ! ! Friend class name lookup 3/n, PR c++/3332 ! * name-lookup.c (push_inner_scope, pop_inner_scope): New functions. ! (lookup_type_scope): Don't deal with name from user declaration ! specially. ! * name-lookup.h (push_inner_scope, pop_inner_scope): Add declarations. ! * parser.c (cp_parser_class_specifier): Use push_inner_scope and ! pop_inner_scope. ! ! 2004-11-25 Kriang Lerdsuwanakij ! ! Friend class name lookup 2/n, PR c++/14513, c++/15410 ! * name-lookup.c (lookup_name_real): Simplify. ! (lookup_type_scope): Add SCOPE parameter. Handle friend class ! lookup. ! * name-lookup.h (tag_scope): New enum type. ! (lookup_type_scope): Adjust declaration. ! * decl.c (lookup_and_check_tag, xref_tag, xref_tag_from_type): ! Change bool parameter GLOBALIZED to TAG_SCOPE parameter SCOPE. ! (start_enum): Likewise. Add assertion test that NAME is ! IDENTIFIER_NODE. Use anonymous name for dummy ENUMERAL_TYPE in ! case of error. ! * cp-tree.h (xref_tag, xref_tag_from_type): Adjust declarations. ! * parser.c (cp_parser_elaborated_type_specifier, ! cp_parser_class_head): Adjust call to xref_tag. ! * pt.c (lookup_template_class, instantiate_class_template): ! Likewise. ! * rtti.c (init_rtti_processing, build_dynamic_cast_1, ! tinfo_base_init, emit_support_tinfos): Likewise. ! ! 2004-11-25 Joseph S. Myers ! ! * g++spec.c, lex.c: Avoid ` as left quote in diagnostics. ! ! 2004-11-24 Mark Mitchell ! ! PR c++/17473 ! * name-lookup.c (supplement_binding): Do not allow typedefs to be ! redefined in class scope. ! ! PR c++/18285 ! * parser.c (cp_parser_set_decl_type_spec): Do not try to allow ! redefinitions of builtin types other that "bool" or "wchar_t". ! ! 2004-11-24 Steven Bosscher ! ! * decl.c (cxx_init_decl_processing): Don't clear ! flag_inline_functions. ! ! 2004-11-24 Mark Mitchell ! ! * pt.c (tsubst_function_type): Do not permit function types which ! return arrays or functions. ! ! PR c++/18586 ! * parser.c (cp_parser_init_declarator): Do not pop scope twice. ! ! PR c++/18530 ! * cp-tree.h (CTOR_NAME): Remove. ! (DTOR_NAME): Remove. ! * decl.c (initialize_predefined_identifiers): Add spaces to the ! end of constructor and destructor names. ! ! 2004-11-24 Giovanni Bajo ! ! PR c++/8929 ! * decl.c (start_decl): Check for invalid specialization headers. ! ! 2004-11-24 Paolo Bonzini ! ! PR c++/16882 ! ! * call.c (standard_conversion): Move check for conversions between ! vector pointers... ! * typeck.c (ptr_reasonably_similar): ... here. ! ! 2004-11-23 Ben Elliston ! ! * cp-tree.h (context_as_string): Remove extern. ! * error.c (context_as_string): Remove. ! ! * cp-tree.h (cp_type_qual_from_rid): Remove extern. ! * lex.c (cp_type_qual_from_rid): Remove. ! ! * cp-tree.h (do_poplevel): Remove extern. ! (check_multiple_declarators): Likewise. ! * semantics.c (do_poplevel): Make static. ! (check_multiple_declarators): Remove. ! ! * cp-tree.h (check_final_overrider): Remove extern. ! * search.c (check_final_overrider): Make static. ! ! * cp-tree.h (build_artificial_parm): Remove extern. ! * decl2.c (build_artificial_parm): Make static. ! ! 2004-11-22 Giovanni Bajo ! ! PR c++/18354 ! * typeck.c (build_unary_op) : Unify code. ! Make sure the result is always a rvalue. ! ! 2004-11-16 Giovanni Bajo ! ! * decl.c (start_preparsed_function): Call check_function_type even ! in templates. ! (require_complete_types_for_parms): Skip dependent types. ! (check_function_type): Likewise. ! ! 2004-11-16 Steven Bosscher ! ! * Make-lang.in (cp/decl.o, cp/search.o): Don't depend on stack.h. ! * search.c: Don't include it. ! ! 2004-11-15 Andrew Pinski ! ! * cp-gimplify.c: Include pointer-set.h ! (cp_genericize_r): Use pointer_sets instead of a hashtable. ! Also instert the new statement for CLEANUP_STMT. ! (cp_genericize): Use pointer_sets instead of a hashtable. ! * Make-lang.in (cp-gimplify.o): Depend on pointer-set.h. ! ! 2004-11-15 Kriang Lerdsuwanakij ! ! Friend class name lookup 1/n, PR c++/18471 ! * decl.c (lookup_and_check_tag): New function. ! (xref_tag, start_enum): Use it. ! (check_elaborated_type_specifier): Move TEMPLATE_TYPE_PARM check ! before !DECL_IMPLICIT_TYPEDEF_P. Also display previously declared ! location. ! * name-lookup.c (lookup_name_current_level): Rename to ... ! (lookup_name_innermost_nonclass_level): ... this. ! (lookup_type_scope): New function. ! * name-lookup.h (lookup_name_current_level): Rename to ... ! (lookup_name_innermost_nonclass_level): ... this. ! (lookup_type_scope): Add declaration. ! ! 2004-11-14 Kriang Lerdsuwanakij ! ! PR c++/17344 ! * pt.c (coerce_template_parms): Only emit error message about ! invalid template argument when TF_ERROR. ! ! 2004-11-12 Mark Mitchell ! ! PR c++/18389 ! * decl.c (start_decl): Make sure to set *pop_scope_p. Return ! error_mark_node to indicate errors. ! ! PR c++/18429 ! * parser.c (cp_parser_direct_declarator): Disallow non-constant ! array bounds when not inside a function. ! ! PR c++/18436 ! * pt.c (tsubst_copy_and_build): Do not do Koenig lookup when an ! unqualified name resolves to a member function. ! ! PR c++/18407 ! * pt.c (tsubst_copy_and_build): Handle qualified names used from a ! derived class correctly. ! ! * decl2.c (import_export_decl): Fix typo in comment. ! * tree.c (pod_type_p): Likewise. ! ! 2004-11-10 Andrew Pinski ! ! * typeck.c (cxx_mark_addressable): Add braces around the first if. ! ! 2004-11-10 Adam Nemet ! ! PR middle-end/18160 ! * typeck.c (cxx_mark_addressable): Issue an error if address of an ! explicit register variable is requested. ! ! 2004-11-10 Nathan Sidwell ! ! PR c++/18143 ! * cp-tree.h (NON_THUNK_FUNCTION_CHECK, THUNK_FUNCTION_CHECK): New. ! (struct lang_decl_flags): Add thunk_p flag. ! (struct lang_decl): Remove separate fixed_offset. Place ! cloned_function and fixed_offset into union. ! (DECL_CLONED_FUNCTION_P, DECL_CLONED_FUNCTION): Adjust. ! (DECL_THUNK_P, SET_DECL_THUNK_P): Adjust. ! (THUNK_FIXED_OFFSET): Adjust. ! * method.c (make_thunk): Adjust. ! ! 2004-11-09 Mark Mitchell ! ! PR c++/18369 ! * init.c (build_new_1): Handle parenthesized type-ids that name an ! array type. Tidy. ! ! 2004-11-09 Joseph S. Myers ! ! * call.c, class.c, decl.c, decl2.c, error.c, mangle.c, parser.c, ! pt.c, search.c, semantics.c, typeck.c: Use %q, %< and %> for ! quoting in diagnostics. ! * parser.c (cp_parser_sizeof_operand): Use '' instead of `' for ! quoting in printf format. ! * decl.c (duplicate_decls, start_decl): Use %qD instead of ! unquoted %D. ! ! 2004-11-08 Kazu Hirata ! ! * class.c, decl.c, lex.c, name-lookup.c, parser.c, pt.c, ! search.c, typeck2.c: Fix comment formatting. ! ! 2004-11-04 Ulrich Weigand ! ! PR tree-optimization/18184 ! * cp-objcp-common.c (cxx_types_compatible_p): Do not treat pointers ! of different modes or alias-all flags as equivalent. ! * typeck.c (comptypes): Likewise. ! ! 2004-11-04 Giovanni Bajo ! ! DR 49, 100 ! * cp-tree.h (TYPE_REF_OBJ_P): New macro. ! (TYPE_PTR_P, TYPE_PTROB_P, TYPE_PTROBV_P, TYPE_PTRFN_P, ! TYPE_REFFN_P): Document. ! (fold_decl_constant_value): New prototype. ! * pt.c (convert_nontype_argument_function): Rewrite and extract ! parts into... ! (fold_decl_constant_value, convert_nontype_argument_function): New. ! (lookup_template_class): Add comment about useless double call. ! * mangle.c (write_expression): Strip conversions before lowering ! pointer to members. ! * cvt.c (ocp_convert): Check LOOKUP_COMPLAIN for a pedwarn. Disallow ! enum to enum conversion. ! ! 2004-11-02 Mark Mitchell ! ! PR c++/18124 ! * parser.c (cp_parser_type_parameter): Robustify. ! ! PR c++/18155 ! * parser.c (cp_parser_single_declaration): Disallow template ! typedefs. ! ! PR c++/18177 ! * typeck.c (build_const_cast): Use error_operand_p. ! ! 2004-11-02 Ziemowit Laski ! ! * cp-lang.c (cxx_types_compatible_p): Remove prototype and definition. ! (LANG_HOOKS_TYPES_COMPATIBLE_P): Move to cp-objcp-common.h. ! * cp-objcp-common.c (cxx_types_compatible_p): Moved definition here ! from cp-lang.c. ! * cp-objcp-common.h (cxx_types_compatible_p): Moved prototype here ! from cp-lang.c. ! (LANG_HOOKS_TYPES_COMPATIBLE_P): Moved here from cp-lang.c. ! ! 2004-11-01 Nathan Sidwell ! ! PR c++/18064 ! * search.c (check_final_overrider): Deprecate gnu covariant extension. ! ! 2004-10-31 Gabriel Dos Reis ! ! Convert diagnostics to use quoting flag q 9/n ! * typeck.c (build_x_unary_op, convert_member_func_to_ptr, ! get_delta_difference): Use new quotation style. ! * repo.c (reopen_repo_file_for_write): Likewise. ! * pt.c (do_type_instantiation): Likewise. ! * parser.c (cp_parser_diagnose_invalid_type_name): ! * name-lookup.c (push_overloaded_decl, set_decl_namespace): ! * error.c (cp_print_error_function, ! print_instantiation_full_context): Likewise. ! * decl.c (define_label, grok_reference_init, ! maybe_deduce_size_from_array_init, revert_static_member_fn): ! * decl2.c (check_classfn): Likewise. ! * class.c (add_method, check_field_decls, layout_class_type, ! resolve_address_of_overloaded_function): Likewise. ! * call.c (build_x_va_arg, build_over_call): Likewise. ! ! 2004-10-31 Gabriel Dos Reis ! ! Convert diagnostics to use quoting flag q 8/n ! * cvt.c (cp_convert_to_pointer, warn_ref_binding, ! convert_to_reference, ocp_convert, convert_to_void ! cp_convert_to_pointer): Use new quotation style. 2004-10-31 Mark Mitchell PR c++/15172 * typeck2.c (store_init_value): Use split_nonconstant_init even for types that require construction. ! ! 1004-10-28 Matt Austern ! ! PR c++/17542 ! * cp-tree.h (class_key_or_enum_as_string): Declare. ! * error.c (class_key_or_enum): Rename to class_key_or_enum_as_string ! and remove static qualifier. ! * decl.c (shadow_tag): Warn about ignored attributes in class/struct/ ! union/enum declaration. ! ! 2004-10-29 Kazu Hirata ! ! * pt.c: Fix a comment typo. ! ! 2004-10-28 Nathan Sidwell ! ! * typeck.c (composite_pointer_type): Remove comment about DR 195. ! (build_reinterpret_cast_1): Revert DR195 patch. Only emit a ! warning when being pedantic. ! (build_reinterpet_cast, build_c_cast): Adjust. ! ! 2004-10-29 Mark Mitchell ! ! PR c++/17695 ! * decl.c (grokdeclarator): Mark TYPE_DECLs as abstract when they ! appear in a constructor/destructor that will be cloned. ! ! 1004-10-28 Matt Austern ! ! PR c++/14124 ! * decl.c (finish_enum): Handle packed attribute. ! * parser.c (cp_parser_enum_specifier): Process trailing attributes. ! 2004-10-28 Mark Mitchell PR c++/17132 *************** *** 17,34 **** 2004-10-27 Mark Mitchell PR c++/18140 * parser.c (cp_parser_next_token_ends_template_argument_p): Do not include ">>". 2004-10-27 Andrew Pinski ! PR c++/13560 ! * error.c (cp_error_at): Output the context as it might be ! different file as the other location. 2004-10-26 Mark Mitchell PR c++/18093 * search.c (current_scope): Return the innermost non-block scope, not the innermost non-block, non-namespace scope. --- 1780,1809 ---- 2004-10-27 Mark Mitchell + PR c++/17435 + * call.c (convert_like_real): Fix formatting. + (initialize_reference): When binding a temporary to a base class, + ensure that the nominal copy made is to the derived class, not the + base class. + PR c++/18140 * parser.c (cp_parser_next_token_ends_template_argument_p): Do not include ">>". 2004-10-27 Andrew Pinski ! * decl.c (bad_specifiers): Move the q after the %. ! ! 2004-10-27 Andrew Pinski ! ! * parser.c (cp_parser_diagnose_invalid_type_name): Move the q after ! the %. 2004-10-26 Mark Mitchell + * name-lookup.c (do_namespace_alias): Use FROB_CONTEXT. + * search.c (current_scope): Fix prototype. + PR c++/18093 * search.c (current_scope): Return the innermost non-block scope, not the innermost non-block, non-namespace scope. *************** *** 48,54 **** * pt.c (tusbst_copy_and_build): Resolve enumeration constants to their underlying values. ! 2004-10-17 Andrew Pinski PR c++/16301 * name-lookup.c (parse_using_directive): If we have a --- 1823,2050 ---- * pt.c (tusbst_copy_and_build): Resolve enumeration constants to their underlying values. ! PR c++/18161 ! * typeck.c (build_binary_op): Honor build_type, even when in a ! template. ! ! 2004-10-26 Nathan Sidwell ! ! * parser.c (cp_lexer_get_preprocessor_token): Remove unneeded ! padding token checking. ! ! 2004-10-25 Andrew Pinski ! ! PR c++/18121 ! * decl.c (grokdeclarator) : Remove the call ! layout_type as it is already done by create_array_type_for_decl. ! ! 2004-10-22 Nathan Sidwell ! ! PR c++/18095 ! * parser.c (eof_token): Make const, correctly initialize rid and ! location fields. ! (struct cp_lexer): Replace buffer_end pointer with buffer_length ! count. Adjust. ! (cp_lexer_new_main): Directly grow lexer's buffer here. Don't ! zero it out. ! (cp_lexer_new_from_tokens): Adjust. ! (cp_lexer_grow_buffer): Remove. ! (cp_lexer_peek_nth_token, cp_lexer_consume_token, ! cp_lexer_purge_token): Add const casts. ! ! 2004-10-21 Mark Mitchell ! ! PR c++/18073 ! PR c++/10841 ! * cp-tree.h (convert_to_base): Change prototype. ! (build_ptrmemfunc): Likewise. ! (convert_ptrmem): New function. ! * call.c (struct conversion): Adjust documentation for base_p. ! (standard_conversion): Set base_p for ck_pmem conversions as ! appropriate. ! (convert_like_real): Use convert_to_base for ck_pmem and ck_ptr ! conversions. ! * class.c (convert_to_base): Handle both pointers and objects. ! Add nonnull parameter. ! (build_vfield_ref): Adjust call to convert_to_base. ! * cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc. ! (convert_force): Likewise. ! * typeck.c (build_unary_op): Likewise. ! (convert_ptrmem): New function. ! (build_static_cast_1): Use it. ! (build_reinterpret_cast): Allow conversions to vector types. ! (get_delta_difference): Add c_cast_p parameter. ! (build_ptrmemfunc): Likewise. Adjust calls to ! get_delta_difference. ! ! 2004-10-21 Andrew Pinski ! ! PR c++/13560 ! * error.c (cp_error_at): Output the context as it might be ! different file as the other location. ! ! 2004-10-21 Kazu Hirata ! ! * typeck.c: Fix a comment typo. ! ! 2004-10-20 Kriang Lerdsuwanakij ! ! PR c++/13495 ! * decl.c (make_unbound_class_template): Add PARM_LIST parameter. ! * cp-tree.h (make_unbound_class_template): Adjust prototype. ! * parser.c (cp_parser_lookup_name): Adjust call to ! make_unbound_class_template. ! (cp_parser_single_declaration): Handle member class of class ! template as template friend parsing correctly. ! * friend.c (is_friend): Call is_specialization_of_friend for ! template friend class. ! (make_friend_class): Handle member class of class template as ! template friend. ! * pt.c (is_specialization_of_friend): Likewise. ! (instantiate_class_template): Likewise. ! (tsubst): Adjust call to make_unbound_class_template. ! ! 2004-10-20 Nathan Sidwell ! ! * typeck.c (composite_pointer_type): Add comment about DR 195 ! (build_reinterpret_cast_1): Add for_reinterpret_cast_p parameter. ! Allow function pointer conversions that DR195 suggests. ! (build_reinterpret_cast, build_c_cast): Update ! build_reinterpret_cast_1 calls. ! ! 2004-10-20 Kazu Hirata ! ! * call.c, typeck.c: Fix comment typos. ! ! 2004-10-20 Nathan Sidwell ! ! * parser.c (cp_token_position): New typedef. Define VEC thereof. ! (struct cp_lexer): Allow buffer and buffer_end to be NULL. Make ! next_token and last_token cp_token_position. Make saved_tokens a ! VEC(cp_token_position). ! (eof_token): New static variable. ! (CP_SAVED_TOKENS_SIZE): Rename to ... ! (CP_SAVED_TOKEN_STACK): ... here. ! (cp_lexer_new_main): Adjust main lexer creation and buffer ! filling. ! (cp_lexer_new_from_tokens): Do not copy the tokens, merely point ! to the parent buffer. Do not append eof token. ! (cp_lexer_destroy): Only free buffer if non-NULL. Free token ! stack. ! (cp_lexer_next_token, cp_lexer_prev_token): Remove. ! (cp_lexer_token_position, cp_lexer_token_at): New. ! (cp_lexer_saving_tokens): Adjust. Make inline. ! (cp_lexer_advance_token, cp_lexer_token_difference): Remove. ! (cp_lexer_peek_token_emit_debug_info): Fold into ... ! (cp_lexer_peek_token): ... here. ! (cp_lexer_peek_nth_token): Don't peek past EOF. ! (cp_lexer_consume_token): Set next_token to eof_token, if reaching ! EOF. ! (cp_lexer_purge_token): Adjust eof setting. ! (cp_lexer_purge_tokens_after): Likewise. ! (cp_lexer_save_tokens): Push next_token directly. ! (cp_lexer_commit_tokens): Adjust. ! (cp_lexer_rollback_tokens): Pop next_token directly. ! (cp_parser_check_for_invalid_template_id): Adjust token purging. ! (cp_parser_translation_unit): Do not consume the EOF. ! (cp_parser_nested_name_specifier_opt): Adjust token purging. ! (cp_parser_template_id, cp_parser_template_name): Likewise. ! ! 2004-10-19 Mark Mitchell ! ! PR c++/14035 ! * call.c (struct conversion): Add base_p. ! (convert_like): Add c_cast_p argument. ! (convert_like_with_conversion): Likewise. ! (build_conv): Clear base_p. ! (standard_conversion): Set it, for derived-to-base conversions. ! (convert_like_real): Add c_cast_p parameter. Handle pointer ! conversions directly rather than relying on ocp_convert. ! (perform_direct_initialization_if_possible): Add c_cast_p ! parameter. ! * cp-tree.h (perform_direct_initialization_if_possible): Change ! prototype. ! (convert_member_func_to_ptr): New function. ! * typeck.c (check_for_casting_away_constness): Add diag_fn ! parameter. ! (build_static_cast_1): New function, split out from ... ! (build_static_cast): ... here. Use build_static_cast_1. ! (build_reinterpret_cast_1): New function, split out from ... ! (build_reinterpret_cast): ... here. Use build_reinterpret_cast_1. ! (build_const_cast_1): New function, split out from ... ! (build_const_cast): ... here. Use build_const_cast_1. ! (build_c_cast): Rewrite to use build_const_cast_1, ! build_static_cast_1, and build_reinterpret_cast_1. ! (convert_member_func_to_ptr): New function. ! ! 2004-10-19 Paolo Bonzini ! ! PR c++/18047 ! * parser.c (enum cp_parser_prec): Give relational expressions ! a higher precedence than equality expressions. ! ! 2004-10-15 Nathan Sidwell ! ! * cp-tree.h (UNIQUELY_DERIVED_FROM_P): Adjust lookup_base call. ! (ACCESSIBLY_UNIQUELY_DERIVED_P): Remove. ! (PUBLICLY_UNIQUELY_DERIVED_P): Adjust lookup_base call. ! (enum base_access): Reorganize. ! (accessible_base_p, accessible_p): Add consider_local_p parameter. ! * call.c (standard_conversion): Update comment about ! DERIVED_FROM_P. ! (enforce_access): Adjust accessible_p call. ! (build_over_call): Adjust accessible_base_p call. ! * class.c (convert_to_base): Adjust lookup_base call. ! (build_vtbl_ref_1): Likewise. ! (warn_about_ambiguous_bases): Likewise. Add early exit. ! * cvt.c (convert_to_pointer_force) Adjust lookup_base call. ! * search.c (accessible_base_p): Add consider_local_p parameter. ! (lookup_base): Pass consider_local_p to accessible_base_p call. ! (friend_accessible_p): Check whether scope is a class member. ! Remove unnecessary class template check. ! (accessible_p): Add consider_local_p parameter. Use it. ! (adjust_result_of_qualified_name_lookup): Adjust lookup_base call. ! * tree.c (maybe_dummy_object): Likewise. ! * typeck.c (comp_except_type): Use PUBLICLY_UNIQUELY_DERIVED_P. ! (build_class_member_access_expr): Adjust lookup_base call. ! * typeck2.c (binfo_or_else): Likewise. ! * rtti.c (build_dynamic_cast_1): Access can consider friendship ! and current scope. ! ! 2004-10-17 Giovanni Bajo ! ! PR c++/17743 ! * decl2.c (grokfield): Apply attributes also to TYPE_DECLs. ! ! 2004-10-16 Giovanni Bajo ! ! PR c++/10479 ! * parser.c (cp_parser_parenthesized_expression_list): Fold ! non-dependent expressions in attribute lists. ! ! 2004-10-15 Mark Mitchell ! ! PR c++/17042 ! * decl.c (declare_global_var): Use the return value from pushdecl. ! ! PR c++/14667 ! * parser.c (cp_parser_simple_declaration): Do not diagnose invalid ! type names if we have already found a valid type. ! (cp_parser_member_declaration): Likewise. ! ! PR c++/17916 ! * parser.c (cp_parser_member_specification_opt): Handle ! CPP_PRAGMA. ! ! 2004-10-15 Kazu Hirata ! ! * dump.c, g++spec.c, repo.c: Update copyright. ! ! 2004-10-15 Kazu Hirata ! ! * decl.c: Fix a comment typo. ! ! 2004-10-13 Andrew Pinski PR c++/16301 * name-lookup.c (parse_using_directive): If we have a *************** *** 61,70 **** * decl.c (cp_finish_decl): Do not call expand_static_init more than once for a single variable. 2004-10-11 Mark Mitchell PR c++/15786 ! * parser.c (cp_parser_declarator): Add member_p parameter. (cp_parser_condition): Adjust calls to cp_parser_declarator. (cp_parser_explicit_instantiation): Likewise. (cp_parser_init_declarator): Likewise. --- 2057,2102 ---- * decl.c (cp_finish_decl): Do not call expand_static_init more than once for a single variable. + 2004-10-14 Matt Austern + + * Make-lang.in (pt.o): depends on pointer-set.h + * cp-tree.h (cp_walk_subtrees): Last argument is pointer_set_t* now. + * pt.c (struct pair_fn_data): Use pointer_set_t, not htab_t + (for_each_template_parm): Convert from htab_t to pointer_set_t. + * tree.c (cp_walk_subtrees): Last argument is pointer_set_t* now. + + 2004-10-13 Andrew Pinski + + PR c++/17661 + * semantics.c (finish_for_expr): Convert expression to void + so that we don't create temporaries for a?b:c. + + 2004-10-13 Kazu Hirata + + * search.c: Fix a comment typo. + + 2004-10-12 Nathan Sidwell + + * class.c (dfs_modify_vtables): Simplify condition. Return + dfs_skip_bases as appropriate. + (modify_all_vtables): Walk in pre-order. + * search.c (dfs_walk_all, dfs_walk_once_r, + dfs_walk_once_accessible_r): Assert post order function never + returns dfs_skip_bases. + + * search.c (struct lookup_base_data_s): New. + (lookup_base_r): Replace with ... + (dfs_lookup_base): ... this. + (lookup_base): Use dfs_walk_all. + + 2004-10-12 Kazu Hirata + + * search.c: Fix comment typos. + 2004-10-11 Mark Mitchell PR c++/15786 ! * parser.c (cp_parser_declarator): Add member_p parameter. (cp_parser_condition): Adjust calls to cp_parser_declarator. (cp_parser_explicit_instantiation): Likewise. (cp_parser_init_declarator): Likewise. *************** *** 75,92 **** (cp_parser_member_declaration): Likewise. (cp_parser_exception_declaration): Likewise. ! 2004-10-11 Mark Mitchell * decl2.c (finish_anon_union): Robustify. 2004-10-10 Mark Mitchell PR c++/17393 * decl.c (grokdeclarator): Robustify error-recovery on invalid declarations. 2004-10-09 Mark Mitchell PR c++/17821 * parser.c (cp_parser_postfix_dot_deref_expression): If the pseduo-destructor-name production does not work, fall back to the --- 2107,2231 ---- (cp_parser_member_declaration): Likewise. (cp_parser_exception_declaration): Likewise. ! PR c++/17936 ! * cp-tree.h (CLASSTYPE_TEMPLATE_SPECIALIZATION): Add a comment. ! * pt.c (optimize_specialization_lookup_p): Do not optimize lookups ! for members of partial or explicit specializations. + PR c++/17929 * decl2.c (finish_anon_union): Robustify. + 2004-10-11 Nathan Sidwell + + * cp-tree.h (get_dynamic_cast_base_type): Rename to ... + (dcast_base_hint): ... here. + * rtti.c (build_dynamic_cast_1): Use dcast_base_hint. + * search.c (struct dcast_data_s): New. + (dynamic_cast_base_recurse): Remove. Replace with ... + (dfs_dcast_hint_pre, dfs_dcast_base_post): ... these. New. + (get_dynamic_cast_base_type): Rename to ... + (dcast_base_hint): ... here. Use dfs_walk_once_accessible. + (accessible_r): Remove. + (dfs_accessible_post): New, broken out of accessible_r. + (accessible_p): Use dfs_walk_once_accessible. + (dfs_walk_once_accessible_r): New. From accessible_r. + (dfs_walk_once_accessible): New. From acessible_p. + + * cp-tree.h (SAME_BINFO_TYPE_P): New. + * class.c (build_base_path): Use SAME_BINFO_TYPE_P to compare + binfo types. + (convert_to_base_statically, determine_primary_bases, + update_vtable_entry_for_fn, dfs_modify_vtables, build_vtt_inits, + dfs_build_secondary_vptr_vtt_inits, build_ctor_vtbl_group, + accumulate_vtbl_inits, dfs_accumulate_vtbl_inits, + build_vtbl_initializer, add_vcall_offset_vtbl_entries_1): Likewise. + * init.c (expand_member_init): Likewise. + * search.c (lookup_base_r, dynamic_cast_base_recurse, + binfo_via_virtual, copied_binfo, binfo_for_vbase, + original_binfo): Likewise. + * tree.c (copy_binfo): Likewise. + + 2004-10-11 Kazu Hirata + + * semantics.c: Fix comment typos. + + 2004-10-10 Andrew Pinski + + PR c++/17554 + part of c++/17657 + middle-end/17703 + * semantics.c (maybe_cleanup_point_expr): Call + fold_build_cleanup_point_expr. + (maybe_cleanup_point_expr_void): New function. + (add_decl_expr): Call maybe_cleanup_point_expr_void. + (finish_expr_stmt): Likewise. + (finish_return_stmt): Likewise. + (finish_for_expr): Likewise. + (finish_asm_stmt): Likewise. + * typeck.c (condition_conversion): Call + fold_build_cleanup_point_expr. + + 2004-10-10 Andrew Pinski + + PR c++/17907 + * semantics.c (add_decl_expr): If the decl has a size which + has side effects then the decl expression needs a cleanup point. + 2004-10-10 Mark Mitchell PR c++/17393 * decl.c (grokdeclarator): Robustify error-recovery on invalid declarations. + 2004-10-10 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 7/n + * typeck.c (composite_pointer_type_r, composite_pointer_type, + cxx_sizeof_or_alignof_type, cxx_sizeof_or_alignof_expr, + string_conv_p, build_class_member_access_expr, + build_class_member_access_expr, lookup_destructor, + finish_class_member_access_expr, build_indirect_ref, + get_member_function_from_ptrfunc, build_function_call, + convert_arguments, build_binary_op, pointer_diff, build_unary_op, + check_for_casting_away_constness, build_static_cast, + build_reinterpret_cast, build_const_cast, build_c_cast, + build_modify_expr, get_delta_difference, build_ptrmemfunc, + dubious_conversion_warnings, convert_for_assignment, + convert_for_initialization, + maybe_warn_about_returning_address_of_local, check_return_expr): + Use quoting marks. + + * typeck2.c (error_not_base_type, readonly_error, + abstract_virtuals_error, cxx_incomplete_type_diagnostic, + store_init_value, digest_init, build_x_arrow, + build_m_component_ref, require_complete_eh_spec_types): Likewise. + + * tree.c (cp_build_qualified_type_real, + handle_java_interface_attribute, handle_init_priority_attribute): + Likewise. + + * semantics.c (finish_asm_stmt, finish_non_static_data_member, + finish_pseudo_destructor_expr, + check_template_template_default_arg, begin_class_definition, + finish_base_specifier, qualified_name_lookup_error, + finish_id_expression, finish_typeof): Likewise. + + * search.c (lookup_base, check_final_overrider, + look_for_overrides_r): Likewise. + + * rtti.c (get_tinfo_decl, build_dynamic_cast_1): Likewise. + 2004-10-09 Mark Mitchell + PR c++/17867 + * error.c (dump_expr): Correct handling of AGGR_INIT_EXPRs using a + constructor. + + PR c++/17670 + * init.c (build_new): Correct comments. + * parser.c (cp_parser_new_expression): Use NULL_TREE for nelts in + the non-array case. + PR c++/17821 * parser.c (cp_parser_postfix_dot_deref_expression): If the pseduo-destructor-name production does not work, fall back to the *************** *** 95,102 **** PR c++/17826 * tree.c (cp_tree_equal): Handle a BASELINK. - 2004-10-09 Mark Mitchell - PR c++/17524 * cp-tree.h (check_var_type): New function. * decl.c (check_var_type): New function, split out from ... --- 2234,2239 ---- *************** *** 106,129 **** PR c++/17685 * decl.c (grokdeclarator): Disallow declarations of operators as non-functions. ! 2004-10-08 Volker Reichelt PR c++/17868 * error.c (dump_expr): Add missing case for RDIV_EXPR. 2004-10-08 Nathan Sidwell PR c++/17829 * parser.c (cp_parser_postfix_expression): Inhibit Koenig when unqualified lookup finds a member function. 2004-09-28 Roger Sayle PR driver/17537 * g++spec.c (lang_specific_driver): Unrecognized libraries, other than -lc and -lm, may require linking against libstc++. 2004-09-27 Mark Mitchell PR c++/17585 --- 2243,2561 ---- PR c++/17685 * decl.c (grokdeclarator): Disallow declarations of operators as non-functions. ! 2004-10-08 Volker Reichelt PR c++/17868 * error.c (dump_expr): Add missing case for RDIV_EXPR. + 2004-10-08 Kazu Hirata + + * pt.c, search.c: Fix comment typos. + 2004-10-08 Nathan Sidwell + * cp-tree.h (dfs_walk, dfs_walk_real, dfs_unmark, markedp, + unmarkedp): Remove. + (dfs_skip_bases, dfs_walk_all, dfs_walk_once): New. + * class.c (struct find_final_overrider_data): Remove most_derived, + vpath_list and vpath fields. Add path field. + (dfs_find_final_ocerrider_1): Add DEPTH parameter. Adjust. + (dfs_find_final_overrider): Rename to ... + (dfs_find_final_overrider_pre): ... here. Adjust. + (dfs_find_final_overrider_post): Adjust. + (dfs_find_final_overrider_q): Fold into + dfs_find_final_overrider_pre. + (find_final_overrider): Adjust dfs searching. + (dfs_modify_vtables): Don't mark binfo here. + (modify_all_vtables): Use dfs_walk_once. + (build_vtt_inits): Likwise. Use dfs_walk_all. + (dfs_build_secondary_vptr_vtt_inits): Don't mark binfo here. + Return dfs_skip_bases as appropriate. + (dfs_fixup_binfo_vtbls): Return dfs_skip_bases as appropriate. + * init.c (dfs_initialized_vtbl_ptrs): Return dfs_skip_bases as + appropriate. Don't mark binfo here. + (initialize_vtbl_ptrs): Use dfs_walk_once. + * search.c (struct vbase_info): Remove unused struct. + (access_in_type): Use dfs_walk_once. + (dfs_access_in_type): Don't mark binfo here. + (dfs_accessible_queue_p, dfs_accessible_p) Remove. + Fold into ... + (accessible_r): ... here. New. Specialize dfs_walk_once. + (accessible_p): Use accessible_r. + (lookup_field_queue_p): Remove. Fold into ... + (lookup_field_r): ... here. Adjust. + (lookup_member): Use dfs_walk_all. + (dfs_walk_real, dfs_walk): Replace with ... + (dfs_walk_all, dfs_walk_once): ... these. + (dfs_walk_once_r, dfs_unmark_r): Workers for dfs_walk_once. + (dfs_unmark, unmarkedp, markedp): Remove. + (dfs_get_pure_virtuals): Don't mark binfo here. + (get_pure_virtuals): Use dfs_walk_once. + (dfs_debug_unmarked_p): Remove. Fold into ... + (dfs_debug_mark): ... here. + (note_debug_info_needed): Use dfs_walk_all. + + 2004-10-07 Andrew Pinski + + * pt.c (tsubst_expr) : Look passed the + CLEANUP_POINT_EXPR to get the asm expression. + + 2004-10-07 Mark Mitchell + + * cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag. + (DECL_MEMBER_TEMPLATE_P): New macro. + (is_member_template): Remove. + (class_method_index_for_fn): New function. + * pt.c (build_over_call): Use DECL_MEMBER_TEMPLATE_P. + * class.c (finish_struct_methods): Remove out-of-date comment. + * decl.c (copy_fn_p): Use DECL_MBMER_TEMPLATE_P. + * decl2.c (check_classfn): Use DECL_MEMBER_TEMPLATE_P and + class_method_index_for_fn. + * pt.c (is_member_template): Remove. + (is_member_template_class): Likewise. + (optimize_specialization_lookup_p): New function. + (retrieve_specialization): Optimize lookups for members that are + not member templates. + (register_specialization): Adjust accordingly. + (build_template_decl): Add member_template_p parameter. Set + DECL_MEMBER_TEMPLATE_P. + (process_partial_specialization): Adjust call to + retrieve_specialization. + (push_template_decl_real): Determine whether the template is a + member template. + (lookup_template_class): Use retrieve_specialization. + (tsubst_decl): Adjust call to retrieve_specialization. + (tsubst_exception_specification): New function. + (tsubst): Use it. + (tsubst_copy): Use DECL_MEMBER_TEMPLATE_P. + (instantiate_template): Adjust call to retrieve_specialization. + (regenerate_decl_from_template): Do not actually generate a new + DECL. + (instantiate_decl): Adjust call to retrieve_specialization. + (class_method_index_for_fn): New method. + + 2004-10-07 Andrew Pinski + + * parser.c (cp_parser_asm_definition): Look passed the + CLEANUP_POINT_EXPR to get the asm expression. + + 2004-10-06 Andrew Pinski + + PR c++/17368 + * semantics.c (finish_asm_stmt): Asm expressions need cleanup + also. + + 2004-10-05 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 6/n + * pt.c (finish_member_template_decl, check_specialization_scope, + maybe_process_partial_specialization, determine_specialization, + check_explicit_specialization, maybe_check_template_type, + process_partial_specialization, check_default_tmpl_args, + push_template_decl_real, redeclare_class_template, + convert_nontype_argument, coerce_template_parms, + lookup_template_class, push_tinst_level, + instantiate_class_template, tsubst_arg_types, + tsubst_function_type, tsubst, tsubst_qualified_id, + tsubst_copy_and_build, check_instantiated_args, + do_decl_instantiation, do_type_instantiation, + invalid_nontype_parm_type_p, check_specialization_namespace, + convert_template_argument, determine_specialization, + check_template_shadow, tsubst_decl + instantiate_pending_templates): Use quoting marks. + + 2004-10-05 Nathan Sidwell + PR c++/17829 * parser.c (cp_parser_postfix_expression): Inhibit Koenig when unqualified lookup finds a member function. + 2004-10-04 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 5/n + * parser.c (cp_parser_name_lookup_error, + cp_parser_diagnose_invalid_type_name, + cp_parser_primary_expression, cp_parser_unqualified_id, + cp_parser_nested_name_specifier_opt, cp_parser_labeled_statement, + cp_parser_jump_statement, cp_parser_simple_declaration, + cp_parser_decl_specifier_seq, cp_parser_mem_initializer_id, + cp_parser_type_parameter, cp_parser_template_id, + cp_parser_template_name, cp_parser_direct_declarator, + cp_parser_parameter_declaration_list, cp_parser_class_head, + cp_parser_base_specifier, cp_parser_lookup_name, + cp_parser_late_parsing_default_args, + cp_parser_optional_template_keyword + cp_parser_elaborated_type_specifier, cp_parser_check_class_key, + cp_parser_check_access_in_redeclaration): Use quoting marks. + + * name-lookup.c (supplement_binding, pushdecl, + check_for_out_of_scope_variable, validate_nonmember_using_decl, + do_nonmember_using_decl, lookup_tag, set_decl_namespace, + push_namespace, do_namespace_alias, do_using_directive, + ambiguous_decl, lookup_namespace_name, add_function): Likewise. + + * method.c (use_thunk): Likewise. + + * lex.c (unqualified_name_lookup_error, + unqualified_fn_lookup_error): Likewise. + + 2004-10-04 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 4/n + * except.c (decl_is_java_type, build_throw, + is_admissible_throw_operand, check_handlers_1, check_handlers): + Use quoting formats. + * friend.c (add_friend, make_friend_class, do_friend): Likewise. + * init.c (sort_mem_initializers, emit_mem_initializers, + member_init_ok_or_else, expand_member_init, is_aggr_type, + build_offset_ref, build_java_class_ref): Likewise. + + 2004-10-03 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 3/n + * decl.c (pop_label, duplicate_decls, redeclaration_error_message, + redeclaration_error_message, lookup_label, check_goto, + make_typename_type, make_unbound_class_template, + fixup_anonymous_aggr, check_tag_decl, start_decl, start_decl_1, + grok_reference_init, layout_var_decl, maybe_commonize_var, + check_for_uninitialized_const_var, reshape_init_array, + reshape_init, check_initializer, cp_finish_decl, + member_function_or_else, bad_specifiers, grokfndecl, grokvardecl, + check_static_variable_definition, compute_array_index_type, + create_array_type_for_decl, check_special_function_return_type, + grokdeclarator, check_default_argument, grokparms, + grok_ctor_properties, grok_op_properties, + check_elaborated_type_specifier, xref_tag, finish_enum, + build_enumerator, check_function_type, start_preparsed_function, + store_parm_decls): Use quoting formats. + * decl2.c (grok_array_decl, delete_sanity, check_member_template, + check_java_method, check_classfn, finish_static_data_member_decl, + grokfield, grokbitfield, grok_function_init, + build_anon_union_vars, coerce_new_type, coerce_delete_type, + check_default_args): Likewise. + * parser.c (cp_parser_decl_specifier_seq): Likewise. + + 2004-10-03 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 2/n + * class.c (build_base_path, add_method, alter_access, + handle_using_decl, check_bases, + maybe_warn_about_overly_private_class, find_final_overrider, + warn_hidden, finish_struct_anon, add_implicitly_declared_members, + check_bitfield_decl, check_field_decls, layout_empty_base, + build_base_field, check_methods, layout_virtual_bases, + warn_about_ambiguous_bases, layout_class_type, finish_struct_1, + resolve_address_of_overloaded_function, instantiate_type, + note_name_declared_in_class): Use format flag "q" for quoting. + + 2004-10-03 Gabriel Dos Reis + + Convert diagnostics to use quoting flag q 1/n + * error.c (locate_error): Ignore quoting flag q. + * call.c (build_user_type_conversion_1, build_operator_new_call, + build_object_call, op_error, build_conditional_expr, + build_new_op, build_op_delete_call, enforce_access, + convert_like_real, convert_arg_to_ellipsis, build_x_va_arg, + convert_default_arg, build_over_call, build_new_method_call, + joust, perform_implicit_conversion, initialize_reference): Use the + quoting flag q. + + 2004-10-03 Andrew Pinski + + PR c++/17797 + * typeck.c (build_reinterpret_cast): Return if the inner type + is error_mark_node. + + 2004-10-01 Jan Hubicka + + * semantics.c (expand_body): Update call of tree_rest_of_compilation. + + 2004-09-30 Nathan Sidwell + + * cp-tree.h (struct lang_decl): Shrink by reordering fields and + turning operator_code and fixed_offset into bitfields. + + 2004-09-29 Joseph S. Myers + + * decl.c (duplicate_decls): Merge TREE_DEPRECATED. + + 2004-09-29 Jason Merrill + + PR tree-optimization/17697 + * decl.c (duplicate_decls): Copy TREE_NOTHROW from newdecl to olddecl. + + 2004-09-28 Jason Merrill + + PR middle-end/17525 + * class.c (build_base_field): Set TYPE_MODE. + 2004-09-28 Roger Sayle PR driver/17537 * g++spec.c (lang_specific_driver): Unrecognized libraries, other than -lc and -lm, may require linking against libstc++. + 2004-09-28 Kazu Hirata + + * tree.c: Fix a comment typo. + + 2004-09-28 Nathan Sidwell + + * class.c (VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P): Remove. + (struct secondary_vptr_vtt_init_data_s): New. + (build_vtt_inits): Adjust dfs_walkers. + (dfs_build_secondary_vptr_vtt_inits): Caller data is a + secondary_vptr_vtt_init_data_s structure. Adjust. + (dfs_ctor_vtable_bases_queue_p): Remove. + (dfs_fixup_binfo_vtbls): No need to clear BINFO_MARKED. Simplify. + + * pt.c (struct get_template_base_data_s): Remove. + (get_template_base_r): Fold into get_template_base. + (get_template_base): Walk base binfos directly in inheritance + graph order. + + 2004-09-27 Mark Mitchell + + PR c++/17642 + * cp-tree.h (fold_if_not_in_template): New function. + * call.c (build_conditional_expr): Use fold_if_not_in_template. + (build_cxx_call): Likewise. + * cvt.c (convert_to_complex): Likewise. + (ocp_convert): Likewise. + (convert): Likewise. + (convert_force): Likewise. + * decl.c (compute_array_index_type): Clear + processing_template_decl while folding array bounds. + * pt.c (convert_nontype_argument): Clear + processing_template_decl while processing non-type argument + initialization. + * tree.c (fold_if_not_in_template): New function. + * typeck.c (build_class_member_access_expr): Use + fold_if_not_in_template. + (build_array_ref): Likewise. + (build_binary_op): Likewise. Do not try to optimize computations + when processing templates. + (cp_pointer_int_sum): Use fold_if_not_in_template. + (pointer_diff): Likewise. + (build_unary_op): Likewise. + (build_reinterpret_cast): Likewise. + (get_delta_difference): Likewise. + (expand_ptrmemfunc_cst): Likewise. + (dubious_conversion_warnings): Likewise. + + 2004-09-27 Matt Austern + + * cp/parser.c (struct cp_token): New one-bit field , implicit_extern_c + (cp_lexer_get_preprocessor_token): Set implicit_extern_c for + tokens that come from headers that are implicitly extern "C". + (struct cp_parser): new one-bit field, implicit_extern_c. + (cp_parser_new): Set parser's implicit_extern_c to false. + (cp_parser_translation_unit): Pop lang context if we were in a + header that was implicitly extern "C". + (cp_parser_declaration_seq_opt): Push/pop lang context as + required by the token's and parser's implicit_extern_c. + 2004-09-27 Mark Mitchell PR c++/17585 *************** *** 132,156 **** * semantics.c (finish_qualified_id_expr): Use it. (finish_id_expression): Likewise. ! 2004-09-22 Giovanni Bajo ! PR c++/14179 ! * parser.c (cp_parser_initializer): Speed up parsing of simple ! literals as initializers. ! 2004-09-21 Giovanni Bajo PR c++/14179 * decl.c (reshape_init): Extract array handling into... (reshape_init_array): New function. Use integers instead of trees for indices. Handle out-of-range designated initializers. 2004-09-16 Mark Mitchell PR c++/17501 * parser.c (cp_parser_nested_name_specifier): Do not resolve typename types if the user explicitly said "typename". 2004-09-13 Mark Mitchell PR c++/16162 --- 2564,3006 ---- * semantics.c (finish_qualified_id_expr): Use it. (finish_id_expression): Likewise. ! PR c++/17585 ! * semantics.c (finish_id_expression): Do not add "this->" to ! static member functions. ! 2004-09-27 Nathan Sidwell ! PR c++/17681 ! * error.c (dump_type): Change TREE_VEC case into TREE_BINFO. ! ! * class.c (struct count_depth_data): Remove. ! (dfs_depth_post, dfs_depth_q): Remove. ! (find_final_overrider): Use number of vbase classes as depth ! bound. ! ! * cp-tree.h (types_overlap_p): Remove. ! * search.c (struct overlap_info): Remove. ! (dfs_check_overlap, dfs_no_overlap_yet, types_overlap_p): Remove. ! ! * pt.c (GTB_VIA_VIRTUAL, GTB_IGNORE_TYPE): Remove. ! (get_template_base_recursive): Remove. Replace with ... ! (get_template_base_r): ... this. ! (struct get_template_base_data_s): New. ! (get_template_base): Use get_template_base_r via dfs_walk. Always ! return NULL on failure. ! (unify): Remove error_mark_node check from get_template_base result. ! ! 2004-09-24 Paolo Bonzini ! ! * parser.c (cp_parser_expression_stack): Clarify why it is ! an array of NUM_PREC_VALUES elements. ! (cp_parser_binary_expression): Clarify why we do not need to ! handle stack overflow. ! ! 2004-09-24 Nathan Sidwell ! ! PR c++/16889 ! * search.c (lookup_field_queue_p): Correct check for hidden base. ! ! * search.c (bfs_walk): Remove. ! (lookup_member): Use dfs_walk_real. ! (dfs_walk_real): Move and adjust documentation from bfs_walk. ! ! 2004-09-23 Zack Weinberg ! ! * decl.c (grokfndecl): If ::main is found not to return int, ! correct it after issuing a diagnostic. ! (grokdeclarator): If the incoming type was error_mark_node, do ! not complain about declaring something with no type. ! (start_function): Change check for ::main not returning int to ! an assertion, as grokfndecl now catches this when the user did it. ! * init.c (perform_member_init, sort_mem_initializers) ! (emit_mem_initializers): Make most diagnostics be issued on ! the line of current_function_decl, not whatever the current ! input line is. ! * parser.c (cp_lexer_peek_token_emit_debug_info): Surround ! definition and declaration with #ifdef ENABLE_CHECKING. ! Avoid unnecessary use of fprintf. ! (cp_lexer_print_token, cp_lexer_debug_stream): Adjust stub ! definitions to avoid warnings. ! (cp_lexer_new_main): Add assertion that first token is not a ! padding token. ! (cp_lexer_new_from_token_array): Fold into ... ! (cp_lexer_new_from_tokens): ... here. Add assertion that ! first token is not a padding token. ! (cp_lexer_set_source_position_from_token): Move nearer to callers. ! Remove unused lexer argument. ! (cp_lexer_peek_token): Just print debugging report (if enabled) ! and return lexer->next_token. ! (cp_lexer_skip_purged_tokens): Delete. ! (cp_lexer_next_token_is, cp_lexer_next_token_is_not): Make ! inline, simplify bodies. ! (cp_lexer_peek_nth_token): Add debugging report a la ! cp_lexer_peek_token. ! (cp_lexer_consume_token): Correct commentary. Advance over ! purged tokens here. Set current source position here, from ! token to be returned. Avoid unnecessary use of fprintf. ! (cp_lexer_purge_token): Advance next_token pointer over this and ! subsequent purged tokens. ! (cp_parser_error): Adjust source position to that of the ! peeked token. ! (cp_parser_push_lexer_for_tokens, cp_parser_pop_lexer): New functions. ! (cp_parser_string_literal): Remove some excessive cleverness. ! (cp_parser_enum_specifier): Call start_enum before consuming ! the opening brace. ! (cp_parser_member_declaration): Make the "extra semicolon" ! diagnostic consistently-worded with the other place this is ! diagnosed. Explicitly set the diagnostic location to the ! location of the offending semicolon. ! (cp_parser_enclosed_template_argument_list): Use % quoting ! in diagnostics. Do not use cp_parser_require. Set location ! of diagnostics about improper use of '>>' to location of ! offending token. ! (cp_parser_late_parsing_for_member): ! Use cp_parser_push_lexer_for_tokens and cp_parser_pop_lexer. ! (cp_parser_late_parsing_default_args): Likewise. Manually ! move some logic outside the loop. ! ! 2004-09-23 Andrew Pinski ! ! PR c++/17618 ! * cvt.c (cp_convert_to_pointer): Return early when the type is ! an error_mark_node. ! ! 2004-09-21 Fariborz Jahanian ! ! PR c++/13989 ! PR c++/9844 ! * decl.c (grokfndecl): Add new argument "attrlist", use it ! to call cplus_decl_attributes. ! (start_function): Remove call to cplus_decl_attributes. ! * cvt.c (ocp_convert): Add support to use type conversion ! function to vector type. ! * parser.c (cp_parser_conversion_type_id): Add attributes, if any, ! to the parsed type. ! ! 2004-09-23 Paolo Bonzini ! ! PR c++/17596 ! ! * parser.c (cp_parser_token_tree_map_node, ! cp_parser_pm_expression, cp_parser_additive_expression, ! cp_parser_multiplicative_expression, cp_parser_shift_expression, ! cp_parser_relational_expression, cp_parser_equality_expression, ! cp_parser_and_expression, cp_parser_exclusive_or_expression, ! cp_parser_inclusive_or_expression, ! cp_parser_logical_and_expression, ! cp_parser_logical_or_expression): Removed. ! (enum cp_parser_prec, struct cp_parser_token_tree_map_node, ! binops, binops_by_token): New. ! (cp_parser_assignment_expression): Use cp_parser_binary_expression. ! (cp_parser_new): Initialize binops_by_token. ! (cp_parser_binary_expression): Rewritten. ! (N_CP_TTYPES): New. ! ! 2004-09-23 Kazu Hirata ! ! * parser.c: Fix a comment typo. ! ! 2004-09-23 Nathan Sidwell ! ! PR c++/17620 ! * decl.c (xref_basetypes): Look through typedefs before checking ! for duplicate base. ! ! 2004-09-22 Nathan Sidwell ! ! * cp-tree.h (unemitted_tinfo_decls): Make a VEC(tree). ! * decl2.c (cp_finish_file): Adjust tinfo decl emission loop. ! * rtti.c (unemitted_tinfo_decls): Make a VEC(tree). ! (init_rtti_processing): Initialize it to something realistic. ! (get_tinfo_decl): Adjust pushing the new decl. ! ! * cp-tree.h (struct lang_type_class): Remove marked flags, add ! diamond_shaped and repeated_base flags. Reorder to keep 8-bit blocks. ! (TYPE_MARKED_P): New. ! (CLASSTYPE_DIAMOND_SHAPED_P, CLASSTYPE_REPEATED_BASE_P): New. ! (CLASSTYPE_MARKED_N, SET_CLASSTYPE_MARKED_N, ! CLEAR_CLASSTYPE_MARKED_N): Remove. ! (CLASSTYPE_MARKED_*, SET_CLASSTYPE_MARKED_*, ! CLEAR_CLASSTYPE_MARKED_*): Remove. ! * decl.c (xref_basetypes): Use TYPE_MARKED_P. Determine diamond ! shaped and repeated base properties. ! * lex.c (cxx_make_type): Don't clear TYPE_ALIAS_SET. ! * rtti.c (dfs_class_hint_mark, dfs_class_hint_unmark, ! class_hint_flags): Remove. ! (get_pseudo_ti_init): Use CLASSTYPE_REPEATED_BASE_P and ! CLASSTYPE_DIAMOND_SHAPED_P. ! ! 2004-09-21 Ziemowit Laski ! ! * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): Moved here from ! cp-objcp-common.h. ! (objcp_tsubst_copy_and_build): Reformat function signature. ! * cp-objcp-common.h (objcp_tsubst_copy_and_build): Likewise. ! (LANG_HOOKS_FOLD_OBJ_TYPE_REF): Moved to cp-lang.c. ! ! 2004-09-21 Zack Weinberg ! ! * parser.c (cp_lexer_peek_token, cp_lexer_consume_token): ! Don't handle CPP_PRAGMA tokens specially. ! (cp_lexer_handle_pragma): Use cp_lexer_consume_token. Don't ! purge the token; do clear token->value after processing. Add ! assertion at beginning that token->value is nonzero. ! (cp_parser_statement, cp_parser_declaration_seq_opt): Handle ! CPP_PRAGMA as a full statement or declaration in its own right. ! ! 2004-09-21 Matt Austern ! ! PR c++/15049 ! * decl.c (grokvardecl): Accept declarations of global variables ! using anonymous types. ! ! 2004-09-21 Roger Sayle ! ! PR c++/7503 ! * tree.c (lvalue_p_1): Disallow MIN_EXPR and MAX_EXPR as lvalues ! if either operand has side-effects. ! * typeck.c (rationalize_conditional_expr): Assert that neither ! operand of MIN_EXPR or MAX_EXPR has side-effects. ! (build_modify_expr): Add support for MIN_EXPR and MAX_EXPR. ! Check that the "lhs" is a valid lvalue, i.e. that neither operand ! of a MIN_EXPR or MAX_EXPR has a side-effect. ! ! 2004-09-21 Nathan Sidwell ! ! * cp-tree.h (struct lang_type_header): Remove ! uses_multiple_inheritance field. ! (TYPE_USES_MULTIPLE_INHERITANCE): Remove. ! (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P): Remove. ! (TYPE_USES_VIRTUAL_BASECLASSES): Remove. ! (DECL_NEEDS_VTT_PARM_P): Use CLASSTYPE_VBASECLASSES. ! (TYPE_CONTAINS_VPTR_P): Likewise. ! * call.c (add_template_candidate_real): Use ! CLASSTYPE_VBASECLASSES. ! (build_special_member_call): Likewise. ! * class.c (finish_struct_bits): Remove ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P & TYPE_USES_VIRTUAL_BASECLASSES ! bookkeeping. ! (check_bases_and_members): Use TYPE_CONTAINS_VPTR_P. ! (create_vtable_ptr): Remove TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P ! bookkeeping. ! (build_vtt_inits): Use CLASSTYPE_VBASECLASSES. ! (accumulate_vtbl_inits, build_vbase_offset_vtbl_entries): ! Likewise. ! * decl.c (xref_basetypes): Remove TYPE_USES_MULTIPLE_INHERITANCE, ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P, TYPE_USES_VIRTUAL_BASECLASSES ! bookkeeping. ! (cxx_maybe_build_cleanup): Use CLASSTYPE_VBASECLASSES. ! * decl2.c (maybe_retrofit_in_chrg): Likewise. ! * init.c (expand_member, push_base_cleanups): Likewise. ! * pt.c (instantiate_class_template): Remove ! TYPE_USES_MULTIPLE_INHERITANCE, ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P, TYPE_USES_VIRTUAL_BASECLASSES ! bookkeeping. ! * ptree.c (cxx_print_type): Remove TYPE_USES_MULTIPLE_INHERITANCE ! check. ! * typeck2.c (process_init_constructor): Replace some sorrys with ! asserts. ! ! 2004-09-21 Andreas Tobler ! ! * decl.c (reshape_init_array): Initialize max_index_cst to fix ! bootstrap failure. ! ! 2004-09-20 Mark Mitchell ! ! PR c++/17530 ! * pt.c (tsubst): Fix parentheses to accomodate emacs. ! (tsubst_baselink): If we get a single function, mark it as used. ! ! 2004-09-20 Matt Austern ! Zack Weinberg ! ! * decl.c (make_rtl_for_nonlocal_decl, start_preparsed_function): ! Apply lbasename to input_filename before passing to get_fileinfo. ! * semantics.c (begin_class_definition): Likewise. ! * lex.c (handle_pragma_interface): Apply get_fileinfo to the ! correct filename. Rename variables to be less confusing. ! (handle_pragma_implementation): Likewise. Disable "appears ! after file is included" diagnostic. ! ! * parser.c (struct cp_token): Add in_system_header fiag. ! (CP_TOKEN_BLOCK_NUM_TOKENS, struct cp_token_block) ! (CP_TOKEN_BUFFER_SIZE, cp_token_cache_push_token) ! (CPP_NONE, cp_lexer_read_token): Delete. ! (struct cp_lexer): Remove first_token, string_tokens, ! main_lexer_p fields. Clarify comments. ! (struct cp_token_cache): Now just a pair of pointers. ! (CP_LEXER_BUFFER_SIZE): New #define. ! (CPP_PURGED): New fake token type. ! (cp_lexer_new_from_token_array, cp_lexer_destroy) ! (cp_lexer_peek_token_emit_debug_info, cp_lexer_skip_purged_tokens) ! (cp_lexer_handle_pragma, cp_token_cache_new, cp_parser_string_literal): ! New functions. ! (cp_lexer_new_from_tokens): Now a simple wrapper around ! cp_lexer_new_from_token_array. ! (cp_lexer_set_source_position_from_token): Also update ! in_system_header. ! (cp_lexer_next_token, cp_lexer_prev_token, cp_lexer_advance_token): ! Don't wrap round. ! (cp_lexer_token_difference): Dont handle wrapping round. ! (cp_lexer_new_main): Enable pragma deferral and raw strings, ! read the entire translation unit through c_lex_with_flags into ! this lexer's buffer, then turn raw strings back off again. ! (cp_lexer_grow_buffer): Adjust for buffer no longer being circular. ! (cp_lexer_get_preprocessor_token): No need to handle not being ! the main lexer. Set token->in_system_header too. ! (cp_lexer_peek_token): Skip purged tokens. Feed pragma tokens ! to cp_lexer_handle_pragma. No need to call cp_lexer_read_token. ! (cp_lexer_peek_nth_token): Likewise. ! (cp_lexer_purge_token): Mark the token PURGED, don't shift all ! the other tokens down. ! (cp_lexer_purge_tokens_after): Likewise. ! (cp_lexer_save_tokens, cp_lexer_rollback_tokens): Don't worry ! about there being no tokens. ! (cp_lexer_print_token): Revise to give useful information on ! all tokens. ! (struct cp_parser): Add field translate_strings_p. ! (cp_parser_new): Initialize it. ! (cp_parser_translation_unit): Destroy the lexer when done. ! (cp_parser_parameter_declaration): Restructure saving of ! default arguments. ! (cp_parser_save_member_function_body): Likewise. ! (cp_parser_check_for_invalid_template_id) ! (cp_parser_nested_name_specifier_opt, cp_parser_template_id): ! Adjust calls to cp_lexer_advance_token. ! (cp_parser_skip_to_closing_parenthesis, cp_parser_declaration): ! No need to fiddle c_lex_string_translate. ! (cp_parser_primary_expression, cp_parser_linkage_specification) ! (cp_parser_asm_definition, cp_parser_asm_specification_opt) ! (cp_parser_asm_operand_list, cp_parser_asm_clobber_list) ! Use cp_parser_string_literal. ! (cp_parser_attribute_list): Save and restore ! parser->translate_strings_p, not c_lex_string_translate. ! (cp_parser_cache_group): Delete. ! (cp_parser_cache_group_1): Rename cp_parser_cache_group. Do ! not take a cache argument. ! ! 2004-09-20 Giovanni Bajo PR c++/14179 * decl.c (reshape_init): Extract array handling into... (reshape_init_array): New function. Use integers instead of trees for indices. Handle out-of-range designated initializers. + 2004-09-20 Steven Bosscher + + * lex.c (cxx_init): Don't set the ridpointer for RID_NULL + to null_node. + + 2004-09-19 Mark Mitchell + + * decl2.c (determine_visibility): Allow class visibility + directives to override targetm.cxx.export_class_data. + + 2004-09-18 Kazu Hirata + + * call.c, semantics.c: Follow spelling conventions. + * class.c: Fix a comment typo. + + 2004-09-16 Geoffrey Keating + + PR pch/13361 + * cp/lex.c (handle_pragma_interface): Duplicate string from tree. + (handle_pragma_implementation): Likewise. + + 2004-09-17 Jeffrey D. Oldham + Zack Weinberg + + * cp-tree.def: Use tree_code_class enumeration constants + instead of code letters. + * call.c, class.c, cp-gimplify.c, cp-lang.c, cxx-pretty-print.c + * mangle.c, pt.c, semantics.c, tree.c, typeck.c: + Update for new tree-class enumeration constants. + 2004-09-16 Mark Mitchell + PR c++/16002 + * parser.c (cp_parser_simple_declaration): Commit to tentative + parses after seeing a decl-specifier. + (cp_parser_simple_declaration): Eliminate spurious message. + (cp_parser_init_declarator): Adjust error message. + + PR c++/16029 + * lex.c (unqualified_name_lookup_error): Mark the dummy + declaration as used. + PR c++/17501 * parser.c (cp_parser_nested_name_specifier): Do not resolve typename types if the user explicitly said "typename". + 2004-09-16 Andrew MacLeod + + * error.c (dump_decl): Make sure there is lang_specific info before + checking for DTOR and CTOR decls. + + 2004-09-16 Nathan Sidwell + + * class.c (copy_virtuals): Remove. + (build_primary_vtable): Use copy_list directly. + (build_secondary_vtable): Likewise. + (update_vtable_entry_for_fn): Clear BV_CALL_INDEX here. + (create_vtable_ptr): Likewise. + + 2004-09-16 Kazu Hirata + + * search.c: Follow spelling conventions. + + 2004-09-16 Nathan Sidwell + + * cp-tree.h (struct lang_type_class): Make pure_virtuals a + VEC(tree). + (CLASSTYPE_INLINE_FRIENDS, CLASSTYPE_PURE_VIRTUALS): Update + comments. + * call.c (build_new_method_call): Don't confirm a pure virtual is + in CLASSTYPE_PURE_VIRTUALS. Reorder checks. Make it a warning. + * class.c (check_methods): CLASSTYPE_INLINE_FRIENDS is a VEC(tree). + (fixup_inline_methods, finish_struct): Likewise. + * decl.c (finish_method): Likewise. + * search.c (dfs_get_pure_virtuals, get_pure_virtuals): + CLASSTYPE_PURE_VIRTUALS is a VEC(tree). + * typeck2.c (abstract_virtuals_error): Likewise. Truncate the + vector to avoid repeating the list in error messages. + + 2004-09-15 Mark Mitchell + + * cp-objcp-common.h (LANG_HOOKS_COMDAT_GROUP): Define. + * cp-tree.h (cxx_comdat_group): Declare. + * decl.c (cxx_comdat_group): New function. + + 2004-09-15 Nathan Sidwell + + * search.c (get_pure_virtuals): Remove unused variables. + + * cp-tree.h (struct lang_decl_flags): Remove + needs_final_overrider. + (DECL_NEEDS_FINAL_OVERRIDER_P): Remove. + * decl.c (duplicate_decls): Do not copy DECL_NEEDS_FINAL_OVERRIDER_P. + * class.c (finish_struct_bits): Correct comment about + CLASSTYPE_PURE_VIRTUALS. + * search.c (get_pure_virtuals): Remove useless loop. + + 2004-09-14 Mark Mitchell + + PR c++/17324 + * mangle.c (partially_mangled_name): New variable. + (partially_mangled_name_len): Likewise. + (save_partially_mangled_name): New function. + (restore_partially_mangled_name): Likewise. + (write_encoding): Save and restore partially mangled names around + calls to get_mostly_instantiated_function_type. + (write_unqualified_name): Likewise. + + 2004-09-14 Nathan Sidwell + + * pt.c (unify): Replace gcc_unreachable with gcc_assert. + 2004-09-13 Mark Mitchell PR c++/16162 *************** *** 160,174 **** necessary. (cp_parser_template_name): Honor check_dependency_p. ! 2004-09-13 Mark Mitchell PR c++/17327 * pt.c (unify): Add ENUMERAL_TYPE case. Replace sorry with gcc_unreacable. ! 2004-09-06 Release Manager ! * GCC 3.4.2 released. 2004-08-25 Roger Sayle --- 3010,3479 ---- necessary. (cp_parser_template_name): Honor check_dependency_p. ! PR c++/16716 ! * parser.c (cp_parser_parse_and_diagnose_invalid_type_name): ! Robustify. PR c++/17327 * pt.c (unify): Add ENUMERAL_TYPE case. Replace sorry with gcc_unreacable. ! 2004-09-12 Richard Henderson ! PR c++/16254 ! * semantics.c (maybe_cleanup_point_expr): Don't call fold. ! * typeck.c (condition_conversion): Likewise. ! ! 2004-09-11 Richard Henderson ! ! PR c++/17404 ! * pt.c (cur_stmt_expr): Move from tsubst_expr. ! (tsubst_expr) : Move ... ! (tsubst_copy_and_build): ... here. ! ! 2004-09-10 Zack Weinberg ! ! * cp-tree.h (interface_only, interface_unknown): Delete declarations; ! comment explaining them moved to c-common.h. ! * lex.c (interface_only, interface_unknown, extract_interface_info): ! Delete definitions. ! (cxx_finish): Don't reset interface_unknown. ! (handle_pragma_interface): Don't set interface_only and ! interface_unknown; just the like-named fields in finfo. ! (handle_pragma_implementation): Adjust comment. ! * decl2.c (cp_finish_file): Don't reset interface_only and ! interface_unknown. ! * method.c (synthesize_method): Don't reset interface_unknown or ! call extract_interface_info. ! * pt.c (pop_tinst_level): Don't call extract_interface_info. ! * decl.c (start_cleanup_fn): Don't save or restore interface_only ! and interface_unknown. ! (make_rtl_for_nonlocal_decl): Call get_fileinfo on input_filename ! and use the result instead of the interface_only/interface_unknown ! globals. ! (start_preparsed_function): Likewise. ! * lex.c (cxx_make_type): Likewise. ! * semantics.c (begin_class_definition): Likewise. ! (expand_body): Don't call extract_interface_info. ! ! 2004-09-10 Ziemowit Laski ! ! * decl.c (objc_mark_locals_volatile): Make description of ! routine more descriptive; only mark VAR_DECLs at each ! binding level. ! ! 2004-09-10 Richard Henderson ! ! PR c++/17386 ! * call.c (build_vfield_ref): Move... ! * class.c (build_vfield_ref): ... here. Convert datum to the ! primary base containing the vptr. ! (make_new_vtable): Simplify build_primary_vtable arguments. ! (finish_struct_1): Do not duplicate TYPE_VFIELD. ! * typeck.c (build_class_member_access_expr): Don't warn for ! null object access to base fields. ! ! 2004-09-10 Ziemowit Laski ! ! * decl.c (objc_get_current_scope, objc_mark_locals_volatile): ! New functions, to be called from ObjC++. ! ! 2004-09-10 Kazu Hirata ! ! * class.c, cp-tree.h, decl.c, decl2.c, mangle.c, ! name-lookup.h, parser.c, search.c, semantics.c, typeck2.c: Fix ! comment typos. ! ! 2004-09-09 Ziemowit Laski ! ! * typeck.c (build_c_cast): Preserve the cast if casting ! to and from an Objective-C type. ! ! 2004-09-09 Ziemowit Laski ! ! * Make-lang.in (cp/typeck.o): Depend on c-common.h. ! * typeck.c: Include c-common.h. ! (comptypes): For RECORD_TYPEs, call objc_comptypes() and ! return the result if nonnegative. ! ! 2004-09-09 Zack Weinberg ! ! * decl2.c (import_export_class) ! * lex.c (handle_pragma_interface): ! Test MULTIPLE_SYMBOL_SPACES with if, not #ifdef. ! ! 2004-09-08 Ziemowit Laski ! ! * Make-lang.in (cp/semantics.o): Depend on c-common.h. ! * semantics.c: Include c-common.h. ! (finish_compound_stmt): Call objc_clear_super_receiver(). ! ! 2004-09-08 Ziemowit Laski ! ! * cp-tree.h (do_poplevel): New prototype. ! * semantics.c (do_poplevel): Make externally visible. ! ! 2004-09-08 Nathan Sidwell ! ! * cp-tree.h (tree_pair_s): Define a GC'd vector. ! * name-lookup.h (cxx_saved_binding, cp_class_binding): Likewise. ! * semantics.c (deferred_access): Likewise. ! ! 2004-09-06 Daniel Jacobowitz ! ! * semantics.c (expand_body): Assert that we are not nested. ! ! 2004-09-06 Zack Weinberg ! ! * decl.c (build_enumerator): Use add_double and int_fits_type_p ! instead of cp_build_binary_op, to avoid creating short-lived trees. ! * parser.c (cp_parse_type_specifier ): Use two-token ! lookahead instead of backtracking. Move some code to avoid a ! conditional branch. ! (cp_parser_enum_specifier): Avoid duplication of effort with caller. ! Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate. ! (cp_parser_enumerator_list, cp_parser_enumerator_definition): ! Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate. ! ! 2004-09-04 Kriang Lerdsuwanakij ! ! * decl.c (grok_declarator): Remove a redundant semicolon. ! ! * parser.c (cp_parser_decl_specifier_seq, cp_parser_type_specifier): ! Correct comments describing function parameters. ! ! 2004-09-03 Matt Austern ! Compile speed improvement. ! * parser.c (cp_lexer_print_token): Only define if ENABLE_CHECKING set. ! Otherwise define a stub macro that expands to nothing. ! (cp_lexer_debugging_p): Only define if ENABLE_CHECKING set. Otherwise ! define a stub macro that expands to 0. ! (cp_lexer_start_debugging): Only define if ENABLE_CHECKING set. ! (cp_lexer_stop_debugging): Likewise. ! (cp_lexer_debug_stream): Only define if ENABLE_CHECKING set. Otherwise ! define a stub macro that expands to NULL. ! (cp_lexer_new_main): Only set debugging_p if ENABLE_CHECKING set. ! (cp_lexer_new_from_tokens): Likewise. ! ! 2004-09-03 Jan Hubicka ! ! * decl.c (finish_function): Clean out pointers we no longer need. ! ! 2004-09-03 Jan Beulich ! ! * g++spec.c (MATH_LIBRARY_PROFILE): Default to MATH_LIBRARY rather ! than "-lm". ! ! 2004-09-02 Paul Brook ! ! * decl2.c (determine_visibility): Only check data visibility ! for VAR_DECLS. ! ! 2004-08-31 Mark Mitchell ! ! * cp-tree.h (DECL_CONSTRUCTION_VTABLE_P): New macro. ! * class.c (build_ctor_vtbl_group): Set DECL_CONSTRUCTION_VTABLE_P. ! * decl2.c (determine_visibility): Honor ! TARGET_CXX_EXPORT_CLASS_DATA. ! ! * class.c (key_method): Rename to ... ! (determine_key_method): ... this. ! (finish_struct_1): Adjust accordingly. ! * cp-tree.h (key_method): Declare. ! * decl2.c (maybe_emit_vtables): Determine the key method here if ! it has not already been done. ! ! 2004-08-31 Ziemowit Laski ! ! * Make-lang.in (CXX_AND_OBJCXX_OBJS): Add cp/cp-objcp-common.o. ! (cp/cp-lang.o): Depend on debug.h, gtype-cp.h and cp/cp-objcp-common.h. ! (cp/cp-decl.c): Do not depend on gtype-cp.h. ! (cp/cp-objcp-common.o): New target. ! * cp-lang.c: Include debug.h, cp-objcp-common.h and gtype-cp.h. ! (cxx_get_alias_set, cxx_warn_unused_global_decl, cp_expr_size, ! cp_tree_size, cp_var_mod_type_p, cxx_initialize_diagnostics): Move ! prototypes and definitions to cp-objcp-common.h and cp-objcp-common.c, ! respectively. ! (LANG_HOOKS_TREE_SIZE, LANG_HOOKS_FINISH, ! LANG_HOOKS_CLEAR_BINDING_STACK, LANG_HOOKS_INIT_OPTIONS, ! LANG_HOOKS_INITIALIZE_DIAGNOSTICS, LANG_HOOKS_HANDLE_OPTION, ! LANG_HOOKS_HANDLE_FILENAME, LANG_HOOKS_MISSING_ARGUMENT, ! LANG_HOOKS_POST_OPTIONS, LANG_HOOKS_GET_ALIAS_SET, ! LANG_HOOKS_EXPAND_CONSTANT, LANG_HOOKS_EXPAND_EXPR, ! LANG_HOOKS_EXPAND_DECL, LANG_HOOKS_PARSE_FILE, ! LANG_HOOKS_DUP_LANG_SPECIFIC_DECL, LANG_HOOKS_TRUTHVALUE_CONVERSION, ! LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, LANG_HOOKS_MARK_ADDRESSABLE, ! LANG_HOOKS_PRINT_STATISTICS, LANG_HOOKS_PRINT_XNODE, ! LANG_HOOKS_PRINT_DECL, LANG_HOOKS_PRINT_TYPE, ! LANG_HOOKS_PRINT_IDENTIFIER, LANG_HOOKS_PRINT_ERROR_FUNCTION, ! LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, LANG_HOOKS_WRITE_GLOBALS, ! LANG_HOOKS_FUNCTION_INIT, LANG_HOOKS_FUNCTION_FINAL, ! LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P, ! LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, ! LANG_HOOKS_ATTRIBUTE_TABLE, LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, ! LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN, ! LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS, ! LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, ! LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, ! LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, ! LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN, ! LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN, LANG_HOOKS_EXPR_SIZE, ! LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR, ! LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION, LANG_HOOKS_MAKE_TYPE, ! LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIZE, ! LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE, ! LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE, LANG_HOOKS_INCOMPLETE_TYPE_ERROR, ! LANG_HOOKS_TYPE_PROMOTES_TO, LANG_HOOKS_REGISTER_BUILTIN_TYPE, ! LANG_HOOKS_GIMPLIFY_EXPR, LANG_HOOKS_FOLD_OBJ_TYPE_REF): Move ! hooks to cp-objcp-common.h. ! (finish_file): New function. ! * cp-objcp-common.c: New file. ! * cp-objcp-common.h: New file. ! * cp-tree.h (cp_finish_file): New prototype. ! * decl.c: Do not include gtype-cp.h. ! * decl2.c (finish_file): Rename to cp_finish_file. ! ! 2004-08-31 Richard Henderson ! ! PR c++/17221 ! * pt.c (tsubst_expr): Move OFFSETOF_EXPR handling ... ! (tsubst_copy_and_build): ... here. ! ! 2004-08-30 Mark Mitchell ! ! * cp-tree.h (initialize_artificial_var): Declare. ! * decl.c (initialize_artifical_var): New function. ! * class.c (initialize_array): Remove. ! (initialize_vtable): Use initialize_artificial_var. ! (build_vtt): Likewise. ! (build_ctor_vtbl_group): Likewise. ! ! 2004-08-30 Richard Henderson ! ! * class.c (build_base_path): Use build_address directly. ! * typeck.c (build_unary_op): Don't lower &a.b to pointer ! arithmetic directly. ! * typeck2.c (store_init_value): Don't assume !TREE_CONSTANT ! means !initializer_constant_valid_p. ! ! 2004-08-30 Richard Henderson ! ! * class.c (fixed_type_or_null): Use get_base_address before ! assuming an ADDR_EXPR is non-null. ! ! 2004-08-30 Nathan Sidwell ! ! * name-lookup.c (pop_binding, pushdecl, ! set_identifier_type_value_with_scope, push_overloaded_decl, ! arg_assoc_type): Replace abort with gcc_assert or gcc_unreachable. ! * parser.c (cp_parser_diagnose_invalid_type_name, ! cp_parser_postfix_expression, cp_parser_unary_expression, ! cp_parser_check_declarator_template_para): Likewise. ! * pt.c (push_inline_template_parms_recursive, ! check_explicit_specialization, convert_nontype_argument, ! coerce_template_template_parms, uses_template_parms, ! instantiate_class_template, tsubst_decl, tsubst, tsubst_copy, ! tsubst_expr, instantiate_template, ! maybe_adjust_types_for_deduction, type_unification_real, ! resolve_overloaded_unification, template_decl_level, ! type_dependent_expression_p): Likewise. ! * search.c (lookup_base_r): Likewise. ! * semantics.c (finish_stmt_expr, simplify_aggr_init_expr): Likewise. ! * tree.c (lvalue_p_1, count_functions, cxx_printable_name, ! verify_stmt_tree_r, get_type_decl, stabilize_call): Likewise. ! * typeck.c (common_type, get_member_function_from_ptrfunc, ! build_binary_op, build_unary_op, expand_ptrmemfunc_cst): Likewise. ! * typeck2.c (cxx_incomplete_type_diagnostic, ! split_nonconstant_init_1, store_init_value, ! process_init_constructor): Likewise. ! ! 2004-08-30 Nathan Sidwell ! ! * call.c (check_dtor_name): Replace abort with gcc_assert or ! gcc_unreachable. ! (build_call, add_builtin_candidate, build_new_op, ! convert_like_real, build_over_call, in_charge_arg_for_name, ! source_type, joust): Likewise. ! * class.c (build_simple_base_path, get_vcall_index, ! finish_struct_1, instantiate_type, get_enclosing_class, ! add_vcall_offset_vtbl_entries_1, cp_fold_obj_type_ref): Likewise. ! * cp-gimplify.c (cp_genericize): Likewise. ! * cp-lang.c (cp_expr_size, cp_tree_size): Likewise. ! * cvt.c (cp_convert_to_pointer, ocp_convert): Likewise. ! * decl.c (poplevel, make_unbound_class_template, reshape_init, ! check_special_function_return_type, grokdeclarator, ! grok_op_properties, tag_name, xref_tag, start_preparsed_function, ! finish_function): Likewise. ! * decl2.c (grokfield, maybe_emit_vtables):Likewise. ! * error.c (dump_global_iord, dump_decl, dump_template_decl, ! language_to_string): Likewise. ! * except.c (choose_personality_routine): Likewise. ! * friend.c (do_friend): Likewise. ! * g++spec.c (lang_specific_driver): Likewise. ! * init.c (build_zero_init, expand_default_init, build_new_1, ! build_vec_delete_1, build_vec_init, build_dtor_call): Likewise. ! * lex.c (retrofit_lang_decl, cp_type_qual_from_rid): Likewise. ! * mangle.c (add_substitution, write_unscoped_name, ! write_template_prefix, write_identifier, ! write_special_name_destructor, write_type, write_builtin_type, ! write_expression, write_template_param, ! write_java_integer_type_codes): Likewise. ! * method.c (implicitly_declare_fn): Likewise. ! ! 2004-08-30 Nathan Sidwell ! ! * cp-tree.h (BINFO_PRIMARY_P): Use a binfo flag. ! (BINFO_INDIRECT_PRIMARY_P): Remove. ! * class.c (determine_primary_base): Rename to ... ! (determine_primary_bases): ... here. Set all primary bases. ! (set_primary_base): Remove. ! (mark_primary_bases): Remove. ! (build_simple_base_path, walk_subobject_offsets, ! propagate_binfo_offsets, end_of_class): Adjust. ! (layout_class_type): Rename determine_primary_base call. ! (dump_class_hierarchy_r, dump_vtable): Adjust. Don't pass a binfo ! to type_as_string. ! (dfs_build_secondary_vptr_vtt_inits, dfs_accumulate_vtbl_inits, ! build_rtti_vtbl_entries): Adjust. ! * init.c (build_vtbl_address): Adjust. ! ! * cp-tree.h (SET_BINFO_NEW_VTABLE_MARKED): Use gcc_assert. ! ! 2004-08-28 Ziemowit Laski ! ! * Make-lang.in (CXX_OBJS): Split up into CXX_OBJS and ! CXX_AND_OBJCXX_OBJS. ! (CXX_C_OBJS): Include in CXX_AND_OBJCXX_OBJS instead of listing ! separately on the link line. ! ! 2004-08-28 Jason Merrill ! ! * decl.c (expand_static_init): Avoid bogus warnings. ! ! 2004-08-27 Jason Merrill ! ! PR c++/16851 ! * tree.c (stabilize_init): See through a COMPOUND_EXPR. ! ! PR c++/13684 ! * decl.c (expand_static_init): Use thread-safety API. ! (register_dtor_fn): Return the call, don't expand it. ! * tree.c (add_stmt_to_compound): New fn. ! (stabilize_call): Use it. ! ! 2004-08-27 Richard Henderson ! ! * cp-tree.def (OFFSETOF_EXPR): New. ! * parser.c (cp_parser_builtin_offsetof): Either built an ! OFFSETOF_EXPR, or call fold_offsetof immediately. ! * pt.c (tsubst_expr): Handle OFFSETOF_EXPR. ! ! 2004-08-27 Nathan Sidwell ! ! * call.c (validate_conversion_obstack): Replace ! my_friendly_assert with gcc_assert or gcc_unreachable. ! (direct_reference_binding, merge_conversion_sequences, ! build_user_type_conversion_1, perform_overload_resolution, ! build_op_delete_call, enforce_access, call_builtin_trap, ! build_over_call, build_special_member_call, build_new_method_call, ! initialize_reference): Likewise. ! * class.c (build_base_path, build_primary_vtable, alter_access, ! check_bases, update_vtable_entry_for_fn, layout_empty_base, ! clone_function_decl, adjust_clone_args, ! type_requires_array_cookie, include_empty_classes, ! finish_struct_1, resolve_address_of_overloaded_function, ! instantiate_type, get_vtbl_decl_for_binfo, build_vtt_inits, ! dfs_build_secondary_vptr_vtt_inits, build_ctor_vtbl_group, ! accumulate_vtbl_inits, build_vtbl_initializer, ! build_vbase_offset_vtbl_entries, build_rtti_vtbl_entries): Likewise. ! * cvt.c (build_up_reference, convert_to_reference): Likewise. ! * decl.c (poplevel, duplicate_decls, make_typename_type, ! cxx_init_decl_processing, reshape_init, check_initializer, ! make_rtl_for_nonlocal_decl, initialize_local_var, cp_finish_decl, ! expand_static_init, grokfndecl, grokvardecl, build_ptrmem_type, ! grokdeclarator, copy_fn_p, grok_op_properties, xref_tag, ! xref_basetypes, start_preparsed_function, save_function_data, ! finish_function, finish_method, maybe_register_incomplete_var, ! complete_vars): Likewise. ! * decl2.c (grok_array_decl, check_member_template, ! check_classfn, finish_static_data_member_decl, coerce_new_type, ! coerce_delete_type, import_export_class, decl_needed_p, ! determine_visibility, import_export_decl, build_cleanup, ! start_static_initialization_or_destructi, do_static_destruction, ! prune_vars_needing_no_initialization, ! build_offset_ref_call_from_tree): Likewise. ! * error.c (dump_decl, dump_expr): Likewise. ! * init.c (finish_init_stmts, build_zero_init, ! expand_virtual_init, expand_default_init, expand_aggr_init_1, ! build_offset_ref, build_new_1, build_delete, build_vbase_delete): ! Likewise. ! * mangle.c (write_method_parms, write_template_args, ! write_expression, write_template_arg): Likewise. ! * method.c (make_thunk, finish_thunk, use_thunk): Likewise. ! * name-lookup.c (pop_binding, begin_scope, leave_scope, ! resume_scope, push_using_decl, validate_nonmember_using_decl, ! is_ancestor, poplevel_class, set_inherited_value_binding_p, ! push_class_level_binding, do_class_using_decl, push_namespace, ! pop_namespace, add_using_namespace, ambiguous_decl, ! lookup_namespace_name, lookup_type_current_level, ! maybe_process_template_type_declaration): Likewise. ! * parser.c (cp_lexer_peek_nth_token, ! cp_parser_parse_and_diagnose_invalid_typ, ! cp_parser_translation_unit, cp_parser_template_id, ! cp_parser_lookup_name, cp_parser_late_parsing_for_member): Likewise. ! * pt.c (push_access_scope, finish_member_template_decl, ! push_inline_template_parms_recursive, add_outermost_template_args, ! get_innermost_template_args, begin_explicit_instantiation, ! end_explicit_instantiation, retrieve_specialization, ! is_specialization_of, is_specialization_of_friend, ! register_specialization, check_explicit_specialization, ! comp_template_parms, process_template_parm, ! process_partial_specialization, convert_nontype_argument, ! coerce_template_template_parms, coerce_template_parms, ! mangle_class_name_for_template, lookup_template_function, ! lookup_template_class, instantiate_class_template, tsubst_decl, ! tsubst_function_type, tsubst, tsubst_qualified_id, tsubst_copy, ! instantiate_template, fn_type_unification, type_unification_real, ! get_template_base, regenerate_decl_from_template, ! template_for_substitution, instantiate_decl, ! get_mostly_instantiated_function_type, dependent_scope_ref_p, ! value_dependent_expression_p, resolve_typename_type): Likewise. ! * repo.c (repo_emit_p): Likewise. ! * rtti.c (build_headof, get_tinfo_decl, get_pseudo_ti_init, ! create_tinfo_types, emit_tinfo_decl): Likewise. ! * search.c (lookup_base_r, lookup_base, lookup_field_1, ! dfs_access_in_type, build_baselink, lookup_member, ! adjust_result_of_qualified_name_lookup, copied_binfo): Likewise. ! * semantics.c (perform_or_defer_access_check, ! finish_non_static_data_member, finish_stmt_expr_expr, ! finish_stmt_expr, finish_call_expr, finish_pseudo_destructor_expr, ! finish_template_template_parm, finish_member_declaration, ! emit_associated_thunks): Likewise. ! * tree.c (build_target_expr_with_type, force_target_expr, ! copy_binfo, get_first_fn, cp_tree_equal): Likewise. ! * typeck.c (type_after_usual_arithmetic_conversions, comptypes, ! cxx_sizeof_or_alignof_type, perform_integral_promotions, ! build_class_member_access_expr, finish_class_member_access_expr, ! build_ptrmemfunc_access_expr, build_unary_op, ! unary_complex_lvalue, cxx_mark_addressable, build_modify_expr, ! build_ptrmemfunc, expand_ptrmemfunc_cst, check_return_expr ! * typeck2.c (complete_type_check_abstract, ! abstract_virtuals_error, process_init_constructor, ! add_exception_specifier): Likewise. ! ! 2004-08-27 Nathan Sidwell ! ! * class.c (build_vtbl_initializer): Use ssize_int. ! * decl.c (complete_array_type): Likewise. ! * method.c (finish_thunk): Likewise. ! * search.c (get_dynamic_base_type): Likewise. ! ! 2004-08-26 Richard Henderson ! ! * cp-tree.h (DECL_FIELD_IS_BASE): New. ! * class.c (build_base_field): Set it. ! (build_simple_base_path): Use it. ! (fixed_type_or_null): Don't consider base fields definitive. 2004-08-25 Roger Sayle *************** *** 177,190 **** * decl.c (finish_enum): Make the precision of the enumerated type the same width as the underlying integer type. ! 2004-08-24 Jason Merrill ! PR c++/16851 ! * tree.c (stabilize_init): See through a COMPOUND_EXPR. ! PR c++/15461 ! * semantics.c (nullify_returns_r): Replace a DECL_STMT ! for the NRV with an INIT_EXPR. 2004-08-24 Nathan Sidwell --- 3482,3558 ---- * decl.c (finish_enum): Make the precision of the enumerated type the same width as the underlying integer type. ! 2004-08-25 Mark Mitchell ! PR c++/17155 ! * lex.c (build_lang_decl): Set DECL_NO_STATIC_CHAIN for all C++ ! functions. ! * mangle.c (get_identifier_nocopy): Add cast. ! ! * cp-tree.h (mangle_type): Remove. ! * mangle.c (globals): GTY it. ! (mangle_obstack): New variable. ! (name_obstack): Likewise. ! (name_base): Likewise. ! (write_char): Adjust accordingly. ! (write_chars): Likewise. ! (write_string): Likewise. ! (start_mangling): Initialize G.substitutions only one. Add ! ident_p parameter. ! (finish_mangling): Use VARRAY_CLEAR to reclaim ! storage in G.substitutions. Use obstack_finish. ! (init_mangle): Adjust for changes to variable names above. ! Initialize G.substitutions. ! (mangle_decl_string): Adjust call to start_mangling. ! (get_identifier_nocopy): New function. ! (mangle_decl): Use it. ! (mangle_type_string): Adjust call to start_mangling. ! (mangle_special_for_type): Likewise. ! (mangle_vtt_for_type): Likewise. ! (mangle_ctor_vtbl_for_type): Likewise. ! (mangle_thunk): Likewise. ! (mangle_guard_variable): Likewise. ! (mangle_ref_init_variable): Likewise. ! ! 2004-08-25 Kriang Lerdsuwanakij ! ! PR c++/14428 ! * pt.c (redeclare_class_template): Check the type of non-type and ! template template parameter. ! ! 2004-08-25 Nathan Sidwell ! ! * call.c (convert_class_to_reference): Adjust build_int_cst calls. ! (build_user_type_conversion_1, convert_like_real, ! build_java_interface_fn_ref, build_special_member_call): Likewise. ! * class.c (finish_struct_1, build_vtbl_initializer): Likewise. ! * cp-gimplify.c (cp_gimplify_expr): Likewise. ! * cvt.c (cp_convert_to_pointer): Likewise. ! * decl.c (cxx_init_decl_processing, complete_array_type): Likewise. ! * decl2.c (start_static_initialization_or_destruction, ! generate_ctor_or_dtor_function): Likewise. ! * except.c (build_throw): Likewise. ! * mangle.c (write_integer_cst): Likewise. ! * method.c (finish_thunk): Likewise. ! * rtti.c (build_headof, get_tinfo_decl_dynamic, ! build_dynamic_cast_1, ptr_initializer, ptm_initializer, ! get_pseudo_ti_init): Likewise. ! * search.c (get_dynamic_cast_base_type): Likewise. ! ! 2004-08-25 Zack Weinberg ! ! * class.c, search.c: Remove references to DWARF_DEBUG. ! ! 2004-08-25 Adam Nemet ! ! * repo.c (extract_string): Reset backquote after one character. ! (get_base_filename): Fix indentation. ! ! 2004-08-24 Nathan Sidwell ! ! * decl.c (cxx_init_decl_processing): Adjust ! build_common_tree_nodes call. 2004-08-24 Nathan Sidwell *************** *** 198,214 **** * search.c (friend_accessible_p): Increment processing_template_decl when deal with TEMPLATE_DECL of SCOPE. ! 2004-08-23 Janis Johnson ! Backports from mainline: ! 2004-02-27 Ziemowit Laski ! 2004-03-24 Ziemowit Laski ! * Make-lang.in (cp/mangle.o): Depend on $(TARGET_H). ! * mangle.c (write_type): Add call to 'mangle_fundamental_type' ! target hook. ! * tree.c (pod_type_p): Treat VECTOR_TYPEs as PODs. 2004-08-19 Mark Mitchell --- 3566,3637 ---- * search.c (friend_accessible_p): Increment processing_template_decl when deal with TEMPLATE_DECL of SCOPE. ! 2004-08-24 Nathan Sidwell ! PR c++/17149 ! * semantics.c (check_accessibility_of_qualified_id): Defer check ! if qualifying_type is a template parameter. ! 2004-08-23 Mark Mitchell ! PR c++/17163 ! * pt.c (instantiate_decl): Do not try to apply ! DECL_DECLARED_INLINED_P to a VAR_DECL. ! ! * search.c (build_baselink): Fix typo in comment. ! ! 2004-08-22 Andrew Pinski ! ! Revert: ! 2004-08-22 Andrew Pinski ! PR c++/14029 ! * typeck.c (build_unary_op): Use &a.b if the folded lowered ! expression is not constant. ! ! 2004-08-23 Nathan Sidwell ! ! * name-lookup.c (pushdecl): Rename build_type_copy call. ! * tree.c (cp_build_qualified_type_real, ! build_exception_variant, handle_java_interface_attribute): Likewise. ! ! 2004-08-22 Andrew Pinski ! ! PR c++/14029 ! * typeck.c (build_unary_op): Use &a.b if the folded lowered ! expression is not constant. ! ! 2004-08-20 Mark Mitchell ! ! PR c++/17121 ! * decl.c (expand_static_init): Use DECL_FUNCTION_SCOPE_P. ! ! 2004-08-21 Joseph S. Myers ! ! PR c++/17120 ! * pt.c (tsubst_copy_and_build): Avoid clearing TREE_NO_WARNING for ! MODOP_EXPR. ! ! 2004-08-20 Kriang Lerdsuwanakij ! ! * pt.c (register_specialization): Check DECL_TEMPLATE_SPECIALIZATION ! before calling comp_template_args. ! ! 2004-08-20 Nathan Sidwell ! ! * class.c (build_vtbl_initializer): Use build_int_cst for ! negative size types. ! * decl.c (complete_array_type): Likewise. ! * method.c (finish_thunk): Likewise. ! ! 2004-08-20 Andreas Tobler ! ! * tree.c: Remove unused mark_local_for_remap_r. ! ! 2004-08-19 Eric Christopher ! ! * cp-tree.h (cxx_unsave_expr_now): Delete prototype. ! * tree.c (cxx_unsave_expr_now): Delete. ! (cp_unsave_r): Ditto. 2004-08-19 Mark Mitchell *************** *** 216,223 **** --- 3639,3667 ---- * pt.c (push_template_decl_real): Disallow template allocation functions with fewer than two parameters. + 2004-08-19 Nathan Sidwell + + * cp-tree.h (build_shared_int_cst): Remove. + * tree.c (shared_int_cache): Remove. + (build_shared_int_cst): Remove. + * class.c (finish_struct_1): Use build_int_cst. + + 2004-08-19 Nathan Sidwell + + * decl.c (finish_enum): Do not copy value node early, copy + later. + * lex.c (cxx_init): Force null_node to be unique. + + 2004-08-19 Joseph S. Myers + + PR c++/17041 + * pt.c (tsubst_copy, tsubst_copy_and_build): Copy TREE_NO_WARNING + from input for MODOP_EXPR. + 2004-08-18 Mark Mitchell + * pt.c (dependent_template_p): Fix typo in commment. + PR c++/17068 * pt.c (dependent_template_p): Treat IDENTIFIER_NODEs as dependent. *************** *** 225,232 **** 2004-08-17 Mark Mitchell PR c++/16246 ! * pt.c (unify): Make sure that non-type arguments have the same ! type as the corresponding parameter. 2004-08-12 Mark Mitchell --- 3669,3779 ---- 2004-08-17 Mark Mitchell PR c++/16246 ! * pt.c (unify): Tidy ARRAY_TYPE handling. Make sure that non-type ! arguments have the same type as the corresponding parameter. ! ! PR c++/16215 ! * parser.c (cp_parser_name_lookup_error): If parser->object_scope ! is set use it for diagnostic purposes. ! (cp_parser_pseudo_destructor_name): Remove special-case error ! message. ! ! PR c++/15871 ! * semantics.c (expand_or_defer_fn): Honor -fkeep-inline-functions. ! ! PR c++/16965 ! * cp-tree.h (qualified_name_lookup_error): Add parameter. ! * name-lookup.c (do_class_using_decl): Restrict set of entities ! passed to cp_emit_debug_info_for_using more carefully. ! (lookup_qualified_name): Allow lookup_member to return sets of ! ambiguous entries. ! * parser.c (cp_parser_lookup_name): Add ambiguous_p parameter. ! (cp_parser_primary_expression): Handle ambiguous lookups. ! (cp_parser_template_name): Adjust use of cp_parser_lookup_name. ! (cp_parser_template_argument): Likewise. ! (cp_parser_elaborate_type_specifier): Likewise. ! (cp_parser_namespace_name): Likewise. ! (cp_parser_class_name): Likewise. ! (cp_parser_lookup_name_simple): Likewise. ! * pt.c (tsubst_qualified_id): Handle ambiguous results. ! (tsubst_expr): Likewise. ! * semantics.c (qualified_name_lookup_error): Add decl paramter. ! For ambiguous lookups, print candidates. ! ! 2004-08-16 Kriang Lerdsuwanakij ! ! PR c++/6749 ! * pt.c (instantiate_pending_templates): Add int parameter. Don't ! return anything. ! * cp-tree.h (instantiate_pending_templates): Adjust prototype. ! * decl2.c (finish_file): Adjust call to ! instantiate_pending_templates. ! ! 2004-08-15 Roger Sayle ! ! * call.c (build_vfield_ref, build_call, build_conditional_expr, ! convert_arg_to_ellipsis, build_x_va_arg, build_over_call, ! build_java_interface_fn_ref, build_special_member_call, ! build_new_method_call, initialize_reference): Replace calls to ! build with calls to buildN. ! * class.c (build_base_path, convert_to_base_statically, ! build_vfn_ref, instantiate_type, dfs_accumulate_vtbl_inits, ! build_vtbl_initializer): Likewise. ! * cp-gimplify.c (genericize_try_block, genericize_catch_block, ! gimplify_if_stmt, cp_genericize_r): Likewise. ! * cvt.c (convert_to_void): Likewise. ! * decl.c (check_initializer, finish_constructor_body, ! finish_destructor_body): Likewise. ! * error.c (dump_expr): Likewise. ! * except.c (build_exc_ptr, expand_start_catch_block, build_throw): ! Likewise. ! * init.c (perform_member_init, expand_virtual_init, ! expand_cleanup_for_base, build_init, expand_default_init, ! build_offset_ref, decl_constant_value, build_new, build_new_1, ! build_vec_delete_1, build_vec_init, build_delete, ! push_base_cleanups, build_vec_delete): Likewise. ! * mangle.c (write_integer_cst): Likewise. ! * method.c (thunk_adjust, do_build_copy_constructor, ! do_build_assign_ref): Likewise. ! * pt.c (lookup_template_function, tsubst, tsubst_copy_and_build, ! unify, build_non_dependent_expr): Likewise. ! * rtti.c (build_headof, build_typeid, ifnonnull, ! build_dyanmic_cast_1, tinfo_base_init): Likewise. ! * semantics.c (begin_compound_stmt, finish_call_expr, ! finish_pseudo_destructor_expr, finish_id_expression, ! simplify_aggr_init_expr, finalize_nrv_r): Likewise. ! * tree.c (build_target_expr, build_cplus_new, array_type_nelts_top, ! array_type_nelts_total, stabilize_call): Likewise. ! * typeck.c (decay_conversion, build_class_member_access_expr, ! lookup_destructor, build_ptrmemfunc_access_expr, build_array_ref, ! get_member_function_from_ptrfunc, build_binary_op, pointer_diff, ! build_x_unary_op, build_unary_op, unary_complex_lvalue, ! build_compound_expr, build_modify_expr, expand_ptrmemfunc_cst, ! check_return_expr): Likewise. ! * typeck2.c (split_nonconstant_1, split_nonconstant_init_1, ! split_nonconstant_init, store_init_value, build_m_component_ref): ! Likewise. ! ! 2004-08-15 Nathan Sidwell ! ! * call.c (convert_class_to_reference, ! build_user_type_conversion_1, convert_like_real, ! build_java_interface_fn_ref, build_special_member_call): Use ! build_int_cst. ! * class.c (build_vtbl_initializer): Likewise. ! * cp-gimplify.c (cp_gimplify_expr): Likewise. ! * cvt.c (cp_convert_to_pointer): Likewise. ! * decl.c (cxx_init_decl_processing, complete_array_type): Likewise. ! * decl2.c (start_static_initialization_or_destruction, ! generate_ctor_or_dtor_function): Likewise. ! * except.c (build_throw): Likewise. ! * lex.c (cxx_init): Likewise. ! * mangle.c (write_integer_cst): Likewise. ! * rtti.c (build_headof, get_tinfo_decl_dynamic, ! build_dynamic_cast_1, ptr_initializer, ptm_initializer, ! get_pseudo_ti_init): Likewise. ! * search.c (get_dynamic_cast_base_type): Likewise. ! * tree.c (build_shared_int_cst): Likewise. 2004-08-12 Mark Mitchell *************** *** 256,275 **** * except.c (build_throw): Allocate cleanup_type and the function for __cxa_throw separately. - 2004-08-11 Mark Mitchell - - PR c++/16717 - * semantics.c (expand_body): Do not update static_ctors and - static_dtors here. - (expand_or_defer_fn): Do it here, instead. - PR c++/16853 * call.c (standard_conversion): Do not accept conversions between pointers to members if the class types are unrelated. PR c++/16870 * pt.c (tsubst): Just return the unknown_type_node. PR c++/16964 * parser.c (cp_parser_class_specifier): Robustify. --- 3803,3821 ---- * except.c (build_throw): Allocate cleanup_type and the function for __cxa_throw separately. PR c++/16853 * call.c (standard_conversion): Do not accept conversions between pointers to members if the class types are unrelated. + PR c++/16618 + * parser.c (cp_parser_builtin_offsetof): Cast to "const volatile + char &" instead of just "char &". + PR c++/16870 * pt.c (tsubst): Just return the unknown_type_node. + 2004-08-11 Mark Mitchell + PR c++/16964 * parser.c (cp_parser_class_specifier): Robustify. *************** *** 280,286 **** PR c++/16929 * pt.c (tsubst_default_argument): Clear out current_class_ptr and current_class_ref while tsubsting. ! 2004-08-01 Mark Mitchell PR c++/16224 --- 3826,3922 ---- PR c++/16929 * pt.c (tsubst_default_argument): Clear out current_class_ptr and current_class_ref while tsubsting. ! ! 2004-08-10 Mark Mitchell ! ! PR c++/16971 ! * parser.c (cp_parser_init_declarator): Robustify. ! ! 2004-08-06 Richard Sandiford ! ! * typeck2.c (process_init_constructor): Guard the missing field warning ! with warn_missing_field_initializers rather than extra_warnings. ! ! 2004-08-06 Paolo Bonzini ! ! * class.c (instantiate_type) : Do not handle. ! ! 2004-08-05 Mark Mitchell ! ! * decl.c (start_preparsed_function): Move determine_visibility ! call. ! * decl2.c (determine_visibility): Incorporate dllexport testing. ! ! 2004-08-05 Geoffrey Keating ! ! * g++spec.c (lang_specific_driver): An -Xlinker or -Wl, option ! means that libstdc++ is needed. ! ! 2004-08-05 Nathan Sidwell ! ! * cvt.c (cp_convert_to_pointer): Adjust force_fit_type call. ! ! 2004-08-04 Geoffrey Keating ! ! * decl.c (make_rtl_for_nonlocal_decl): Set DECL_ASSEMBLER_NAME rather ! than passing it as a parameter to rest_of_decl_compilation. ! * decl2.c (grokfield): Use set_user_assembler_name. ! ! 2004-08-04 Nathan Sidwell ! ! * decl.c (complete_array_type): Don't gratuitously copy ! maxindex. Its type is always set. ! ! 2004-08-04 Paul Brook ! ! * Make-lang.in (cp/semantics.o, cp/optimize.o): Depend on TARGET_H. ! * cp-tree.h (struct language_function): Rename x_dtor_label to ! x_cdtor_label. ! (dtor_label): Rename ... ! (cdtor_label): ... to this. ! * decl.c (begin_constructor_body): Remove. ! (check_special_function_return_type): Maybe change the return type. ! (grokdeclarator): Pass the class type. ! (start_preparsed_function): Constructors may need a return label. ! (finish_constructor_body, finish_destructor_body): Set the return ! value. ! (begin_function_body): Don't call begin_constructor_body. ! (finish_function): Don't warn for constructors or destructors. ! (implicitly_declare_fn): Maybe change the return type. ! * optimize.c: Include target.h. ! (maybe_clone_body): Remap the function result. ! * semantics.c: Include target.h. ! (finish_return_stmt): Maybe jump to return label for constructors. ! ! 2004-08-03 Mark Mitchell ! ! * class.c (build_vtable): Do not set DECL_VISIBILITY here. ! (check_field_decls): Or here. ! (check_methods): Or here. ! (initialize_array): Don't mess with DECL_CONTEXT. ! * cp-tree.h (start_decl): Adjust prototype. ! (determine_visibility): New function. ! * decl.c (duplicate_decls): Remove checks for hidden "operator ! new". ! (build_library_fn_1): Give all library functions default ! visibility. ! (start_decl): Add pop_scope_p parameter. Tidy. ! (cp_finish_decl): Do not pop scopes here. Call ! determine_visibility for variable definitions. ! (start_preparsed_function): Call determine_visibility. ! * decl2.c (determine_visibility): New function. ! * method.c (use_thunk): Fix formatting. ! * parser.c (cp_parser_condition): Adjust calls to start_decl. ! (cp_parser_init_declarator): Likewise. ! * pt.c (instantiate_decl): Always call pop_nested_class. ! * rtti.c (get_tinfo_decl): Do not set DECL_VISIBILITY. ! (tinfo_base_init): Likewise. ! ! 2004-08-02 Mark Mitchell ! ! PR c++/16707 ! * name-lookup.c (validate_nonmember_using_decl): Robustify. ! 2004-08-01 Mark Mitchell PR c++/16224 *************** *** 294,301 **** (maybe_process_partial_specialization): Use it. (register_specialization): Likewise. - 2004-08-01 Mark Mitchell - PR c++/16489 * cp-tree.h (DECL_INTEGRAL_CONSTANT_VAR_P): New macro. * call.c (null_ptr_cst_p): Handle variables with constant --- 3930,3935 ---- *************** *** 311,317 **** PR c++/16810 * typeck.c (build_ptrmemfunc): Loosen assertion. ! 2004-07-28 Kriang Lerdsuwanakij PR c++/13092 * init.c (build_offset_ref): Build SCOPE_REF with non-null --- 3945,4349 ---- PR c++/16810 * typeck.c (build_ptrmemfunc): Loosen assertion. ! 2004-08-01 Gabriel Dos Reis ! ! * call.c (z_candidate::template_decl): Rename from template. ! (add_template_candidate_real): Adjust member reference. ! (joust): Likewise. ! ! 2004-07-29 Mark Mitchell ! ! * cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define. ! (lang_decl_flags): Narrow the width of "languages". Add ! repo_available_p. ! (DECL_NEEDED_P): Remove. ! (FOR_EACH_CLONE): New macro. ! (DECL_REPO_AVAILABLE_P): Likewise. ! (DECL_TINFO_P): Likewise. ! (set_linkage_according_to_type): Declare. ! (import_export_vtable): Remove. ! (import_export_tinfo): Likewise. ! (mark_needed): New function. ! (decl_needed_p): Likewise. ! (note_vauge_linkage_fn): Likewise. ! (init_repo): Change prototype. ! (repo_template_used): Remove. ! (repo_template_instantiated): Likewise. ! (repo_emit_p): New function. ! (repo_export_class_p): Likewise. ! (no_linkage_check): Change prototype. ! * class.c (set_linkage_according_to_type): New function. ! (build_vtable): Use it. Do not call import_export_vtable. Set ! DECL_IGNORED_P if appropriate. ! * decl.c (duplicate_decls): Preserve DECL_REPO_AVAILABLE_P. ! (make_rtL_for_nonlocal_decls): Check for template instantiations ! explicitly. ! (grokfndecl): Adjust call to no_linkage_check. ! (set_linkage_for_static_data_member): New function. ! (grokvardecl): Use it. Adjust call to no_linkage_check. ! (grokdeclarator): Use set_linkage_for_static_data_member. ! * decl2.c (note_vague_linkage_fn): New function. ! (note_vague_linkage_var): Likewise. ! (finish_static_data_member_decl): Use it. ! (import_export_vtable): Remove. ! (import_export_class): Use repo_export_class_p. ! (var_finalized_p): Simplify. ! (maybe_emit_vtables): Simplify. ! (mark_needed): New function. ! (decl_needed_p): Likewise. ! (import_export_decl): Add documentation and consistency checks. ! Use repo_emit_p. Handle virtual tables and RTTI information ! here. ! (import_export_tinfo): Remove. ! (write_out_vars): Call import_export_decl. ! (cxx_callgraph_analyze_expr): Ensure that all vtables are emitted ! whenever one is. ! (finish_file): Use decl_needed_p. Do not call import_export_decl ! for undefined static data members. Do not warn about undefined ! inlines when using a repository. ! (mark_used): Use note_vague_linkage_fn. Always defer template ! instantiations. ! * lex.c (cxx_init): Adjust call to init_repo. Always set ! flag_unit_at_a-time. ! * method.c (synthesize_method): Remove unncessary ! import_export_decl call. ! (implicitly_declare_fn): Use set_linkage_according_to_type. ! * optimize.c (maybe_clone_body): Use FOR_EACH_CLONE. ! * pt.c (instantiate_class_template): Don't redundantly add classes ! to keyed_classes. Don't call repo_template_used. ! (tsubst_decl): Set DECL_INTERFACE_KNOWN for instantiations of ! templates with internal linkage. ! (check_instantiated_args): Adjust call to no_linkage_check. ! (instantiate_template): Use FOR_EACH_CLONE. ! (mark_definable): New function. ! (mark_decl_instantiated): Use it. ! (do_decl_instantiation): Adjust tests for explicit instantiation ! after "extern template". ! (instantiate_class_member): Do not use repo_template_instantiated. ! (do_type_instantiation): Simplify. ! (instantiate_decl): Use mark_definable. Check repo_emit_p. ! Simplify. ! * repo.c (repo_get_id): Remove. ! (original_repo): Remove. ! (IDENTIFIER_REPO_USED): Remove. ! (IDENTIFIER_REPO_CHOSEN): Remove. ! Remove all #if 0'd code. ! (repo_template_used): Remove. ! (repo_template_instantiated): Remove. ! (temporary_obstack_initialized_p): New variable. ! (init_repo): Register with lang_post_pch_load. Avoid creating ! identifiers unnecessarily. Don't use original_repo. Close the ! file here. ! (reopen_repo_file_for_write): Not here. ! (finish_repo): Always write out a new repository file. ! (repo_emit_p): New function. ! (repo_export_class_p): Likewise. ! * rtti.c (get_tinfo_decl): Use set_linkage_according_to_type. ! (involves_incomplete_p): New function. ! (tinfo_base_init): Use it. ! (ptr_initializer): Remove non_public_ptr parameter. ! (ptm_initializer): Likewise. ! (get_pseudo_ti_init): Likewise. ! (unemitted_tinfo_decl_p): Remove. ! (emit_tinfo_decl): Use import_export_decl. ! * semantics.c (expand_body): Move updates of static_ctors and ! static_dtors to ... ! (expand_or_defer_fn): ... here. ! * tree.c (no_linkage_check): Add relaxed_p parameter. ! ! 2004-07-28 Eric Christopher ! ! * cp-lang.c (LANG_HOOKS_UNSAFE_FOR_REEVAL): Delete. ! ! 2004-07-28 Nathan Sidwell ! ! * cp-tree.h (struct tree_pair_s): New. ! (typedef tree_pair_p): New. ! (DEF_VEC_O(tree_pair_s)): New. ! (struct lang_type_class): Make vcall_indices a VEC(tree_pair_s). ! (CLASSTYPE_VCALL_INDICES): Update documentation. ! * class.c (get_vcall_index): Adjust. ! (add_vcall_offset): Adjust. ! ! 2004-07-27 Kelley Cook ! ! * pt.c, typeck.c: Remove spurious carriage returns. ! ! 2004-07-27 Kriang Lerdsuwanakij ! ! PR c++/14429 ! * pt.c (coerce_template_template_parms) : Only check ! when the type of ARG is not dependent. ! ! 2004-07-26 Geoffrey Keating ! ! * g++spec.c (LIBSTDCXX_PROFILE): Default to LIBSTDCXX. ! (lang_specific_driver): If the C++ or math library options don't ! start with '-l', don't count them as added libraries. ! ! 2004-07-26 Nathan Sidwell ! ! * decl.c (xref_basetypes): Adjust base access vector creation. ! * rtti.c (get_pseudo_ti_init, get_pseudo_ti_desc): Adjust base ! access accesses. ! * search.c (dynamic_cast_base_recurse, dfs_access_in_type): Likewise. ! ! 2004-07-26 Niall Douglas ! Brian Ryner ! ! PR c++/15000 ! PR c++/9283 ! * class.c (check_field_decls): Apply hidden visibility if ! -fvisibility-inlines-hidden and inlined unless otherwise specified ! (build_vtable): Set vtable visibility to class visibility. ! (check_field_decls): Default static member visibility to class ! visibility. ! (check_methods): Default method visibility to class visibility. ! * cp-tree.h: Added CLASSTYPE_VISIBILITY and ! CLASSTYPE_VISIBILITY_SPECIFIED macro. ! * decl.c (duplicate_decls): New logic for merging definition decls ! with declaration decls. Added ignore & warning when non default ! applied to global operator new or delete. ! * method.c, optimize.c, rtti.c: Added setting of VISIBILITY_SPECIFIED ! wherever VISIBILITY was changed ! * rtti.c (get_tinfo_decl): Set typeinfo visibility to class ! visibility. ! (tinfo_base_init): Set typeinfo name visibility to class visibility. ! ! 2004-07-25 Bernardo Innocenti ! ! * decl.c: Rename all identifiers named `class' to `cl'. ! * cp-tree.h: Likewise. ! ! 2004-07-25 Gabriel Dos Reis ! ! * cp-tree.h (TYPE_SET_PTRMEMFUNC_TYPE): Use GGC_CNEW. ! * typeck2.c (abstract_virtuals_error): Use GGC_NEW. ! * name-lookup.c (binding_entry_make): Use GGC_NEW. ! (binding_table_construct): Use GGC_CNEWVEC. ! (binding_table_new): Use GGC_NEW. ! (cxx_binding_make): Likewise. ! (begin_scope): Likewise. ! (push_to_top_level): Use GCC_CNEW. ! * parser.c (cp_token_cache_new): Likewise. ! (cp_token_cache_push_token): Likewise. ! (cp_lexer_new_main): Likewise. ! (cp_lexer_new_from_tokens): Likewise. ! (cp_parser_context_new): Likewise. ! (cp_parser_new): Likewise. ! (cp_lexer_new_from_tokens): Use GGC_NEWVEC. ! * lex.c (cxx_make_type): Use GGC_CNEW. ! (retrofit_lang_decl): Use GGC_NEWVAR. ! (cxx_dup_lang_specific_decl): Likewise. ! (copy_lang_type): Likewise. ! * decl.c (use_label): Use GGC_NEW instead of ggc_alloc. ! (save_function_data): Likewise. ! (lookup_label): Use GGC_CNEW instead of ggc_alloc_cleared. ! (cxx_push_function_context): Likewise. ! ! 2004-07-25 Richard Henderson ! ! * decl.c (start_preparsed_function): Set DECL_ARTIFICIAL and ! DECL_IGNORED_P on RESULT_DECL. ! * semantics.c (finalize_nrv): Copy them too. ! ! 2004-07-23 Nathan Sidwell ! ! * search.c (lookup_conversion_operator): Avoid two loops. ! (add_conversions): Remove. ! (check_hidden_convs, split_conversions, ! lookup_conversions_r): New. ! (lookup_conversions): Use lookup_conversions_r. ! ! 2004-07-22 Nathan Sidwell ! ! * pt.c (get_template_base): Check type is completable. ! ! 2004-07-21 Eric Christopher ! ! * decl.c (poplevel): Inline unused variable checking. ! Change formatting. ! ! 2004-07-21 Paolo Bonzini ! ! * typeck.c (build_binary_op): Do not use RDIV_EXPR for ! integer vectors. ! ! 2004-07-21 Giovanni Bajo ! ! PR c++/14497 ! * pt.c (check_explicit_specialization): Remove extension to accept ! specializations without template headers. Fall-through to normal ! processing. ! ! 2004-07-21 Giovanni Bajo ! ! PR c++/509 ! * pt.c (determine_specialization): New parameter template_count. ! Disambiguate between member templates and member functions counting ! the template headers. ! (check_explicit_specialization): Update caller. ! (tsubst_friend_function): Likewise. ! ! 2004-07-20 Steven Bosscher ! ! * cp-tree.def (TINST_LEVEL): Make it an 'x' node. ! * cp-tree.h (tinst_level_t): New tree type. ! (union lang_tree_node): Handle it. ! (TINST_LOCATION): New accessor macro. ! (make_tinst_level): New prototype. ! * cp-lang.c (cp_tree_size): Handle TINST_LEVEL. ! * decl.c (cp_tree_node_structure): Likewise. ! * error.c (print_instantiation_full_context): Use TINST_LOCATION. ! (print_instantiation_partial_context): Likewise. ! * pt.c (pop_tinst_level): Likewise. ! (push_tinst_level): Use make_tinst_level. ! * tree.c (make_tinst_level): New function. ! (cp_walk_subtrees): Walk TINST_DECL for a TINST_LEVEL node. ! ! 2004-07-20 Mark Mitchell ! ! * parser.c (cp_parser_simple_type_specifier): Fix typo. ! ! PR c++/16637 ! * parser.c (cp_parser_simple_type_specifier): Do not record usage ! of globally-qualified names. ! ! 2004-07-20 Kriang Lerdsuwanakij ! ! PR c++/16175 ! * error.c (dump_type) : Output ! cv qualifier. ! ! 2004-07-19 Mark Mitchell ! ! PR c++/16623 ! * cp-tree.h (lang_type_class): Add lazy_assignment_op. ! (CLASSTYPE_LAZY_ASSIGNMENT_OP): New macro. ! * class.c (add_implicitly_declared_members): Use ! CLASSTYPE_LAZY_ASSIGNMENT_OP. ! * method.c (lazily_declare_fn): Clear ! CLASSTYPE_LAZY_ASSIGNMENT_OP. ! * search.c (lookup_fnfields_1): Check it. ! ! 2004-07-20 Nathan Sidwell ! ! * cp-tree.h (vec_binfo_member): Remove. ! * tree.c (vec_binfo_member): Remove. ! ! * cp-tree.h (struct lang_type_class): Remove vfields field. ! (CLASSTYPE_VFIELDS): Remove. ! (SET_BINFO_NEW_VTABLE_MARKED): Adjust. ! * class.c (determine_primary_base): Remove CLASSTYPE_VFIELDS ! handling. ! (dfs_modify_vtables): Use TYPE_CONTAINS_VPTR_P. ! (finish_struct_1): Remove CLASSTYPE_VFIELDS handling. ! * init.c (dfs_initialize_vtbl_ptrs): Use TYPE_CONTAINS_VPTR_P. ! ! 2004-07-20 Nathan Sidwell ! ! * cp-tree.h (DEF_VEC_P(tree)): Remove here. ! (BINFO_SUBVTT_INDEX, BINFO_VPTR_INDEX, BINFO_PRIMARY_BASE_OF): ! Moved to common. ! (BINFO_LANG_SLOTS): Remove. ! * tree.c (copy_binfo): Adjust BINFO creation and accessors. ! * decl.c (xref_basetypes): Adjust BINFO creation and accessors. ! * class.c (check_bases): Adjust BINFO accessors. ! (determine_primary_base, finish_struct_bits, ! maybe_warn_about_overly_private_class, warn_hidden, ! walk_subobject_offsets, propagate_binfo_offsets, end_of_class, ! warn_about_ambiguous_bases, get_vfield_name, ! dump_class_hierarchy_r, build_vtt_inits, accumulate_vtbl_inits, ! add_vcall_offset_vtbl_entries_r): Likewise. ! * dump.c (cp_dump_tree): Likewise. ! * init.c (sort_mem_initializers, expand_member_init, build_delete, ! push_base_cleanups): Likewise. ! * method.c (do_build_copy_constructor, do_build_assign_ref, ! synthesize_exception_spec): Likewise. ! name-lookup.c (arg_assoc_class): Likewise. ! * pt.c (instantiate_class_template, ! get_template_base_recursive): Likewise. ! * rtti.c (get_pseudo_ti_init, get_pseudo_ti_desc): Likewise. ! * typeck2.c (process_init_constructor): Likewise. ! * search.c (lookup_base_r, dynamic_cast_base_recurse, ! dfs_access_in_type, dfs_walk_real, look_for_overrides, ! types_overlap_p, copied_binfo, original_binfo): Likewise. ! (binfo_for_vtable): Remove ! ! 2004-07-20 Steven Bosscher ! ! * cp-tree.h (struct lang_decl_flags): Unify the template_info and ! thunk_alias, and the access and virtual_offset fields. ! (THUNK_VIRTUAL_OFFSET, THUNK_ALIAS): Adjust. ! * decl.c (finish_case_label): Update c_add_case_node call. ! ! 2004-07-19 Mark Mitchell ! ! Revert patch for PR c++/16623. ! ! 2004-07-19 Kelley Cook ! ! * except.c: Remove two spurious carriage returns. ! ! 2004-07-19 Mark Mitchell ! ! PR c++/16623 ! * cp-tree.h (lang_type_class): Add lazy_assignment_op. ! (CLASSTYPE_LAZY_ASSIGNMENT_OP): New macro. ! * class.c (add_implicitly_declared_members): Use ! CLASSTYPE_LAZY_ASSIGNMENT_OP. ! * method.c (lazily_declare_fn): Clear ! CLASSTYPE_LAZY_ASSIGNMENT_OP. ! * search.c (lookup_fnfields_1): Check it. ! ! 2004-07-19 Nathan Sidwell ! ! * class.c (add_method): Delay adding the slot until the end. ! (determine_primary_base): Adjust VEC_iterate invokation. ! (resort_type_method_vec, finish_struct_methods, warn_hidden, ! walk_subobject_offsets, end_of_class, warn_about_ambiguous_bases, ! build_vtbl_initializer): Likewise. ! * init.c (sort_mem_initializers, build_delete, push_base_cleanups, ! build_vbase_delete): Likewise. ! * method.c (do_build_copy_constructor): Likewise. ! * name-lookup.c (new_class_binding, print_binding_level, ! poplevel_class, store_class_bindings, push_to_top_level, ! pop_from_top_level): Likewise. ! * pt.c (check_explicit_specialization): Likewise. ! * search.c (lookup_conversion_operator, lookup_fnfields_1, ! get_pure_virtuals, add_conversions, dfs_check_overlap, ! binfo_for_vbase): Likewise. ! ! 2004-07-19 Kriang Lerdsuwanakij ! ! PR c++/12170 ! * pt.c (unify) : Use only ! innermost set of template arguments during deduction. Simplify. ! ! 2004-07-19 Joseph S. Myers ! ! * typeck.c (build_modify_expr, build_x_modify_expr): Set ! TREE_NO_WARNING on assignments with an operator other than '='. ! ! 2004-07-10 Steven Bosscher ! Joseph S. Myers ! ! * cp-tree.h (C_SET_EXP_ORIGINAL_CODE): Remove. ! * decl2.c (grokfield): Don't check current_class_depth via ! unused TREE_COMPLEXITY. ! * semantics.c (finish_parenthesized_expr): Set TREE_NO_WARNING ! to avoid the missing parentheses warning. ! Don't set C_SET_EXP_ORIGINAL_CODE. ! ! 2004-07-18 Mark Mitchell ! ! * tree.c (no_linkage_helper): Remove. ! (no_linkage_check): Don't use walk_tree_without_duplicates. ! ! * mangle.c (write_expression): Issue a sorry for zero-operand ! functional casts. ! ! 2004-07-18 Kriang Lerdsuwanakij PR c++/13092 * init.c (build_offset_ref): Build SCOPE_REF with non-null *************** *** 323,341 **** * error.c (dump_decl) : Use pp_expression. (dump_expr) : Likewise. ! 2004-07-21 Kriang Lerdsuwanakij ! PR c++/16175 ! * error.c (dump_type) : Output ! cv qualifier. ! 2004-07-20 Mark Mitchell ! (cp_parser_simple_type_specifier): Fix typo. ! ! PR c++/16637 ! * parser.c (cp_parser_simple_type_specifier): Do not record usage ! of globally-qualified names. 2004-07-12 Andrew Pinski --- 4355,4612 ---- * error.c (dump_decl) : Use pp_expression. (dump_expr) : Likewise. ! 2004-07-17 Jason Merrill ! PR c++/16115 ! * call.c (type_passed_as): Make the invisible reference type ! __restrict. ! * cp-gimplify.c (gimplify_cleanup_stmt): Rename to ! cp_genericize_r. Handle invisible reference lowering. ! (is_invisiref_parm): New fn. ! (cp_genericize): Adjust the types of invisible reference parms. ! Don't repeat the walk for clones. ! * decl.c (store_parm_decls): Don't generate any code for clones. ! 2004-07-17 Joseph S. Myers ! * cp-tree.h (builtin_function): Declare. ! ! 2004-07-16 Mark Mitchell ! ! * class.c (finish_struct_methods): Remove unncessary code. ! (add_implicitly_declared_members): Create declarations for default ! constructors and copy constructors lazily. ! * cp-tree.h (lang_type_class): Remove lazy_default_ctor and ! lazy_copy_ctor. ! (CLASSTYPE_LAZY_DEFAULT_CTOR): New macro. ! (CLASSTYPE_LAZY_COPY_CTOR): Likewise. ! * decl2.c (check_classfn): Robustify. ! (locate_dtor): Handle empty CLASSTYPE_METHOD_VEC. ! (locate_ctor): Handle lazy default constructors. ! (locate_copy): Handle lazy copy constructors. ! (implicitly_declare_fn): Make sure we're looking at the ! TYPE_MAIN_VARIANT for a class before creating functions. Don't ! set TYPE_HAS_CONSTRUCTOR. ! (lazily_declare_fn): New function. ! * name-lookup.c (constructor_name_full): Simplify. ! * search.c (lookup_fnfields_1): Lazily create methods, as ! necessary. ! (lookup_for_overrides): Handle empty CLASSTYPE_METHOD_VEC. ! ! 2004-07-16 Steven Bosscher ! ! * cp-tree.h (struct lang_type): Don't have three GTY options on a ! single bit GTY desc. ! ! 2004-07-16 Richard Henderson ! ! * cp-lang.c (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING): Die. ! * cp-tree.h (cp_copy_res_decl_for_inlining): Remove. ! * tree.c (cp_copy_res_decl_for_inlining): Remove. ! ! 2004-07-16 Nathan Sidwell ! ! * class.c (finish_struct_bits): Use for loop. ! (propagate_binfo_offsets): Do primary binfo outside of loop. ! ! PR c++/16583 ! * dump.c (cp_dump_tree): Don't dump the bases if there's no ! binfo. ! ! * pt.c (tsubst) : We should never get here. ! ! 2004-07-15 Mark Mitchell ! ! * cp-tree.h (lang_type_class): Remove has_real_assign_ref and ! has_abstract_assign_ref. Make methods a VEC(tree) *. ! (TYPE_HAS_CONST_ASSIGN_REF): Add documentation. ! (CLASSTYPE_CONSTRUCTORS): Adjust for changes to CLASSTYPE_METHOD_VEC. ! (CLASSTYPE_DESTRUCTORS): Likewise. ! (TYPE_HAS_REAL_ASSIGN_REF): Remove. ! (TYPE_HAS_ABSTRACT_ASSIGN_REF): Likewise. ! (add_method): Change prototoype. ! * class.c (add_method): Remove error_p parameter. Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! (handle_using_decl): Adjust call to add_method. ! (maybe_warn_about_overly_private_class): Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! (resort_type_method_vec): Likewise. ! (finish_struct_methods): Likewise. ! (check_for_override): Likewise. ! (warn_hidden): Likewise. ! (add_implicitly_declared_members): Defer creation of assignment ! operators. Adjust call to add_method. ! (clone_function_decl): Adjust call to add_method. ! (check_bases_and_members): Don't set TYPE_HAS_REAL_ASSIGN_REF. ! (finish_struct_1): Use CLASSTYPE_DESTRUCTORS. ! * decl.c (grok_special_member_properties): Don't set ! TYPE_HAS_ABSTRACT_ASSIGN_REF. ! * decl2.c (check_classfn): Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! * method.c (locate_dtor): Use CLASSTYPE_DESTRUCTORS. ! (locate_ctor): Use CLASSTYPE_CONSTRUCTORS. ! (locate_copy): Adjust for changes to CLASSTYPE_METHOD_VEC. ! (implicitly_declare_fn): Set DECL_SOURCE_LOCATION. Do not call ! cp_finish_decl. ! * pt.c (check_explicit_specialization): Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! (instantiate_class_template): Do not set ! TYPE_HAS_ABSTRACT_ASSIGN_REF. ! * ptree.c (cxx_print_type): Don't try to print ! CLASSTYPE_METHOD_VEC. ! * rtti.c (emit_support_tinfos): Use CLASSTYPE_DESTRUCTORS. ! * search.c (lookup_field_r): Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! (lookup_fnfields): Likewise. ! (lookup_conversion_operator): Likewise. ! (lookup_fnfields_1): Likewise. Create assignment operators ! lazily. ! (look_for_overrides_here): Adjust for ! changes to CLASSTYPE_METHOD_VEC. ! (add_conversions): Likewise. ! * semantics.c (finish_member_declaration): Adjust call to add_method. ! ! 2004-07-15 Jason Merrill ! ! * cp-lang.c (cxx_types_compatible_p): To the middle-end, ! references and pointers are compatible. ! ! 2004-07-15 Nathan Sidwell ! ! * decl.c (xref_basetypes): Refactor. ! * tree.c (copy_base_binfos): Replace with ... ! (copy_binfo): ... this. Deep copy the given binfo, (not the just ! bases of the given base). ! * cp-tree.h (copy_base_binfo): Remove. ! (copy_binfo): Declare. ! ! 2004-07-15 Mark Mitchell ! ! * name-lookup.c (set_inherited_value_binding_p): Add class_type ! parameter. ! (get_class_binding): Adjust. ! (push_class_level_binding): Don't use set_inherited_value_binding_p. ! ! 2004-07-15 Nathan Sidwell ! ! * class.c (finish_struct_bits): Don't set TYPE_HAS_CONVERSION here. ! * decl.c (xref_basetypes): Set it here. ! ! * class.c (check_bases): Don't set CLASSTYPE_NON_AGGREGATE here. ! Don't check for incomplete base. ! (get_vfield_name): Simplify while loop. ! * decl.c (xref_basetypes): Set CLASSTYPE_NON_AGGREGATE here. ! ! 2004-07-14 Mark Mitchell ! ! * lex.c (cxx_make_type): Remove call to get_pointer_type. ! ! * cp-tree.h (IDENTIFIER_VALUE): Remove. ! (BINFO_PUSHDECLS_MARKED): Likewise. ! (maybe_inject_for_scope_var): Likewise. ! (push_class_decls): Likewise. ! * name-lookup.h (push_class_binding): Remove. ! (innermost_non_namespace_value): New function. ! (outer_binding): Likewise. ! * class.c (add_method): Push bindings before adding to ! TYPE_METHODS. ! (restore_class_cache): Do not restore class_shadowed. ! (pushclass): Do not add USING_DECLs. Do not call ! push_class_decls. ! * config-lang.in (gtfiles): Remove $(srcdir)/cp/search.c. ! * decl.c (pushdecl): Use outer_binding. ! (poplevel): Set the scope for an out-of-scope for-loop declaration ! appropriately. ! (cp_finish_decl): Don't call maybe_inject_for_scope_var. ! * name-lookup.c (new_class_binding): New function. ! (push_binding): Use it. ! (pushdecl): Use innermost_non_namespace_value. ! (maybe_inject_for_scope_var): Remove. ! (push_class_binding): Remove. ! (set_inherited_value_binding_p): New function. ! (get_class_binding): New function. ! (push_class_level_binding): Assert that the current_class_type is ! being defined. ! (outer_binding): New function. ! (innermost_non_namespace_value): Likewise. ! (lookup_name_real): Use outer_binding. ! (lookup_name_current_level): Ignore out-of-scope variables. ! * pt.c (check_template_shadow): Use innermost_non_namespace_value. ! (lookup_template_class): Likewise. ! * search.c (dfs_push_type_decls): Remove. ! (dfs_push_decls): Likewise. ! (setup_class_bindings): Likewise. ! (lookup_field_1): Handle USING_DECLs from dependent scopes. ! (marked_pushdecls_p): Remove. ! (unmarked_pushdecls_p): Remove. ! (marked_identifiers): Remove. ! (setup_class_bindings): Remove. ! (dfs_push_type_decls): Remove. ! (dfs_push_decls): Remove. ! (push_class_decls): Remove. ! ! 2004-07-13 Mark Mitchell ! ! PR c++/16518 ! PR c++/16337 ! * decl.c (grokvardecl): Make declspecs parameter const. ! (grokdeclarator): Likewise. Adjust accordingly. ! * decl.h (grokdeclarator): Adjust declaration. ! * parser.c (cp_parser_init_declarator): Do not clear ! decl_specifiers->attributes. ! ! * cp-tree.h (lang_identifier): Remove class_value. ! (IDENTIFIER_CLASS_VALUE): Remove. ! (pop_class_decls): Likewise. ! (init_search_processing): Likewise. ! * class.c (handle_using_decl): Use lookup_member, not ! IDENTIFIER_CLASS_VALUE. ! (restore_class_cache): New function, split out from ... ! (pushclass): ... here. Do not call clear_identifier_class_values. ! (invalidate_class_lookup_cache): Do not clear ! IDENTIFIER_CLASS_VALUE. ! (popclass): Do not call pop_class_decls. ! (maybe_note_name_used_in_class): Do not save names looked up after ! the class is complete. Use lookup_member, not ! IDENTIFIER_CLASS_VALUE. ! * config-lang.in (gtfiles): Add $(srcdir)/cp/search.c. ! * decl.c (cxx_init_decl_processing): Do not call ! init_search_processing. ! * method.c (do_build_copy_constructor): Remove unnecessary code. ! (do_build_assign_ref): Likewise. ! * name-lookup.c (pushdecl): Use lookup_member, not ! IDENTIFIER_CLASS_VALUE. ! (set_identifier_type_value_with_scope): Set TREE_TYPE on the ! type_shadowed list. ! (poplevel_class): Do not restore IDENTIFIER_CLASS_VALUE. ! (push_class_binding): Do not set it. ! (clear_identifier_class_values): Remove. ! (push_class_level_binding): Do not set IDENTIFIER_CLASS_VALUE. ! (store_binding): Do not save it. ! (pop_from_top_level): Do not restore it. ! * name-lookup.h (cxx_saved_binding): Remove class_value. ! (clear_identifier_class_values): Remove. ! * ptree.c (cxx_print_identifier): Do not print ! IDENTIFIER_CLASS_VALUE. ! * search.c (search_obstack): Remove. ! (push_stack_level): Remove. ! (pop_stack_level): Remove. ! (search_level): Remove. ! (search_stack): Remove. ! (lookup_member): Don't check IDENTIFIER_CLASS_VALUE. ! (setup_class_bindings): Use IDENTIFIER_MARKED, not ! IDENTIFIER_CLASS_VALUE. ! (marked_identifiers): New variable. ! (push_class_decls): Clear IDENTIFIER_MARKED. ! (pop_class_decls): Don't call pop_search_level. ! (init_search_processing): Remove. ! ! 2004-07-12 Mark Mitchell ! ! * cp-tree.h (get_aggr_typedef): Remove. ! * init.c (get_aggr_typedef): Likewise. ! ! * name-lookup.c (push_class_level_binding): Simplify. 2004-07-12 Andrew Pinski *************** *** 344,351 **** 2004-07-07 H.J. Lu PR c++/16276 * rtti.c (emit_tinfo_decl): Turn off DECL_ONE_ONLY if typeinfo ! is not public. 2004-07-07 H.J. Lu --- 4615,4826 ---- 2004-07-07 H.J. Lu PR c++/16276 * rtti.c (emit_tinfo_decl): Turn off DECL_ONE_ONLY if typeinfo ! is not public. + 2004-07-12 Eric Christopher + + * parser.c (cp_parser_class_head): Remove unused variable. + + 2004-07-12 Giovanni Bajo + + * decl.c (grok_op_properties): Reject [de-]allocation functions + declared in a namespace, or declared as static. + + 2004-07-12 Nathan Sidwell + + * cp-tree.h (make_binfo): Remove. + * decl.c (xref_basetypes): Use make_tree_binfo directly. + * tree.h (copy_base_binfos): Likewise. + (make_binfo): Remove. + + * call.c (build_user_type_conversion_1, build_new_op, + check_constructor_callable, build_temp, + perform_direct_initialization_of_possible): Pass type directly to + lookup_fnfields & build_special_member_call. + (build_special_member_call): Accept a type, and complete it. + * class.c (finish_stuct_bits): Copy the BINFOs here. + * cvt.c (ocp_convert): Pass type directly to + build_special_member_call. + * decl.c (build_ptrmemfunc_type): Call xref_bastypes here. + (xref_basetypes): Allocate the binfo here. Adjust. + * init.c (build_init, build_new_1): Pass type directly to + build_special_member_call. + * lex.c (cxx_make_type): Do not allocate binfo here. + * name-lookup.c (arg_assoc_class): Incomplete types have no binfo. + * parser.c (cp_parser_class_head): Always call xref_basetypes. + * pt.c (instantiate_class_template): Likewise. Inhibit access + checking for template friends. + * ptree.c (cxx_print_type): Adjust record printing. + * search.c (lookup_base): When taking a type, complete it before + looking for a binfo. + (lookup_member): Delay completing a type. + (push_class_decls): Don't walk an incomplete type. + (lookup_conversions): Likewise. + * semantics.c (finish_stmt_expr_expr): Pass type directly to + build_special_member_call. + * tree.c (copy_base_binfos): Adjust. + (make_binfo): Likewise. + * typeck.c (build_modify_expr): Pass type directly to + build_special_member_call. + * typeck2.c (process_init_constructor): Check a binfo exists. + (build_m_component_ref): Allow accessing an incomplete type. + (build_functional_cast): Pass type directly to + build_special_member_call. + + 2004-07-12 Giovanni Bajo + + PR c++/2204 + * config-lang.in (gtfiles): Add typeck2.c. + * Make-lang.in: Tweak typeck2.c dependencies, and add rule for + gt-cp-typeck2.h. + * cp-tree.h: Declare complete_type_check_abstract. + * typeck2.c (pat_calc_hash, pat_compare, + complete_type_check_abstract): New functions. + (abstract_virtuals_error): If the type is abstract, register the + declaration within abstract_pending_vars for further checks. + Inspect also dependent types. Handle IDENTIFIER_NODEs as decl. + * decl.c (cp_finish_decl): Do not strip array types. + (create_array_type_for_decl): Check for abstractness of the element + type. + (complete_vars): Call complete_type_check_abstract. + * class.c (finish_struct): Prepare a list of virtual functions for + template types, and call complete_vars on it to check for abstractness. + + 2004-07-12 Paolo Bonzini + + PR tree-optimization/14107 + * decl.c (finish_function): Remove temporary band-aid. + + 2004-07-11 Mark Mitchell + + * call.c (build_operator_new_call): Avoid using push_to_top_level. + (build_new_op): Adjust call to lookup_function_nonclass. + * name-lookup.c (identifier_type_value): Adjust call to + lookup_name_real. + (lookup_name_real): Add block_p parameter. + (lookup_name_nonclass): Adjust call to lookup_name_real. + (lookup_function_nonclass): Likewise. + (lookup_name): Likewise. + * name-lookup.h (lookup_name_real): Change prototype. + (lookup_name_nonclass): Likewise. + * parser.c (cp_parser_lookup_name): Likewise. + + * cp-tree.h (saved_scope): Make old_bindings a vector. + (unuse_fields): Remove. + * name-lookup.h (cxx_saved_binding): Define it. + * class.c (pushclass): Don't use unuse_fields. + * name-lookup.c (cxx_saved_binding_make): Remove. + (store_binding): Add new bindings to a vector, using an + accumulator style, rather than adding them to a list. + (store_bindings): Adjust accordingly. + (store_class_bindings): Likewise. + (push_to_top_level): Likewise. + (pop_from_top_level): Likewise. + * optimize.c (maybe_clone_body): Must push_to_top_level and + pop_from_top_level calls outside of loop. + * parser.c (cp_parser_class_specifier): Move push_scope/pop_scope + calls here from cp_parser_late_parsing_default_args. + (cp_parser_save_default_args): Record the class type in which the + function is declared. + (cp_parser_late_parsing_default_args): Do not call + push_nested_class/pop_nested_class. + * search.c (dfs_unuse_fields): Remove. + (unuse_fields): Remove. + + 2004-07-11 Joseph S. Myers + + * cp-lang.c (LANG_HOOKS_MAYBE_BUILD_CLEANUP, LANG_HOOKS_PUSHLEVEL, + LANG_HOOKS_POPLEVEL, LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): Remove. + * cp-tree.h (poplevel): Declare. + (set_block): Remove. + * decl.c (set_block): Remove. + + 2004-07-10 Mike Stump + + * decl2.c (import_export_class): Never export/import vtables + with inline key functions. + + 2004-07-09 Steven Bosscher + + * typeck.c (c_expand_asm_operands): Remove. + + 2004-07-09 Mike Stump + + * typeck.c (build_class_member_access_expr): Skip null deref + warning when we don't dereference it. + + 2004-07-09 Giovanni Bajo + + PR c++/8211 + PR c++/16165 + * class.c (check_field_decls): Improve -Weffc++ warning: do not + warn for pointers to functions/members, or for classes without + destructors. + + 2004-07-08 Mark Mitchell + + * name-lookup.h (struct cp_binding_level): Update documentation + for class_shadowed. + + 2004-07-08 Giovanni Bajo + + PR c++/16169 + * typeck.c (check_return_expr): Improve -Weffc++ warning: handle + returning CALL_EXPR, and non-reference return type. + + 2004-07-08 Nathan Sidwell + + * name-lookup.c (push_binding): Use VEC_reserve. + + 2004-07-08 Richard Henderson + + * cp-tree.h (expand_eh_spec_block): Remove. + + 2004-07-07 Mark Mitchell + + * cp-tree.h (saved_scope): Remove x_previous_class_type and + x_previous_class_values; add x_previous_class_level. + (previous_class_type): Remove. + (previous_class_values): Remove. + (previous_class_level): New macro. + * class.c (pushclass): Restore the identifier cache more + expeditiously. + (invalidate_class_lookup_cache): Use vector for class_shadowed and + previous_class_values. + * decl.c (poplevel): Likewise. + * name-lookup.c (cxx_binding_init): New function. + (cxx_binding_make): Use it. + (push_binding): For a binding in a class level, use a vector of + cp_class_binding nodes. + (push_binding_level): New function. + (begin_scope): Use it. + (leave_scope): Do not put class binding levels on the free list. + (print_binding_level): Adjust for the fact that class_shadowed is + a vector. + (poplevel_class): Likewise. + (clear_identifier_class_values): Likewise. + (push_class_level_binding): Likewise. + (set_class_shadows): Remove. + (store_binding): New function. + (store_class_bindings): New function. + (push_to_top_level): Use store_class_bindings as appropriate. + (pop_from_top_level): Use previous_class_level, not + previous_class_type. + * name-lookup.h (cp_class_binding): New type. + (cp_binding_level): Use a vector object for class_shadowed. + (push_binding_level): Declare. + (set_class_shadows): Remove. + + 2004-07-07 Andrew Pinski + + * class.c (instantiate_type): BUFFER_REF is dead. + * lex.c (init_operators): IN_EXPR is dead. + + 2004-07-07 Jason Merrill + + PR c++/16334 + * call.c (build_new_op): Give overload warnings for built-in + candidates. 2004-07-07 H.J. Lu *************** *** 353,365 **** * rtti.c (emit_tinfo_decl): Turn off DECL_ONE_ONLY if typeinfo is not public. ! 2004-07-01 Release Manager ! * GCC 3.4.1 released. 2004-06-28 Nathan Sidwell ! PR C++/16174 * call.c (build_temp): Declare. (check_constructor_callable): New. (reference_binding): Only set CHECK_COPY_CONSTRUCTOR if not for --- 4828,5099 ---- * rtti.c (emit_tinfo_decl): Turn off DECL_ONE_ONLY if typeinfo is not public. ! 2004-07-07 Nathan Sidwell ! * cp-tree.h (CLASSTYPE_N_BASECLASSES): Remove. ! * class.c (build_primary_vtable, check_bases, ! determine_primary_base, finish_struct_bits, ! maybe_warn_about_overly_private_class, dfs_find_final_overrider_q, ! get_basefndecls, warn_hidden, walk_subobject_offsets, ! build_base_fields, create_vtable_ptr, propagate_binfo_offsets, ! layout_virtual_bases, end_of_class, warn_about_ambiguous_bases, ! finish_struct_1, get_vfield_name, contains_empty_class_p, ! dump_class_hierarchy_r, finish_vtbls, build_vtt_inits, ! dfs_ctor_vtable_bases_queue_p, accumulate_vtbl_inits, ! add_vcall_offset_vtbl_entries_r, cp_fold_obj_type_ref): Adjust ! BINFO macros. ! * decl.c (xref_basetypes): Likewise. ! * dump.c (cp_dump_tree): Likewise. ! * error.c (dump_expr): Likewise. ! * init.c (sort_mem_initializers, expand_member_init, ! push_base_cleanups): Likewise. ! * method.c (do_build_copy_constructor, do_build_assign_reg, ! synthesize_exception_spec): Likewise. ! * name-lookup.c (arg_assoc_class): Likewise. ! * pt.c (instantiate_class_template, tsubst, ! get_template_base_recursive): Likewise. ! * ptree.c (cxx_print_type): Likewise. ! * rtti.c (get_psuedo_ti_init, get_pseudo_ti_desc): Likewise. ! * search.c (lookup_base_r, dynamic_cast_base_recurse, ! dfs_access_in_type, access_in_type, lookup_field_queue_p, ! bfs_walk, dfs_walk_real, look_for_overrides, markedp, unmarkedp, ! marked_pushdecls_p, unmarked_pushdecls_p, dfs_debug_markedp, ! dfs_debug_unmarkedp, dfs_check_overlap, dfs_no_overlap_yet, ! binfo_for_vtable, copied_binfo, original_binfo): Likewise ! * tree.c (copy_base_binfos, make_binfo): Likewise. ! * typeck.c (commmon_base_type): Likewise ! * typeck2.c (process_init_constructor): Likewise ! ! 2004-07-06 Joseph S. Myers ! ! * decl.c (check_tag_decl): Name redeclared type in diagnostic. ! ! 2004-07-06 Giovanni Bajo ! ! PR c++/3671 ! * pt.c (convert_nontype_argument): Disallow conversions between ! different enumeration types. ! ! 2004-07-06 Nathan Sidwell ! ! * cp-tree.h (BINFO_MARKED): Remove. ! (BINFO_VTABLE_PATH_MARKED, BINFO_NEW_VTABLE_MARKED, ! BINFO_DEPENDENT_BASE_P, BINFO_LOST_PRIMARY_P, ! BINFO_INDIRECT_PRIMARY_P): Use appropriate BINFO_FLAG_n. ! (SET_BINFO_NEW_VTABLE_MARKED): Use BINFO_VIRTUAL_P. ! * class.c (build_base_path): Use BINFO_VIRTUAL_P. ! (mark_primary_bases, determine_primary_base, base_derived_from, ! dfs_find_final_overrider, dfs_find_final_overrider_q, ! dfs_find_inal_overrider_post, update_vtable_entry_for_fn, ! dfs_modify_vtables, walk_subobject_offsets, ! layout_nonempty_base_or_field, build_base_field, ! build_base_fields, propagate_binfo_offsets, layout_virtual_bases, ! end_of_class, get_vfield_name, dump_class_hierarchy, dump_vtable, ! finish_vtbls, build_vtt_inits, dfs_build_secondary_vptr_vtt_inits, ! build_ctor_vtbl_group, accumulate_vtble_inits, ! dfs_accumulate_vtbls_inits, build_vbase_offset_vtbl_entries, ! build_vcall_offset_vtbl_entries, add_vcall_offset_vtbl_entries_r, ! add_vcall_offset_vtbl_entries_1): Likewise. ! * decl.c (xref_basetypes): Incomming virtual base indicated by ! TREE_TYPE. Adjust. ! * dump.c (cp_dump_tree): Use BINFO_VIRTUAL_P. ! * init.c (finish_init_stmts, sort_mem_initializers, ! emit_mem_initializers, build_vtble_address, expand_member_init, ! push_base_cleanups): Likewise. ! * method.c (do_build_copy_constructor): Likewise. ! * pt.c (instantiate_class_template, ! get_template_base_recursive): Likewise. ! * rtti.c (dfs_class_hint_mark, get_pseudo_ti_init, ! get_pseudo_ti_desc): Likewise. ! * search.c (lookup_base_r, dynamic_cast_base_recurse, ! binfo_from_vbase, binfo_via_virtual, copied_binfo, ! original_binfo): Likewise. ! * semantics.c (finish_base_specifier): Virtualness is indicated ! by TREE_TYPE. ! * tree.c (copy_base_binfos): Use BINFO_VIRTUAL_P. ! ! 2004-07-06 Mark Mitchell ! ! Revert: ! 2004-06-24 Jason Merrill ! PR c++/16115 ! * decl.c (grokparms): Give the PARM_DECL reference type if the ! parameter is passed by invisible reference. ! ! 2004-07-05 Richard Kenner ! ! * cp-lang.c (cp_var_mod_type_p): Add extra arg. ! * decl.c (grokdeclarator): Extra arg to variably_modified_type_p. ! * pt.c (check_instantiated_args, unify): Likewise. ! ! 2004-07-05 Phil Edwards ! ! * Make-lang.in (check-c++, lang_checks): Add some comments. ! ! 2004-07-05 Zack Weinberg ! ! * cp-mudflap.c: Delete file. ! * Makefile.in: Remove all references to cp-mudflap.o. ! ! 2004-07-05 Zack Weinberg ! ! * decl.c (cxx_init_decl_processing): Call ! build_common_tree_nodes before creating the global NAMESPACE_DECL. ! ! 2004-07-05 Giovanni Bajo ! ! PR c++/2518 ! * call.c (build_operator_new_call): Look only at global scope. ! ! 2004-07-05 Nathan Sidwell ! ! * call.c (enforce_access): Expect TREE_BINFO. ! * class.c (binfo_ctor_vtable): Check TREE_BINFO. ! * cp-tree.h (RECORD_OR_UNION_TYPE_CHECK): Remove. ! (BINFO_SUBVTT_INDEX, BINFO_VPTR_INDEX, BINFO_PRIMARY_BASE_OF): ! Adjust. ! (BINFO_LANG_ELTS): Remove. ! (BINFO_LANG_SLOTS): New. ! (TYPE_RAISES_EXCEPTIONS, ENUM_TEMPLATE_INFO): Use TYPE_LANG_SLOT_1. ! (CLASSTYPE_TEMPLATE_INFO): Adjust. ! * pt.c (tsubst): Split TREE_BINFO case from TREE_VEC case. ! * search.c (lookup_member): Check TREE_BINFO. ! * semantics.c (perform_or_defer_access_check): Likewise. ! (check_accessibility_of_qualified_id): Check ! deferred_access_no_check. ! * tree.c (make_binfo): Use make_tree_binfo. ! ! 2004-07-04 Mark Mitchell ! ! * method.c (implicitly_declare_fn): Set linkage of generated ! functions. ! ! 2004-07-04 Richard Henderson ! ! * typeck.c (cxx_mark_addressable): Don't put_var_into_stack. ! ! 2004-07-03 Scott Brumbaugh ! ! PR c++/3761 ! * name-lookup.c (push_class_level_binding): Don't pass a ! TREE_LIST of ambiguous names to check_template_shadow as it ! only handles declarations. Instead, pull the declaration ! out and pass that. ! ! 2004-07-03 Giovanni Bajo ! ! PR c++/14971 ! * pt.c (check_explicit_specialization): Clarify error message. ! ! 2004-07-02 Richard Henderson ! ! * tree.c (cp_unsave_r): Update remap_save_expr call. ! ! 2004-07-02 Mark Mitchell ! ! PR c++/16240 ! * mangle.c (write_template_arg): Correct mangling. ! ! PR c++/16297 ! * decl.c (grokdeclarator): Robustify. ! ! 2004-07-01 Richard Henderson ! ! * class.c (fixed_type_or_null): Don't handle RTL_EXPR. ! * method.c (synthesize_method): Don't clear_last_expr. ! * name-lookup.c (maybe_push_cleanup_level): Likewise. ! ! 2004-07-01 Nick Clifton ! ! * decl2.c (import_export_class): Invoke the ! import_export_class field in the gcc_target structure if it is not ! empty. ! ! 2004-06-30 Richard Henderson (rth@redhat.com> ! ! * decl.c (start_preparsed_function): Don't set immediate_size_expand. ! * method.c (use_thunk): Likewise. ! ! 2004-06-30 Joseph S. Myers ! ! * call.c (build_over_call), typeck.c (build_function_call): Call ! check_function_arguments instead of check_function_format. ! ! 2004-06-30 Joseph S. Myers ! ! * call.c (build_over_call), typeck.c (build_function_call): Update ! calls to check_function_format. ! ! 2004-06-30 Richard Henderson ! ! * call.c (build_over_call): Use __builtin_memcpy for copying ! CLASS_AS_BASE rather than funny casting. ! ! 2004-06-30 Richard Henderson ! ! * init.c (build_new_1): Fill in TYPE_DOMAIN, TYPE_SIZE and ! TYPE_SIZE_UNIT of full_type. ! ! 2004-06-30 Per Bothner ! ! Conditionally compile support for --enable-mapped_location. ! * decl.c (pop_label): Handle (imperfectly) USE_MAPPED_LOCATION case. ! * decl2.c: If USE_MAPPED_LOCATION, don't do some line number ! adjustments - which I don't understand. ! * error.c (dump_decl): Rename "" to "". ! * error.c: Use LOCATION_FILE and EXPR_LOCATION macros. ! (print_instantiation_partial_context): Use expand_location. ! * decl.c (duplicate_decl): Use new DECL_IS_BUILTIN macro. ! * name-lookup.c: Likewise. ! * lex.c (cxx_init): Likewise. Also use BUILTINS_LOCATION. ! * name-lookup.c: Use input_line macro. ! * parser.c (cp_lexer_get_preprocessor_token): Use UNKNOWN_LOCATION. ! (cp_parser_statement): Rename locaal variable statement_locus to ! statement_location and use SET_EXPR_LOCATION macro. ! * pt.c: Handle USE_MAPPED_LOCATION case. Use new macros. ! * tree.c (cp_walk_subtrees): Likewise. ! ! 2004-06-29 Per Bothner ! ! * tree.c (build_min_nt, build_min, build_min_non_dep): ! Don't set TREE_COMPLEXITY from input_line. ! ! 2004-06-29 Paul Brook ! ! * init.c: Include target.h. ! (get_cookie_size): Remove and replace with target hook. ! Update callers. ! (build_new_1): Store the element size in the cookie. ! ! 2004-06-29 Nathan Sidwell ! ! PR c++/16260 ! * parser.c (cp_parser_template_declaration_after_export): Disable ! access checks here ... ! (cp_parser_class_specifier): ... not here. 2004-06-28 Nathan Sidwell ! * cp-tree.h (VAR_OR_FUNCTION_DECL_CHECK, ! VAR_FUNCTION_OR_PARM_DECL_CHECK, RECORD_OR_UNION_TYPE_CHECK, ! BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK): Use appropriate ! TREE_CHECK macro. ! ! 2004-06-28 Nathan Sidwell ! ! * cp-tree.h (struct deferred_access): Move to ... ! * semantics.c (struct deferred_access): ... here. Adjust. ! (deferred_access_stack): Make a VEC(deferred_access), ! (deferred_access_free_list): Remove. ! (deferred_access_no_check): New. ! (push_deferring_access_checks, resume_deferring_access_checks, ! stop_deferring_access_checks, pop_deferring_access_checks, ! get_deferred_access_checks, pop_to_parent_deferring_access_checks, ! perform_deferred_access_checks, perform_or_defer_access_check): Adjust. ! ! 2004-06-28 Nathan Sidwell ! ! PR c++/16174 * call.c (build_temp): Declare. (check_constructor_callable): New. (reference_binding): Only set CHECK_COPY_CONSTRUCTOR if not for *************** *** 369,401 **** * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New. (LOOKUP_*): Renumber. ! 2004-06-25 Jan Hubicka PR C++/14865 * decl2.c (maybe_emit_vtables): Always import_export_vtable for the reachability analysis. ! 2004-06-22 Jan Hubicka ! PR C++/14950 ! * pt.c (instantiate_decl): Clean TI_PENDING_TEMPLATE_FLAG before ! expanding the function. ! 2004-06-21 Nathan Sidwell ! PR c++/3518 ! * pt.c (check_cv_quals_for_unify): Ignore bogus CV quals at outer ! level. ! ! PR c++/14007 ! * pt.c (check_cv_quals_for_unify): Correct logic for disallowed ! cv-qualifier unification. ! * tree.c (cp_build_qualified_type_real): Renable DR295 logic. ! 2004-06-15 Giovanni Bajo PR c++/15967 ! * search.c (build_new_1): Robustify. 2004-06-14 Giovanni Bajo --- 5103,5754 ---- * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New. (LOOKUP_*): Renumber. ! 2004-06-28 Nathan Sidwell ! ! * friend.c (add_friend): Only perform access checks when context ! is a class. ! * lex.c (cxx_make_type): Only create a binfo for aggregate types. ! * parser.c (cp_parser_class_specifier): Disable access checks here ! when parsing the body of a templated class. ! * semantics.c (perform_or_defer_access_checks): Reorder to allow ! NULL binfos when not checking access. ! ! 2004-06-28 Nathan Sidwell ! ! Use vector API for vbase list. ! * cp-tree.h: Include vec.h ! (DEF_VEC_P (tree)): New type. ! (struct lang_type_class): Change vbase's member type. ! (binfo_for_vbase): Declare. ! * class.c (determine_primary_base, base_derived_from, ! update_vtable_entry_for_fn, walk_subobject_offsets, end_of_class, ! warn_about_ambiguous_bases, dfs_accumulate_vtbl_inits, ! build_vtbl_initializer): Adjust. ! * decl.c (xref_basetypes): Adjust, accumulate upper bound of ! vbases. ! * init.c (sort_mem_initializers, expand_member_init, ! push_base_cleanups): Adjust. ! * method.c (do_build_copy_constructor): Adjust. ! * search.c (get_pure_virtuals, copied_binfo, original_binfo): Adjust. ! (binfo_for_vbase): New. ! * tree.c (copy_base_binfos): Adjust. ! ! 2004-06-28 Mark Mitchell ! ! * parser.c (cp_parser_set_decl_spec_type): Fix thinko. ! ! 2004-06-27 Gabriel Dos Reis ! ! PR c++/14123 ! * cxx-pretty-print.c (pp_cxx_ptr_operator): Properly put ! paranthesis in case of pointers to array members. ! * error.c (dump_type_prefix): Likewise. ! (dump_type_suffix): Maybe issue a whitespace when printing ! ARRAY_TYPE. ! ! 2004-06-27 Mark Mitchell ! ! PR c++/16193 ! * parser.c (cp_parser_set_decl_spec_type): Refine test for ! redefinition of built-in types. ! ! 2004-06-27 Gabriel Dos Reis ! ! * error.c (pp_template_argument_list_start): Remove. ! (pp_template_argument_list_end): Likewise. ! (pp_separate_with_comma): Use pp_cxx_separate_with. ! (reinit_global_formatting_buffer): Remove. ! (pp_non_consecutive_character): Likewise. ! (dump_scope): Use pp_cxx_colon_colon. ! (dump_template_parameter): Use pp_cxx_identifier, ! pp_cxx_tree_identifier and pp_cxx_whitespace. ! (dump_templat_bindings): Replace use of pp_string with sequence ! of pp_cxx_whitespace and pp_equal. ! (dump_type): Use pp_cxx_identifier, pp_cxx_tree_identifier, ! pp_cxx_colon_colon, pp_cxx_whitespace throughout. Don't set ! padding here. ! (dump_aggr_type): Use pp_cxx_identifier amd pp_cxx_tree_identifier. ! (dump_type_prefix): Don't set padding. Use pp_cxx_whitespace, ! pp_cxx_left_parent, pp_cxx_colon_colon and pp_cxx_star troughout. ! (dump_type_suffix): Use pp_cxx_right_paren, pp_cxx_left_bracket, ! pp_cxx_right_bracket, pp_cxx_identifier throughout, ! (dump_decl): Likewise. ! (dump_template_decl): Likewise. ! (dump_function_decl): Likewise. Set padding as appropriate. ! (dump_parameters): Use pp_cxx_left_paren, pp_cxx_identifier and ! pp_cxx_right_paren. ! (dump_exception_spec): Likewise. ! (dump_function_name): Use pp_cxx_tree_identifier and ! pp_cxx_identifier. ! (dump_template_parms): Use pp_cxx_begin_template_argument_list and ! pp_cxx_end_template_argument_list. ! (dump_expr): Use pp_cxx_left_paren, pp_cxx_right_paren, ! pp_cxx_colon_colon, pp_cxx_identifier, pp_cxx_tree_identifier and ! pp_cxx_whitespace throughout. ! (dump_binary_op): Use pp_cxx_whitespace, pp_cxx_left_paren and ! pp_cxx_right_paren. ! (dump_unary_op): Likewise. ! (reinit_cxx_pp): New function. ! (type_as_string); Use it. ! (expr_as_string): Likewise. ! (decl_as_string); Likewise. ! (context_as_string): Likewise. ! (lang_decl_name): Likewise. ! (decl_to_string): Likewise. ! (expr_to_string): Likewise. ! (parm_to_string): Likewise. ! (type_to_string): Likewise. ! (args_to_string): Likewise. ! (cv_to_string): Likewise. ! ! 2004-06-26 Mark Mitchell ! ! * cp-tree.h (cp_cv_quals): New type. ! (cp_declarator): Use it instead of "tree" as appropriate. ! (grok_method_quals): Adjust prototype. ! (grokclassfn): Likewise. ! (do_friend): Likewise. ! * decl.c (grokfndecl): Use cp_cv_quals, not tree. ! (grokdeclarator): Likewise. ! * decl2.c (grok_method_quals): Likewise. ! (grokclassfn): Likewise. ! * friend.c (do_friend): Likewise. ! * method.c (implicitly_declare_fn): Adjust call to grokclassfn. ! * parser.c (make_call_declarator): Use cp_cv_quals, not tree. ! (make_pointer_declarator): Likewise. ! (make_reference_declarator): Likewise. ! (make_ptrmem_declarator): Likewise. ! (cp_parser_ptr_operator): Likewise. ! (cp_parser_cv_qualifier_seq_opt): Likewise. ! (cp_parser_cv_qualifier_opt): Remove. ! (cp_parser_new_declarator_opt): Adjust call to ! cp_parser_ptr_operator. ! (cp_parser_conversion_declaration_opt): Likewise. ! (cp_parser_declarator): Use cp_cv_quals, not tree. ! (cp_parser_direct_declarator): Likewise. ! ! 2004-06-26 Richard Kenner ! ! * call.c, cp-tree.h, cxx-pretty-print.c, decl.c, decl2.c: ! Rename DECL_STMT to DECL_EXPR. ! * init.c, name-lookup.c, parser.c, pt.c, semantics.c: Likewise. ! * cp-lang.c (LANG_HOOKS_SAFE_FROM_P): Deleted. ! * tree.c (cp_walk_subtrees): Don't call c_walk_subtrees. ! ! 2004-06-26 Jan Hubicka PR C++/14865 * decl2.c (maybe_emit_vtables): Always import_export_vtable for the reachability analysis. ! 2004-06-25 Mark Mitchell ! * cp-mudflap.c (mflang_flush_calls): Fix thinkos resulting from ! 2004-06-23 change. ! 2004-06-25 Paul Brook ! * decl2.c (get_guard): Call targetm.cxx.guard_type. ! (get_guard_bits, get_guard_cond): Call targetm.cxx.guard_mask_bit. ! 2004-06-24 Mark Mitchell ! ! * decl.c (grokdeclarator): Restore error messages about __thread. ! * parser.c (cp_parser_decl_specifier_seq): Likewise. ! ! 2004-06-24 Jason Merrill ! ! PR c++/16115 ! * decl.c (grokparms): Give the PARM_DECL reference type if the ! parameter is passed by invisible reference. ! ! 2004-06-24 Andreas Schwab ! ! * cp-tree.h (enum cp_storage_class): Remove trailing comma. ! ! 2004-06-23 Mark Mitchell ! ! * Make-lang.in (cp/lex.o): Do not depend on cp/lex.h. ! (cp/decl.o): Likewise. ! (cp/decl2.o): Likewise. ! (cp/pt.o): Likewise. ! (cp/semantics.o): Likewise. ! * config-lang.in (gtfiles): Do not reference cp/lex.h. ! * class.c: Do not include lex.h. ! (add_implicitly_declared_members): Do not use ! adding_implicit_members. ! (check_bases_and_members): Do not talk about grok_x_components. ! * cp/cp-tree.h (adding_implicit_members): Remove. ! (cp_storage_class): New type. ! (cp_decl_spec): Likewise. ! (cp_decl_specifier_seq): Likewise. ! (cp_parameter_declarator): Use it for the decl_specifiers field. ! (check_tag_decl): Adjust prototype. ! (shadow_tag): Likewise. ! (groktypename): Likewise. ! (start_decl): Likewise. ! (start_function): Likewise. ! (start_method): Likewise. ! (grok_x_components): Remove. ! (grokfield): Adjust prototype. ! (grokbitfield): Likewise. ! (finish_member_class_template): Remove. ! * decl.c: Do not include lex.h. ! (adding_implicit_members): Do not define. ! (check_tag_decl): Do not use trees to represent decl-specifiers. ! (shadow_tag): Likewise. ! (groktypename): Likewise. ! (start_decl): Likewise. ! (grokvardecl): Likewise. ! (grokdeclarator): Likewise. ! (grokparms): Likewise. ! (start_function): Likewise. ! (start_method): Likewise. ! * decl.h (grokdeclarator): Adjust prototype. ! * decl2.c: Do not include lex.h. ! (grok_x_components): Remove. ! (grokfield): Do not use trees to represent decl-specifiers. ! (grokbitfield): Likewise. ! * lex.c: Do not include lex.h. ! * lex.h: Remove. ! * parser.c: Include target.h. ! (clear_decl_specs): New function. ! (cp_parser_translation_unit): Do not use trees to represent ! decl-specifiers. ! (cp_parser_postfix_expression): Likewise. ! (cp_parser_new_type_id): Likewise. ! (cp_parser_condition): Likewise. ! (cp_parser_simple_declaration): Likewise. ! (cp_parser_decl_specifier_seq): Likewise. ! (cp_parser_function_specifier_opt): Likewise. ! (cp_parser_conversion_type_id): Likewise. ! (cp_parser_template_parameter): Likewise. ! (cp_parser_explicit_instantiation): Likewise. ! (cp_parser_type_specifier): Likewise. ! (cp_parser_simple_type_specifier): Likewise. ! (cp_parser_init_declarator): Likewise. ! (cp_parser_type_id): Likewise. ! (cp_parser_type_specifier_seq): Likewise. ! (cp_parser_parameter_declaration): Likewise. ! (cp_parser_member_declaration): Likewise. ! (cp_parser_exception_declaration): Likewise. ! (cp_parser_function_definition_from_specifiers_and_declarator): ! Likewise. ! (cp_parser_single_declaration): Likewise. ! (cp_parser_save_member_function_body): Likewise. ! (cp_parser_friend_p): Likewise. ! (cp_parser_set_storage_class): New function. ! (cp_parser_set_decl_spec_type): Likewise. ! * pt.c: Do not include lex.h. ! * semantics.c: Likewise. ! (finish_member_class_template): Remove. ! ! 2004-06-23 Roger Sayle ! ! * call.c (build_cxx_call): Don't call expand_tree_builtin. No ! longer take both "args" and "convert_args" as arguments. ! (build_op_delete_call): Update call to build_cxx_call. ! (build_over_call): Likewise, update call to build_cxx_call. ! * cp-tree.h (build_cxx_call): Update funtion prototype. ! * typeck.c (build_function_call): Don't call expand_tree_builtin. ! * rtti.c (throw_bad_cast): Update call to build_cxx_call. ! (throw_bad_typeid): Likewise. ! (build_dynamic_cast_1): Likewise. ! ! 2004-06-22 Richard Henderson ! ! * class.c (build_vfn_ref): Take a pointer not object. Build ! an OBJ_TYPE_REF. ! (cp_fold_obj_type_ref): New. ! * call.c (build_over_call): Update build_vfn_ref call. ! * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New. ! * cp-tree.h (cp_fold_obj_type_ref): Declare. ! ! 2004-06-21 Jason Merrill ! ! PR c++/16112 ! * cp-gimplify.c (cp_gimplify_init_expr): Look through ! CLEANUP_POINT_EXPR. ! ! 2004-06-21 Mark Mitchell ! ! * cp-tree.def (NEW_EXPR): Add a fourth slot. ! * cp-tree.h (PARMLIST_ELLIPSIS_P): Remove. ! (TREE_PARMLIST): Likewise. ! (CALL_DECLARATOR_PARMS): Likewise. ! (CALL_DECLARATOR_QUALS): Likewise. ! (CALL_DECLARATOR_EXCEPTION_SPEC): Likewise. ! (cp_declarator_kind): New type. ! (cp_parameter_declarator): Likewise. ! (cp_declarator): Likewise. ! (cp_error_declarator): Likewise. ! (no_parameters): Likewise. ! (groktypename): Change prototype. ! (start_decl): Likewise. ! (start_handler_parms): Likewise. ! (get_scope_of_declarator): Likewise. ! (start_function): Likewise. ! (start_preparsed_function): New function. ! (start_function): Change prototype. ! (start_method): Likewise. ! (grokfield): Likewise. ! (grokbitfield): Likewise. ! (build_new): Likewise. ! (make_pointer_declarator): Remove. ! (make_reference_declarator): Likewise. ! (make_call_declarator): Likewise. ! (set_quals_and_spec): Likewise. ! (process_template_parm): Change prototype. ! (begin_function_definition): Remove. ! (finish_parmlist): Remove. ! * decl.c (groktypename): Do not use trees to represent ! declarators. ! (start_decl): Likewise. ! (start_handler_parms): Remove. ! (get_scope_of_declarator): Reimplement. ! (grokdeclarator): Do not use trees to represent declarators. ! (grokparms): Likewise. ! (start_function): Likewise. ! (start_method): Likewise. ! (build_void_list_mode): Do not use TREE_PARMLIST. ! * decl.h (grokdeclarator): Change prototype. ! * decl2.c (grok_method_quals): Robustify. ! (grok_x_components): Do not use trees to represent declarators. ! (grokfield): Likewise. ! (grokbitfield): Likewise. ! (start_objects): Build FUNCTION_DECLs, not declarators. ! (start_static_storage_duration_function): Likewise. ! * init.c (build_new): Simplify. ! * lex.c (make_pointer_declarator): Remove. ! (make_reference_declarator): Likewise. ! (make_call_declarator): Likewise. ! (set_quals_and_spec): Likewise. ! * method.c (use_thunk): Use start_preparsed_function. ! (synthesize_method): Likewise. ! (implicitly_declare_fn): Build FUNCTION_DECLs, not declarators. ! * optimize.c (maybe_clone_body): Use start_preparsed_function. ! * parser.c (cp_error_declarator): New variable. ! (declarator_obstack): Likewise. ! (alloc_declarator): New function. ! (make_declarator): Likewise. ! (make_id_declarator): Likewise. ! (make_pointer_declarator): Likewise. ! (make_reference_declarator): Likewise. ! (make_ptrmem_declarator): Likewise. ! (make_call_declarator): Likewise. ! (make_array_declarator): Likewise. ! (no_parameters): New variable. ! (make_parameter_declarator): Likewise. ! (cp_parser_check_for_definition_in_return_type): Do not use trees ! to represent declarators. ! (cp_parser_translation_unit): Likewise. ! (cp_parser_new_expression): Likewise. ! (cp_parser_new_type_id): Likewise. ! (cp_parser_new_declarator_opt): Likewise. ! (cp_parser_direct_new_declarator): Likewise. ! (cp_parser_condition): Likewise. ! (cp_parser_declaration_statement): Likewise. ! (cp_parser_declaration): Likewise. ! (cp_parser_conversion_type_id): Likewise. ! (cp_parser_conversion_declarator_opt): Likewise. ! (cp_parser_template_parameter_list): Likewise. ! (cp_parser_template_parameter): Likewise. ! (cp_parser_explicit_instantiation): Likewise. ! (cp_parser_init_declarator): Likewise. ! (cp_parser_declarator): Likewise. ! (cp_parser_direct_declarator): Likewise. ! (cp_parser_type_id): Likewise. ! (cp_parser_parameter_declaration_clause): Likewise. ! (cp_parser_parameter_declaration_list): Likewise. ! (cp_parser_parameter_declaration): Likewise. ! (cp_parser_member_declaration): Likewise. ! (cp_parser_exception_declaration): Likewise. ! (cp_parser_check_declarator_template_parameters): Likewise. ! (cp_parser_function_definition_from_specifiers_and_declarator): ! Likewise. ! (cp_parser_save_member_function_body): Likewise. ! * pt.c (process_template_parm): Add is_non_type parameter. ! (convert_template_argument): Adjust call to groktypename. ! (tsubst_call_declarator_parms): Remove use of TREE_PARMLIST. ! (tsubst): Do not expect declarators. ! (tsubst_copy_and_build): Adjust NEW_EXPR case to handle additional ! argument. ! (instantiate_decl): Use start_preparsed_function. ! * semantics.c (begin_function_definition): Remove. ! (finish_parmlist): Remove. ! * cp-mudflap.c (mflang_flush_calls): Build FUNCTION_DECLs, not ! declarators. ! ! 2004-06-21 Richard Kenner ! ! * call.c (build_vfield_ref): Add new operand for COMPONENT_REF. ! (build_new_method_call): Likewise. ! * decl.c (local_variable_p_walkfn): Don't walk into types. ! * decl2.c (grok_array_decl): Add new operands for ARRAY_REF. ! (build_anon_union_vars): Add new operand for COMPONENT_REF. ! * init.c (buld_new): Add new operand for ARRAY_REF. ! * method.c (do_build_copy_constructor): New op for COMPONENT_REF. ! (do_build_assign_ref): Likewise. ! * parser.c (cp_parser_direct_new_declarator): Add new operands ! for ARRAY_REF. ! (cp_parser_direct_declarator): Likewise. ! * pt.c (tsubst): Likewise. ! (tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand ! for COMPONENT_REF. ! * semantics.c (finish_non_static_data_member): Add new operand ! for COMPONENT_REF. ! * typeck.c (build_class_member_access_expr): Likewise. ! (build_class_member_access_expr, finish_class_member_access_expr): ! Likewise. ! (build_ptrmemfunc_access_expr): Likewise. ! (build_array_ref): Add new operands for ARRAY_REF. ! * typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too. ! * tree.c (count_trees_r, no_linkage_helper): Don't walk in types. ! ! 2004-06-21 Richard Henderson ! ! * dump.c (cp_dump_tree): Don't use dump_next_stmt. ! * parser.c (cp_parser_jump_statement): Update commentary. ! * pt.c (tsubst_expr): Use RETURN_EXPR. ! * semantics.c (finish_return_stmt): Likewise. ! (finalize_nrv_r): Likewise. ! * typeck.c, typeck2.c: Update file start commentary. ! ! 2004-06-21 Richard Henderson ! ! * semantics.c (finish_expr_stmt): Call verify_sequence_points. ! ! 2004-06-20 Richard Henderson ! ! * cp-tree.h (add_decl_stmt): Declare. ! * pt.c (tsubst_copy): Abort for CLEANUP_POINT_EXPR. ! * semantics.c (maybe_cleanup_point_expr): New. ! (add_decl_stmt, finish_expr_stmt, finish_return_stmt, ! finish_for_expr, finish_switch_cond): Use it. ! (finalize_nrv_r): Don't build an EXPR_STMT. Don't frob TREE_CHAIN. ! ! 2004-06-20 Richard Henderson ! ! * cp-tree.def (CLEANUP_STMT, IF_STMT): Move from c-common.def. ! * cp-gimplify.c (gimplify_if_stmt): Move from c-gimplify.c. ! (cp_gimplify_expr): Call it. ! (gimplify_cleanup_stmt): Move from c-gimplify.c. ! (cp_genericize): New. ! * decl.c (finish_function): Call it. ! * cp-tree.h (cp_stmt_codes): Add CLEANUP_STMT, IF_STMT. ! (CLEANUP_BODY, CLEANUP_EXPR, CLEANUP_DECL): Move from c-common.h. ! (IF_COND, THEN_CLAUSE, ELSE_CLAUSE): Likewise. ! (cp_genericize): Declare. ! * cxx-pretty-print.c (pp_cxx_statement): Add CLEANUP_STMT, IF_STMT. ! * dump.c (cp_dump_tree): Likewise. ! * semantics.c (push_cleanup): Move from c-semantics.c. ! ! 2004-06-20 Zack Weinberg ! ! * cp-lang.c (has_c_linkage): Implement. ! ! * cp-tree.h (set_mangled_name_for_decl): Don't prototype. ! * decl.c (duplicate_decls): Use COPY_DECL_RTL. ! (builtin_function_1): Don't call make_decl_rtl. ! (build_cp_library_fn): Don't call set_mangled_name_for_decl. ! (grokvardecl): Don't call mangle_decl. ! * except.c (nothrow_libfn_p): Look at DECL_NAME, not ! DECL_ASSEMBLER_NAME. ! * method.c (set_mangled_name_for_decl): Delete. ! * name-lookup.c (pushdecl): When a local extern shadows a ! file-scope declaration of the same object, give both DECLs the ! same DECL_UID. ! * typeck.c (cxx_mark_addressable): Don't set TREE_ADDRESSABLE ! on DECL_ASSEMBLER_NAME. ! ! 2004-06-19 Richard Henderson ! ! * cp-gimplify.c: Remove unnecessary prototypes. ! (cp_gimplify_stmt): Merge into ... ! (cp_gimplify_expr): ... here. Move to end of file. Handle ! stmts_are_full_exprs_p frobbing. ! * cp-tree.h (cp_gimplify_stmt): Remove. ! * pt.c (tsubst_expr): Merge prep_stmt and unify. ! * tree.c (init_tree): Don't set lang_gimplify_stmt. ! ! 2004-06-18 Richard Henderson ! ! PR c++/16034 ! * semantics.c (begin_cond): New. ! (finish_cond): Rewrite to handle template DECL_STMTs specially. ! Assume that non-template decls go land before the conditional. ! (simplify_loop_decl_cond): Likewise. ! (begin_if_stmt, finish_if_stmt_cond, begin_while_stmt, ! finish_while_stmt_cond, finish_for_init_stmt, finish_for_cond, ! begin_switch_stmt, finish_switch_cond): Update to match. ! ! 2004-06-17 Jason Merrill ! ! PR c++/16015 ! * semantics.c (simplify_aggr_init_expr): Don't return the slot. ! (finish_stmt_expr_expr): Update type after conversions. ! (finish_stmt_expr): Wrap initializer in CLEANUP_POINT_EXPR. ! Handle void initializer. ! * tree.c (build_cplus_new): Make AGGR_INIT_EXPRs void. ! ! 2004-06-17 Geoffrey Keating ! ! * class.c (build_clone): Don't call defer_fn, let mark_used do it. ! * cp-tree.h (defer_fn): Delete. ! * decl2.c (defer_fn): Delete. ! (finish_file): Simplify deferred_fns loops; check that ! only used inline functions get into deferred_fns. ! (mark_used): Inline previous contents of defer_fn. ! ! 2004-06-16 Richard Henderson ! ! * cp-tree.h (COMPOUND_STMT_TRY_BLOCK, COMPOUND_STMT_BODY_BLOCK): Kill. ! (BIND_EXPR_TRY_BLOCK, BIND_EXPR_BODY_BLOCK): New. ! * cxx-pretty-print.c (pp_cxx_function_definition): Move handling ! of CTOR_INITIALIZER ... ! (pp_cxx_statement): ... here. ! * decl.c (begin_function_body): Don't set COMPOUND_STMT_BODY_BLOCK. ! (finish_function): Use alloc_stmt_list to zap entire function. ! * parser.c (cp_parser_compound_statement): Update commentary. ! * pt.c (tsubst_expr): Use BIND_EXPR instead of COMPOUND_STMT. ! * semantics.c (begin_compound_stmt, finish_compound_stmt): Likewise. ! (finish_stmt_expr): Don't look through COMPOUND_STMT. ! ! 2004-06-16 Geoffrey Keating ! ! * pt.c (mark_decl_instantiated): Don't call defer_fn. ! ! 2004-06-16 Richard Henderson ! ! * parser.c (cp_parser_labeled_statement): Update commentary. ! * pt.c (tsubst_expr): Use CASE_LABEL_EXPR. ! * tree.c (mark_local_for_remap_r): Likewise. ! ! 2004-06-16 Richard Henderson ! ! * parser.c (cp_parser_asm_definition): Update commentary. ! * pt.c (tsubst_expr): Use ASM_EXPR. ! * semantics.c (finish_asm_stmt): Likewise. ! ! 2004-06-16 Richard Henderson ! ! * decl.c (finish_destructor_body): Use LABEL_EXPR. ! * parser.c (cp_parser_statement): Update commentary. ! * pt.c (tsubst_expr): Use LABEL_EXPR, GOTO_EXPR. ! * semantics.c (finish_goto_stmt, finish_label_stmt): Likewise. ! * tree.c (mark_local_for_remap_r): Likewise. ! ! 2004-06-16 Richard Henderson ! ! PR c++/16012 ! * semantics.c (begin_for_stmt, begin_for_stmt): Do put the init ! statement in FOR_INIT_STMT for templates. ! ! 2004-06-15 Richard Henderson ! ! * call.c (initialize_reference): Don't build CLEANUP_STMT here. ! * cp-gimplify.c (cp_gimplify_stmt): Remove next_p argument. ! (genericize_try_block): Use gimplify_stmt. ! (genericize_catch_block, genericize_eh_spec_block): Likewise. ! (cp_gimplify_init_expr): Remove STMT_EXPR special case. ! (gimplify_must_not_throw_expr): Update voidify_wrapper_expr call. ! * cp-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P): Remove. ! (cp_tree_chain_matters_p): Remove. ! * cp-tree.h (COMPOUND_STMT_TRY_BLOCK): New. ! (COMPOUND_STMT_BODY_BLOCK): New. ! (STATEMENT_LIST_NO_SCOPE, STATEMENT_LIST_TRY_BLOCK): New. ! (EXPR_STMT_STMT_EXPR_RESULT): New. ! (building_stmt_tree): Check cur_stmt_list. ! (tf_stmt_expr_cmpd, tf_stmt_expr_body): Remove. ! (BCS_NO_SCOPE, BCS_TRY_BLOCK, BCS_FN_BODY): New. ! * decl.c (poplevel): Use pop_stmt_list for minding cleanups. ! (cp_finish_decl): Use push_cleanup. ! (start_function, finish_function): Use statement lists. ! (finish_stmt): Do nothing. ! * except.c (begin_eh_spec_block): Use statement lists. ! (check_handlers_1, check_handlers): Likewise. ! * init.c (construct_virtual_base): Don't add extra compound stmts. ! (build_vec_init): Likewise. ! * name-lookup.c (maybe_push_cleanup_level): Use statement lists. ! * name-lookup.h (struct cp_binding_level): Add statement_list. ! * parser.c (cp_parser_statement): Take the STMT_EXPR node, not a bool. ! (cp_parser_labeled_statement, cp_parser_expression_statement, ! cp_parser_statement_seq_opt): Likewise. ! (cp_parser_compound_statement): Likewise. Take bool for try block. ! (cp_parser_selection_statement): Tidy if processing. ! (cp_parser_already_scoped_statement): Rewrite to do what it says. ! * pt.c (tsubst_copy): Move STMT_EXPR to tsubst_expr. ! (tsubst_expr): Rewrite STMT_EXPR processing. Handle STATEMENT_LIST. ! Mind COMPOUND_STMT_TRY_BLOCK, EXPR_STMT_STMT_EXPR_RESULT. ! * semantics.c (do_poplevel, do_pushlevel): Use statement lists. ! (finish_cond): New, rewritten from FINISH_COND. ! (simplify_loop_decl_cond): New. ! (finish_expr_stmt): Avoid nested EXPR_STMTs. ! (begin_if_stmt, finish_if_stmt_cond, finish_then_clause, ! begin_else_clause, finish_else_clause, finish_if_stmt, ! begin_while_stmt, finish_while_stmt_cond, finish_while_stmt, ! begin_do_stmt, finish_do_body, begin_for_stmt, finish_for_init_stmt, ! finish_for_cond, finish_for_stmt, begin_switch_stmt, ! finish_switch_cond, finish_switch_stmt, begin_try_block, ! finish_try_block, finish_cleanup_try_block, finish_function_try_block, ! finish_handler_sequence, finish_function_handler_sequence, ! begin_handler, finish_handler_parms, finish_handler, ! begin_stmt_expr, finish_stmt_expr_expr, finish_stmt_expr): Rewrite ! using statement lists. ! (begin_compound_stmt): Replace has_no_scope argument with flags. ! Update all callers. Use statement lists. ! (finish_compound_stmt): Likewise. ! (finish_decl_cleanup, finish_eh_cleanup): Use push_cleanup. ! (current_scope_stmt_stack): Remove. ! (simplify_aggr_init_expr): Don't muck with TREE_CHAIN. ! * typeck2.c (split_nonconstant_init_1, split_nonconstant_init): ! Rewrite with statement lists. ! ! 2004-06-15 Alexandre Oliva ! ! * parser.c: Change all assignments of c_lex_string_translate ! to true and false to 1 and 0. ! (cp_lexer_read_token): Convert type of the translated string. ! (cp_parser_skip_to_closing_parentheses): Preserve original ! value of c_lex_string_translate, and set it to -1 while ! running. ! (cp_parser_cache_group): Likewise. ! (cp_parser_cache_group_1): Renamed. ! (cp_parser_asm_operand_list): Remove redundant setting of ! c_lex_string_translate. ! (cp_parser_primary_expression) [CPP_STRING, CPP_WSTRING]: ! Handle chained strings. ! ! 2004-06-12 Andrew Pinski ! ! PR c++/14639 ! Revert: ! 2004-06-02 Andrew Pinski ! ! * cp-tree.h: Fix typo. ! ! * cp-tree.h: Include cgraph.h ! (DECL_NEEDED_P): Use cgraph_*node on the decl instead of ! TREE_SYMBOL_REFERENCED on the DECL_ASSEMBLER_NAME of the decl. ! ! 2004-06-12 Jason Merrill ! ! PR tree-optimization/14107 ! * decl.c (finish_function): Warn about no return in all functions. ! ! 2004-06-15 Paolo Bonzini ! ! * cp-tree.h (struct language_function): Remove cannot_inline. ! * decl.c (save_function_data): cannot_inline is no more. ! (cxx_push_function_context): Likewise. ! * decl2.c (start_objects, start_static_storage_duration_function): ! Reset DECL_INLINE, set DECL_UNINLINABLE. ! ! 2004-06-14 Giovanni Bajo PR c++/15967 ! * search.c (lookup_field): Propagate the ambiguity list. ! (lookup_fnfields): Likewise. 2004-06-14 Giovanni Bajo *************** *** 413,424 **** * name-lookup.c (pushtag): Do not try to put class declarations in explicit specialization scopes. ! i2004-06-11 Mark Mitchell PR c++/15862 * name-lookup.c (unqualified_namespace_lookup): Do not ignore type bindings for undeclared built-ins. 2004-06-10 Jason Merrill PR c++/15875 --- 5766,5786 ---- * name-lookup.c (pushtag): Do not try to put class declarations in explicit specialization scopes. ! 2004-06-11 Andrew Pinski ! ! * decl.c (grokdeclarator): Do not depend on C99's _Bool's behavior. ! ! 2004-06-11 Mark Mitchell PR c++/15862 * name-lookup.c (unqualified_namespace_lookup): Do not ignore type bindings for undeclared built-ins. + 2004-06-11 Giovanni Bajo + + * typeck2.c (abstract_virtual_errors): Reword diagnostics, make them + appear at the correct location. + 2004-06-10 Jason Merrill PR c++/15875 *************** i2004-06-11 Mark Mitchell + + PR c++/14791 + * decl.c (duplicate_decls): Handle fileptr_type_node arguments + specially. + 2004-06-09 Mark Mitchell Revert: *************** i2004-06-11 Mark Mitchell ! PR c++/14808 ! * method.c (make_alias_for_thunk, use_thunk): Use TARGET_IS_PE_COFF ! instead of __CYWGIN__ and __MINGW32__. 2004-06-07 Mark Mitchell --- 5822,5837 ---- * lex.c (handle_pragma_interface): Deprecate. (handle_pragma_implementation): Likewise. ! 2004-06-09 Andrew Pinski ! * g++spec.c (lang_specific_driver): Remove check for -lm ! and -lmath when check it see if it was the math library. ! ! 2004-06-08 Giovanni Bajo ! ! PR c++/7841 ! * parser.c (cp_parser_direct_declarator): Reject constructor named ! as qualified template-id. 2004-06-07 Mark Mitchell *************** i2004-06-11 Mark Mitchell + PR c++/15766 * parser.c (cp_parser_iteration_statement): Fix typo in error message. *************** i2004-06-11 Mark Mitchell PR c++/15503 * parser.c (cp_parser_mem_initializer_id): Gracefully reject 'typename', and accept 'template'. 2004-06-01 Jason Merrill PR c++/15142 --- 5851,5912 ---- PR c++/15554 * pt.c (tsubst_copy): Do not try to substitute for an enumeration ! constant in a non-dependent context. ! PR c++/15057 * except.c (build_throw): Ensure that temp_expr has been initialized. + 2004-06-06 Roger Sayle + + * cp/cp-tree.h (lvalue_or_else): Add function prototype. + 2004-06-06 Giovanni Bajo PR c++/15503 * parser.c (cp_parser_mem_initializer_id): Gracefully reject 'typename', and accept 'template'. + 2004-06-03 Andrew Pinski + Jan Hubicka + + PR c++/14639 + * method.c (use_think): Do not mark thunk as referenced. + + 2004-06-03 Matt Austern + + PR c++/15428 + * decl2.c (maybe_emit_vtables): If TARGET_WEAK_NOT_IN_ARCHIVE_TOC + is nonzero, and if we see a noninline definition of a key method, + make the vtables nonweak. + + 2004-06-02 Matt Austern + + * cp-tree.h (instantiate_decl): new boolean parameter, + undefined_ok. Current behavior is equivalent to its being 0. + * decl2.c (mark_used): Add new argument when calling instantiate_decl + * pt.c (mark_decl_instantiated): Unconditionally make + instantiations explicit unconditionally + (do_decl_instantiation): Don't call SET_DECL_EXPLICIT_INSTANTIATION, + since mark_decl_instantiated now does it. + (instantiate_class_member): New. Instantiate a member of an + explicitly instantiated class template. + (do_type_instantiation): Explicitly instantiate members of an + explicitly instantiated class template. + (instantiate_decl): if undefined_ok is nonzero, and if we're + trying to explicitly instantiated a template with no definition, + change it to an implicit instantiation. + (instantiate_pending_templates): Add new argument to instantiate_decl. + * tree.c (cp_cannot_inline_tree_fn): Likewise. + + 2004-06-02 Andrew Pinski + + * cp-tree.h: Fix typo. + + * cp-tree.h: Include cgraph.h + (DECL_NEEDED_P): Use cgraph_*node on the decl instead of + TREE_SYMBOL_REFERENCED on the DECL_ASSEMBLER_NAME of the decl. + 2004-06-01 Jason Merrill PR c++/15142 *************** i2004-06-11 Mark Mitchell : Use pp_expression. (dump_expr) : Likewise. + 2004-06-01 Richard Henderson + Andrew Pinski + + * lex.c (reswords): Rename "__offsetof" to "__builtin_offsetof". + * parser.c (struct cp_parser): Remove in_offsetof. + (cp_parser_new): Don't set it. + (cp_parser_unary_expression): Don't check it. + (cp_parser_postfix_open_square_expression): Split out from ... + (cp_parser_postfix_expression): ... here. + (cp_parser_postfix_dot_deref_expression): Likewise. + (cp_parser_builtin_offsetof): New. + (cp_parser_primary_expression): Use it. + 2004-06-01 Giovanni Bajo PR c++/14932 *************** i2004-06-11 Mark Mitchell --- 5950,6014 ---- * friend.c (add_friend): Do not try to perform access checks for functions from dependent classes. ! 2004-05-31 Gabriel Dos Reis ! * cxx-pretty-print.c (pp_cxx_colon_colon): Expor. ! (pp_cxx_begin_template_argument_list): Turn into a function. ! (pp_cxx_end_template_argument_list): Likewise. ! (pp_cxx_separate_with): Define. ! (pp_cxx_unqualified_id): Tidy. ! (pp_cxx_primary_expression): Likewise. ! (pp_cxx_postfix_expression): Likewise. ! (pp_cxx_expression): Likewise. ! (pp_cxx_simple_type_specifier): Likewise. ! (pp_cxx_type_specifier_seq): Likewise. ! (pp_cxx_parameter_declaration_clause): Likewise. ! (pp_cxx_exception_specification): Likewise. ! (pp_cxx_direct_declarator): Likewise. ! (pp_cxx_type_id): Likewise. ! * cxx-pretty-print.h (pp_cxx_whitespace): Export from ! cxx-pretty-print.c. ! (pp_cxx_left_paren): Likewise. ! (pp_cxx_right_paren): Likewise. ! (pp_cxx_left_brace): Likewise. ! (pp_cxx_right_brace): Likewise. ! (pp_cxx_left_bracket): Likewise. ! (pp_cxx_right_bracket): Likewise. ! (pp_cxx_dot): Likewise. ! (pp_cxx_identifier): Likewise. ! (pp_cxx_tree_identifier): Likewise. ! (pp_cxx_ampersand): New macro. ! (pp_cxx_star): Likewise. ! (pp_cxx_arrow): Likewise. ! (pp_cxx_semicolon): Likewise. ! (pp_cxx_complement): Likewise. ! (pp_cxx_begin_template_argument_list): Declaree. ! (pp_cxx_end_template_argument_list): Likewise. ! (pp_cxx_colon_colon): likewise. ! 2004-05-31 Eric Botcazou ! * parser.c (cp_parser_simple_type_specifier): Explicitly test ! against NULL_TREE. ! 2004-05-31 Kazu Hirata ! ! * call.c, class.c, cp-tree.def, decl2.c, name-lookup.c, pt.c, ! typeck.c: Fix comment formatting. ! ! 2004-05-30 Andrew Pinski ! ! * cp-lang.c (cp_expand_decl): Remove. ! (LANG_HOOKS_EXPAND_DECL): Use c_expand_decl. ! ! 2004-05-30 Andreas Jaeger ! ! * lang-specs.h: Add missing initializers for .ii. ! ! 2004-05-28 Aldy Hernandez ! ! * decl.c (cp_make_fname_decl): Free return value from ! fname_as_string. 2004-05-28 Mark Mitchell *************** i2004-06-11 Mark Mitchell + PR c++/14668 * parser.c (cp_parser_simple_type_specifier): Call maybe_note_name_used_in_class. + 2004-05-28 Tom Marshall + + PR c++/15214 + * class.c (finish_struct_1): Warn only if the dtor is non-private or + the class has friends. + + 2004-05-27 Adam Nemet + + PR c++/12883 + * decl.c (complete_array_type): Set TYPE_NEEDS_CONSTRUCTING and + TYPE_HAS_NONTRIVIAL_DESTRUCTOR based on the underlying type. + + 2004-05-24 Geoffrey Keating + + * method.c (implicitly_declare_fn): Don't call defer_fn; abort + if it might be needed. + * pt.c (mark_decl_instantiated): Only call defer_fn if + the function actually needs processing in finish_file. + * decl2.c (finish_file): Add check that elements in + deferred_fns_used are really needed there. Remove unnecessary + test of DECL_SAVED_TREE. + + 2004-05-23 Paolo Bonzini + + * Make-lang.in: No need to specify $(LIBCPP). + 2004-05-23 Mark Mitchell PR c++/15044 *************** i2004-06-11 Mark Mitchell + PR c++/15165 * pt.c (instantiate_template): Robustify. + 2004-05-23 Mark Mitchell + PR c++/15025 * decl.c (xref_tag): Issue errors about redeclaring template classes as non-template classes. + 2004-05-23 Mark Mitchell + PR c++/14821 * name-lookup.c (supplement_binding): Allow redefinitions of namespace aliases. *************** i2004-06-11 Mark Mitchell + + * class.c (alter_access): Use %E format specifier to print an + identifier node. Avoid looking at the IDENTIFIER_POINTER. + (push_lang_context): Likewise. + * decl.c (lookup_label): Likewise. + (grokdeclarator): Likewise. + * parser.c (cp_parser_check_for_invalid_template_id): Likewise. + * pt.c (do_type_instantiation): Likewise. + * tree.c (handle_java_interface_attribute): Likewise. + (handle_com_interface_attribute): Likewise. + (handle_init_priority_attribute): Likewise. + 2004-05-22 Mark Mitchell PR c++/15285 *************** i2004-06-11 Mark Mitchell + PR c++/15507 * class.c (layout_nonempty_base_or_field): Do not try to avoid layout conflicts for unions. *************** i2004-06-11 Mark Mitchell PR c++/15064 * parser.c (cp_parser_postfix_expression): typeid operator cannot be used in integral constant expressions. ! 2004-04-18 Release Manager ! * GCC 3.4.0 released. 2004-04-08 Danny Smith PR c++/14808 ! * method.c (make_alias_for_thunk): Just return function decl ! for one_only functions if __CYGWIN__ or __MINGW32__ ! (use_thunk): Don't put function and thunk in same one_only ! section if __CYGWIN__ or __MINGW32__. 2004-04-08 Jakub Jelinek * decl2.c (mark_used): Don't segfault if cfun != NULL but current_function_decl == NULL. 2004-04-01 Mark Mitchell PR c++/14803 --- 6132,6316 ---- * typeck.c (build_unary_op): Do not optimize "&x[y]" when in a template. + 2004-05-22 Roger Sayle + + * name-lookup.c (check_for_out_of_scope_variable): Avoid ICE by + returning when TREE_TYPE is error_mark_node. + * typeck.c (require_complete_type): Return error_mark_node if + value's type is an error_mark_node. + + 2004-05-20 Andrew Pinski + + * optimize.c (calls_setjmp_r): Remove. + (calls_setjmp_p): Remove. + * cp-tree.c (calls_setjmp_p): Remove. + * decl.c (finish_function): Do not call calls_setjmp_p. + + 2004-05-18 Zack Weinberg + + * decl.c (cp_finish_decl): Use mark_decl_referenced. + * decl2.c (maybe_make_one_only): Likewise. + * method.c (use_thunk): Likewise. + + 2004-05-18 Jason Merrill + + * class.c (build_base_path): Tidy a bit. + + 2004-05-14 Geoffrey Keating + + * name-lookup.c (struct scope_binding): New. + (EMPTY_SCOPE_BINDING): New. + (lookup_using_namespace): Take a scope_binding instead of a + cxx_binding. + (qualified_lookup_using_namespace): Likewise. + (cxx_binding_clear): Delete. + (do_nonmember_using_decl): Use a scope_binding instead of a + cxx_binding. + (lookup_tag): Don't call select_decl. + (ambiguous_decl): Don't return anything (and change callers to match). + Take a scope_binding as the second parameter. + (lookup_namespace_name): Use a scope_binding instead of a + cxx_binding. + (unqualified_namespace_lookup): Likewise. + (lookup_qualified_name): Likewise. + (select_decl): Take a scope_binding instead of a cxx_binding. + Use macros rather than hand-coding tests for type-ness. + + 2004-05-13 Diego Novillo + + * cp-gimplify.c: Rename from cp-simplify.c. + * Make-lang.in, optimize.c: Update. + + 2004-05-13 Diego Novillo + + Merge from tree-ssa-20020619-branch. See + ChangeLog.tree-ssa for details. + + * Make-lang.in, call.c, class.c, cp-lang.c, cp-tree.def, + cp-tree.h, cvt.c, decl.c, decl2.c, error.c, except.c, + expr.c, init.c, name-lookup.h, optimize.c, parser.c, + pt.c, rtti.c, semantics.c, tree.c, typeck.c, typeck2.c: + Merged. + * cp-mudflap.c: New file. + * cp-simplify.c:: New file. + + 2004-05-03 Giovanni Bajo + + PR c++/14389 + * decl2.c (check_classfn): For member templates, compare also the + template parameters to match the declaration. + * cp-tree.h: Adjust declaration of check_classfn. + * decl.c (start_decl, grokfndecl): Adjust callers of check_classfn. + * friend.c (do_friend): Likewise. + * pt.c (tsubst_friend_function): Likewise. + + 2004-05-01 Zack Weinberg + + * decl.c (reshape_init): Do not apply TYPE_DOMAIN to a VECTOR_TYPE. + Instead, dig into the representation type to find the array bound. + + 2004-04-30 Jason Merrill + + Refer to base members using COMPONENT_REFs where possible. + * class.c (build_simple_base_path): New fn. + (build_base_path): Use it for non-virtual base references. + (layout_class_type): Change base fields to their real type + after layout is done. + * cp-tree.h (IS_FAKE_BASE_TYPE): New macro. + * cp-lang.c (cxx_get_alias_set): Use it. + + 2004-04-30 Kazu Hirata + + * class.c, cp-tree.h, decl.c, decl2.c, pt.c, rtti.c: Fix + comment typos. + 2004-04-23 Giovanni Bajo PR c++/15064 * parser.c (cp_parser_postfix_expression): typeid operator cannot be used in integral constant expressions. ! 2004-04-22 Mark Mitchell ! * init.c (build_aggr_init): Fix accidental use of C99 construct in ! previous change. ! ! * class.c (initialize_array): Don't set TREE_HAS_CONSTRUCTOR on ! braced initializer. ! * cp-tree.h (BRACE_ENCLOSED_INITIALIZER_P): New macro. ! * decl.c (reshape_init): Use it. ! * init.c (perform_member_init): Remove redundant condition. ! (build_aggr_init): Adjust to handle brace-enclosed initializers ! correctly. ! (expand_default_init): Use BRACE_ENCLOSED_INITIALIZER_P. ! ! * parser.c (cp_parser_initializer_clause): Do not set ! TREE_HAS_CONSTRUCTOR on the initializer. ! * rtti.c (tinfo_base_init): Likewise. ! (generic_initializer): Likewise. ! (ptr_initializer): Likewise. ! (ptm_initializer): Likewise. ! (class_initializer): Likewise. ! (get_pseudo_ti_init): Likewise. ! * typeck2.c (digest_init): Use BRACE_ENCLOSED_INITIALIZER_P. ! ! 2004-04-22 Alan Modra ! ! * name-lookup.c (anonymous_namespace_name): Make static. ! ! 2004-04-19 Roger Sayle ! ! PR middle-end/14531 ! * class.c (build_base_path): Call fold whilst building the NULL ! pointer check expression trees. ! ! 2004-04-15 Bryce McKinlay ! ! * init.c (build_new_1): Don't use type size argument for Java ! _Jv_AllocObject call. ! ! 2004-04-09 Danny Smith ! ! * method.c (make_alias_for_thunk): Remove preprocessor guard on ! declaration and definition. 2004-04-08 Danny Smith PR c++/14808 ! * method.c (use_thunk): Test TARGET_USE_LOCAL_THUNK_ALIAS_P rather ! than ASM_OUTPUT_DEF. 2004-04-08 Jakub Jelinek * decl2.c (mark_used): Don't segfault if cfun != NULL but current_function_decl == NULL. + 2004-04-05 Nathan Sidwell + + PR c++/3518 + * pt.c (check_cv_quals_for_unify): Ignore bogus CV quals at outer + level. + + 2004-04-05 Richard Kenner + + * init.c (decl_constant_value): Don't look at DECL_INITIAL + of PARM_DECL. + * tree.c (bot_manip, build_min): Don't look at TREE_CONSTANT + or TREE_SIDE_EFFECTS of a type. + + 2004-04-02 Nathan Sidwell + + PR c++/14007 + * pt.c (check_cv_quals_for_unify): Correct logic for disallowed + cv-qualifier unification. + * tree.c (cp_build_qualified_type_real): Renable DR295 logic. + + 2004-04-02 Jan Hubicka + + * cp-lang. (LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): Define. + * cp-tree.h (cp_update_decl_after_saving): Declare. + * tree.c (cp_update_decl_after_saving): Define. + 2004-04-01 Mark Mitchell PR c++/14803 *************** i2004-06-11 Mark Mitchell ! PR c++/14804 ! * decl.c (cp_finish_decl): Preserve TREE_READONLY more often. ! * typeck2.c (split_nonconstant_init): Clear TREE_READONLY. 2004-04-01 Mark Mitchell PR c++/14810 * name-lookup.c (maybe_push_cleanup_level): Robustify. 2004-03-30 Mark Mitchell PR c++/14724 --- 6319,6354 ---- 2004-04-01 Richard Henderson ! PR c++/14804 ! * decl.c (cp_finish_decl): Preserve TREE_READONLY more often. ! * typeck2.c (split_nonconstant_init): Clear TREE_READONLY. 2004-04-01 Mark Mitchell PR c++/14810 * name-lookup.c (maybe_push_cleanup_level): Robustify. + 2004-04-01 Richard Kenner + + * class.c (VTT_TOP_LEVEL_P): Use unsigned_flag directly. + + 2004-03-31 Richard Kenner + + * call.c (joust): Use TYPE_UNSIGNED, not TREE_UNSIGNED. + * class.c (check_bitfield_decl): Likewise. + * cvt.c (type_promotes_to): Likewise. + * decl.c (finish_enum): Likewise. + * mangle.c (write_builtin_type): Likewise. + * semantics.c (finish_switch_cond, finish_unary_op_expr): Likewise. + * typeck.c (type_after_usual_arithmetic_conversions): Likewise. + (build_binary_op): Likewise. + + 2004-03-31 Jan Hubicka + + * tree.h (optimize_function): Kill prototype. + * optimize.c (dump_function, optimize_function, dump_finction): Kill. + * semantics.c (expand_body): Kill. + 2004-03-30 Mark Mitchell PR c++/14724 *************** i2004-06-11 Mark Mitchell ! PR C++/14639 ! * method.c (use_think): Do not mark thunk as referenced. 2004-03-21 Mark Mitchell --- 6358,6420 ---- PR c++/14763 * pt.c (tsubst_default_argument): Clear current_function_decl. ! 2004-03-30 Zack Weinberg ! * name-lookup.c, parser.c: Use new shorter form of GTY markers. ! ! 2004-03-29 Zack Weinberg ! ! * error.c (dump_function_name): If T's DECL_LANG_SPECIFIC ! is null, just print the literal name and return. ! ! 2004-03-25 Kazu Hirata ! ! * cxx-pretty-print.c: Fix comment typos. ! ! 2004-03-24 Kazu Hirata ! ! * cxx-pretty-print.c, cxx-pretty-print.h, decl.h, friend.c: ! Update copyright. ! ! 2004-03-23 Ziemowit Laski ! ! * Make-lang.in (cp/mangle.o): Depend on $(TARGET_H). ! * mangle.c (write_type): Add call to 'mangle_fundamental_type' ! target hook. ! ! 2004-03-23 Zack Weinberg ! ! PR 12267, 12391, 12560, 13129, 14114, 14133 ! * cp-lang.c (c_reset_state): Delete. ! (push_file_scope, pop_file_scope): New stubs. ! * parser.c (c_parse_file): Call sorry() here if called more than once. ! ! 2004-03-23 Richard Kenner ! ! * typeck.c (build_c_cast): Only look at TREE_CONSTANT_OVERFLOW ! for INTEGER_CST. ! ! 2004-03-22 Gabriel Dos Reis ! ! * cxx-pretty-print.c (pp_cxx_parameter_declaration_clause): Declare. ! ! 2004-03-21 Gabriel Dos Reis ! ! * error.c (enum pad): Remove. ! (dump_qualifiers): Likewise. ! (dump_type): Replace dump_qualifiers with pp_cxx_cv_qualifier_seq. ! (dump_aggr_type): Likewise. ! (dump_type_suffix): Likewise. ! (dump_simple_decl): Likewise. ! (dump_function_decl): Likewise. ! (cv_to_string): Likewise. ! (dump_type_prefix): Likewise. Adjust return void. ! * cxx-pretty-print.c (pp_cxx_cv_qualifier_seq): Move to ! cxx_pretty_print.h. ! (pp_cxx_template_keyword_if_needed): Document. ! (pp_cxx_qualified_id): Document case FUNCTION_DECL. Tidy. ! (pp_cxx_expression): Handle NON_DEPENDENT_EXPR and ! MUST_NOT_THROW_EXPR. 2004-03-21 Mark Mitchell *************** i2004-06-11 Mark Mitchell PR c++/14545 --- 6460,6473 ---- * typeck.c (lookup_destructor): Allow the use of destructors from base classes. ! ! 2004-03-19 Richard Kenner ! ! * cxx-pretty-print.c (pp_cxx_unqualified_id): Use ! TEMPLATE_TYPE_PARM_INDEX instead of TYPE_FIELDS. ! * search.c (dfs_unuse_fields): Add two more TREE_CODES that mean ! the field is named TEMPLATE_TYPE_PARM_INDEX. ! 2004-03-19 Giovanni Bajo PR c++/14545 *************** i2004-06-11 Mark Mitchell + * call.c (build_conditional_expr): Do not call force_rvalue for operands of void_type when the conditional expression itself has void type. *************** i2004-06-11 Mark Mitchell + + * cp-tree.def (TEMPLATE_TYPE_PARM, TYPEOF_TYPE): Update comments. + * cp-tree.h (NEW_EXPR_USE_GLOBAL, DELETE_EXPR_USE_GLOBAL): Add check. + (DELETE_EXPR_USE_VEC, COMPOUND_EXPR_OVERLOADED): Likewise. + (KOENIG_LOOKUP_P, PTRMEM_OK_P, TEMPLATE_TYPE_PARM_INDEX): Likewise. + (TYPENAME_TYPE_FULLNAME): Add check and use type.values. + (TYPEOF_TYPE_EXPR): New macro. + * class.c (finish_struct_bits): Use TYPE_VFIELD and TYPE_METHODS. + * error.c (dump_type): Use TYPEOF_TYPE_EXPR. + * pt.c (tsubst): Likewise. + * semantics.c (finish_typeof): Likewise. + * search.c (dfs_unuse_fields): Handle TYPENAME_TYPE, TYPEOF_TYPE, + and TEMPLATE_TYPE_PARM. + * typeck.c (comptypes): Use TYPE_ORIG_SIZE_TYPE, not TYPE_DOMAIN. + (build_array_ref): Use TYPE_DOMAIN, not TYPE_VALUES. + 2004-03-16 Mark Mitchell PR c++/14586 *************** i2004-06-11 Mark Mitchell + + * cp-lang.c, ptree.c: Update copyright. + 2004-03-13 Mark Mitchell PR c++/14550 *************** i2004-06-11 Mark Mitchell ! PR c++/14476 ! * decl.c (xref_tag): Do not create dummy ENUMERAL_TYPEs. 2004-03-10 Mark Mitchell PR c++/14510 * decl.c (xref_tag): Disregard non-type declarations when ! looking up a tagged type. ! ! 2004-03-10 Jason Merrill ! ! PR c++/14452 ! * tree.c (stabilize_init): Return whether or not it worked. ! * init.c (build_new_1): If not, use a sentry. ! * cp-tree.h: Adjust prototype. ! 2004-03-09 Nathan Sidwell PR c++/14397 * call.c (convert_like_real): Build a const qualified temporary, --- 6575,6602 ---- allowed in integral constant expressions. (cp_parser_delete_expression): Likewise. ! 2004-03-12 Matt Austern ! * decl2.c (maybe_make_one_only): Look at ! TARGET_EXPLICIT_INSTANTIATION_ONE_ONLY when deciding whether ! to make an explicit instantiation weak. ! * method.c (use_thunk): Make sure we call comdat_linkage ! when appropriate. ! * pt.c (do_type_instantiation): On systems where weak symbols ! don't go in a static archive's TOC, explicit instantiation of a ! class must imply *explicit* instantiation of its memeber. ! ! 2004-03-11 Kazu Hirata ! ! * call.c, cp-tree.h, pt.c: Fix comment typos. 2004-03-10 Mark Mitchell PR c++/14510 * decl.c (xref_tag): Disregard non-type declarations when ! looking up a tagged type. ! 2004-03-09 Nathan Sidwell PR c++/14397 * call.c (convert_like_real): Build a const qualified temporary, *************** i2004-06-11 Mark Mitchell + PR c++/14432 * name-lookup.c (supplement_binding): Ignore functions that are marked DECL_ANTICIPATED. *************** i2004-06-11 Mark Mitchell + + * class.c (check_methods): Don't use IDENTIFIER_ERROR_LOCUS. + * cp-tree.h (DECL_INVALID_OVERRIDER_P): New macro. + (lang_identifier): Remove implicit_decl and error_locus. + (IDENTIFIER_IMPLICIT_DECL): Remove. + (SET_IDENTIFIER_IMPLICTI_DECL): Likewise. + (IDENTIFIER_ERROR_LOCUS): Likewise. + (SET_IDENTIFIER_ERROR_LOCUS): Likewise. + (TYPE_ASSEMBLER_NAME_STRING): Likewise. + (TYPE_ASSEMBLER_NAME_LENGTH): Likewise. + (implicitly_declare): Remove. + * decl.c (warn_extern_redeclared_static): Remove check of + IDENTIFIER_IMPLICIT_DECL. + (duplicate_decls): Don't check IDENTIFIER_ERROR_LOCUS. + (implicitly_declare): Remove. + (grok_ctor_properties): Don't set IDENTIFIER_ERROR_LOCUS. + (start_function): Don't check IDENTIFIER_IMPLICIT_DECL. + (start_method): Don't check IDENTIFIER_ERROR_LOCUS. + * lex.c (unqualified_name_lookup_error): Create a dummy VAR_DECL + in the innermost scope, rather than at namespace scope. + * name-lookup.c (push_local_binding): Give it external linkage. + (pushdecl): Remove dead code. + * name-lookup.h (push_local_binding): Declare it. + * ptree.c (cxx_print_identifier): Don't print + IDENTIFIER_IMPLICIT_DECL or IDENTIFIER_ERROR_LOCUS. + * search.c (check_final_overrider): Use DECL_INVALID_OVERRIDER_P, + not IDENTIFIER_ERROR_LOCUS. + * typeck.c (build_function_call): Remove dead code. + 2004-03-08 Jason Merrill PR c++/13170 *************** i2004-06-11 Mark Mitchell - - PR c++/13944 - * except.c (do_free_exception): Remove #if 0 wrapper. - (build_throw): Use it if we elide a copy into the - exception object. - - * tree.c (stabilize_call): Fix thinko. ! * init.c (build_new_1): Preevaluate initializer. Simplify EH code. ! (build_init): Call a constructor rather than call build_aggr_init ! for classes. ! * except.c (stabilize_throw_expr): Remove. ! (build_throw): Use stabilize_init instead of stabilize_throw_expr. ! * tree.c (stabilize_call, stabilize_init): New fns. ! * call.c (build_over_call): A constructor no longer returns the ! address of the object. ! ! 2004-03-01 Mark Mitchell ! PR c++/14324 ! * lex.c (retrofit_lang_decl): Treat entities with no linkage as ! having C++ linkage for name-mangling purposes. ! PR c++/14260 ! * parser.c (cp_parser_direct_declarator): Recognize constructor ! declarators that use a template-id to name the class being ! constructed. ! PR c++/14337 ! * pt.c (tsubst_qualified_id): Handle dependent qualifying scopes. ! (tsubst_expr): Do not call tsubst_copy, even when ! processing_template_decl. 2004-03-01 Mark Mitchell --- 6685,6699 ---- PR debug/14079 * name-lookup.c (add_decl_to_level): Add extern variables, as well as static, to static_decls array. ! 2004-03-05 Jason Merrill ! * tree.c (list_hash_pieces): s/TYPE_HASH/TREE_HASH/. ! 2004-03-04 Geoffrey Keating ! * decl.c (grokfndecl): Update old incorrect comment. ! (grokvardecl): Diagnose C++ variables of type with no linkage. 2004-03-01 Mark Mitchell *************** i2004-06-11 Mark Mitchell + + PR c++/14369 + * error.c (dump_expr): Handle THROW_EXPR. + + 2004-03-01 Mark Mitchell + PR c++/14360 * parser.c (cp_parser_postfix_expression): Do not perform Koenig lookup if ordinary name-lookup finds a non-function. *************** i2004-06-11 Mark Mitchell ! * decl.c (redeclaration_error_message): Correct handling of ! templates. ! * pt.c (tsubst_friend_declaration): Adjust code to determine ! whether or not a friend template is a definition. ! (tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs. ! 2004-03-01 Gabriel Dos Reis ! PR c++/14369 ! * error.c (dump_expr): Handle THROW_EXPR. 2004-02-29 Mark Mitchell --- 6718,6743 ---- are no extra tokens after the end of the default-argument expression. ! 2004-03-01 Mark Mitchell ! PR c++/14324 ! * lex.c (retrofit_lang_decl): Treat entities with no linkage as ! having C++ linkage for name-mangling purposes. ! PR c++/14260 ! * parser.c (cp_parser_direct_declarator): Recognize constructor ! declarators that use a template-id to name the class being ! constructed. ! ! PR c++/14337 ! * pt.c (tsubst_qualified_id): Handle dependent qualifying scopes. ! (tsubst_expr): Do not call tsubst_copy, even when ! processing_template_decl. ! ! 2004-03-01 Jeff Law ! ! * init.c (build_vec_delete_1): Convert 2nd argument to NE_EXPR to ! the proper type. 2004-02-29 Mark Mitchell *************** i2004-06-11 Mark Mitchell PR debug/12103 * class.c (update_vtable_entry_for_fn): Do not go through covariance machinery if the type returned by an overrider is the same as the original. ! 2004-02-27 Giovanni Bajo ! PR c++/14284 ! * pt.c (dependent_type_p_r): A template template parameter is a ! dependent type. 2004-02-26 Mark Mitchell --- 6758,6781 ---- * pt.c (instantiate_class_template): Likewise. (resolve_typename_type): Likewise. ! 2004-02-29 Mark Mitchell ! ! PR c++/14267 ! * typeck.c (build_modify_expr): Remove more of the cast-as-lvalue ! extension. PR debug/12103 * class.c (update_vtable_entry_for_fn): Do not go through covariance machinery if the type returned by an overrider is the same as the original. ! 2004-02-29 Kazu Hirata ! * call.c: Fix a comment typo. ! ! 2004-02-27 Ziemowit Laski ! ! * tree.c (pod_type_p): Treat VECTOR_TYPEs as PODs. 2004-02-26 Mark Mitchell *************** i2004-06-11 Mark Mitchell + PR c++/14284 + * pt.c (dependent_type_p_r): A template template parameter is a + dependent type. + + 2004-02-26 Giovanni Bajo + PR c++/14246 * mangle.c (write_template_arg_literal): Don't rely on identity for boolean constants. + 2004-02-24 Jason Merrill + + * tree.c (build_exception_variant): Use check_qualified_type. + + 2004-02-23 Zack Weinberg + Kazu Hirata + + * decl.c (cxx_init_decl_processing): Don't check + flag_writable_strings. + + 2004-02-23 Andrew Pinski + + PR c++/14156 + * typeck.c (maybe_warn_about_returning_address_of_location): + Change check for VAR_DECL to use DECL_P instead. + 2004-02-23 Giovanni Bajo PR c++/14250 * cvt.c (build_expr_type_conversion): Type must be complete before looking up for conversions. + 2004-02-23 Giovanni Bajo + + PR c++/14143 + * name-lookup.c (arg_assoc_class): Don't look into template + arguments if it is not a primary template. + + 2004-02-20 John David Anglin + + PR c++/12007 + * method.c (use_thunk): Always clone function argument tree. + 2004-02-20 Mark Mitchell PR c++/14199 *************** i2004-06-11 Mark Mitchell + PR c++/13927 + * decl.c (duplicate_decls): Return error_mark_node for invalid + redeclarations. + * name-lookup.c (push_namespace): Ignore the return value from + pushdecl. + * pt.c (push_template_decl_real): Robustify. + PR c++/14186 * name-lookup.c (push_class_level_binding): Do not complain about adding a binding for a member whose name is the same as the *************** i2004-06-11 Mark Mitchell PR c++/14181 ! * parser.c (cp_parser_new_expression): Parse an ill-formed direct-new-declarator after a parenthesized type-id to emit good diagnostic. 2004-02-17 Mark Mitchell PR c++/11326 --- 6855,6868 ---- 2004-02-19 Giovanni Bajo PR c++/14181 ! * parser.c (cp_parser_new_expression): Parse an ill-formed direct-new-declarator after a parenthesized type-id to emit good diagnostic. + 2004-02-18 Kazu Hirata + + * cp-tree.def, cvt.c: Update copyright. + 2004-02-17 Mark Mitchell PR c++/11326 *************** i2004-06-11 Mark Mitchell + + PR c++/13927 + * error.c (dump_decl) : Dump as simple declarations. + 2004-02-13 Mark Mitchell PR c++/14122 *************** i2004-06-11 Mark Mitchell - - PR c++/13927 - * error.c (dump_decl) : Dump as simple declarations. - - 2004-02-13 Mark Mitchell - PR c++/14083 * call.c (build_conditional_expr): Call force_rvalue on the non-void operand in the case that one result is a throw-expression --- 6914,6919 ---- *************** i2004-06-11 Mark Mitchell + + * call.c (conversion_kind): New type. + (conversion_rank): Likewise. + (conversion): Likewise. + (CONVERSION_RANK): New macro. + (conversion_obstack): New variable. + (obstack_initialized): Likewise. + (z_candidate): Change type of convs and second_conv. + (candidate_warning): New type. + (IDENTITY_RANK): Remove. + (EXACT_RANK): Likewise. + (PROMO_RANK): Likewise. + (STD_RANK): Likewise. + (PBOOL_RANK): Likewise. + (USER_RANK): Likewise. + (ELLIPSIS_RANK): Likewise. + (BAD_RANK): Likewise. + (ICS_RANK): Likewise. + (ICS_STD_RANK): Likewise. + (ICS_USER_FLAG): Likewise. + (ICS_ELLIPSIS_FLAG): Likewise. + (ICS_THIS_FLAG): Likewise. + (ICS_BAD_FLAG): Likewise. + (NEED_TEMPORARY_P): Likewise. + (CHECK_COPY_CONSTRUCTOR_P): Likewise. + (USER_CONV_CAND): Likewise. + (USER_CONV_FN): Likewise. + (conversion_obstack_alloc): New function. + (alloc_conversion): Likewise. + (validate_conversion_obstack): Likewise. + (alloc_conversions): Likewise. + (build_conv): Adjust to deal with new conversion data structures. + (build_identity_conv): New function. + (build_ambiguous_conv): Likewise. + (standard_conversion): Adjust to deal with new conversion data + structures. + (convert_class_to_reference): Likewise. + (direct_reference_binding): Likewise. + (reference_binding): Likewise. + (implicit_conversion): Likewise. + (add_candidate): Likewise. + (add_function_candidate): Likewise. + (add_conv_candidate): Likewise. + (build_builtin_candidate): Likewise. + (print_z_candidate): Likewise. + (merge_conversion_sequences): Likewise. + (build_user_type_conversion_1): Likewise. + (build_user_type_conversion): Likewise. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (conditional_conversion): Likewise. + (build_conditional_expr): Likewise. + (build_new_op): Likewise. + (build_op_delete_call): Likewise. + (convert_like_real): Likewise. + (build_over_call): Likewise. + (build_new_method_call): Likewise. + (is_subseq): Likewise. + (maybe_handle_implicit_object): Likewise. + (maybe_handle_ref_bind): Likewise. + (compare_ics): Likewise. + (source_type): Likewise. + (add_warning): Likewise. + (joust): Likewise. + (can_convert_arg): Likewise. + (can_convert_arg_bad): Likewise. + (perform_implicit_conversion): Likewise. + (perform_direct_initialization_if_possible): Likewise. + (initialize_reference): Likewise. + * cp-lang.c (cp_tree_size): Do not handle WRAPPER. + * cp-tree.def (WRAPPER): Likewise. + (IDENTITY_CONV): Remove. + (LVALUE_CONV): Likewise. + (QUAL_CONV): Likewise. + (STD_CONV): Likewise. + (PTR_CONV): Likewise. + (PMEM_CONV): Likewise. + (BASE_CONV): Likewise. + (REF_BIND): Likewise. + (USER_CONV): Likewise. + (AMBIG_CONV): Likewise. + (RVALUE_CONV): Likewise. + * cp-tree.h (tree_wrapper): Remove. + (WRAPPER_ZC): Remove. + (lang_tree_node): Remove wrapper. + (LOOKUP_SPECULATIVELY): Remove. + (build_op_delete_call): Adjust prototype. + (validate_conversion_obstack): Declare. + (build_zc_wrapper): Remove. + * cvt.c (convert_to_reference): Remove dead code. + (ocp_convert): Likewise. + * decl.c (redeclaration_error_message): Correct handling of + templates. + (finish_destructor_body): Do not use LOOKUP_SPECULATIVELY. + (cp_tree_node_structure): Remove WRAPPER case. + * decl2.c (finish_file): Call validate_conversion_obstack. + * init.c (build_new_1): Remove use of LOOKUP_SPECULATIVELY. + (build_op_delete_call): Likewise. + (build_x_delete): Likewise. + (build_delete): Adjust call to build_op_delete_call. + * pt.c (tsubst_friend_declaration): Adjust code to determine + whether or not a friend template is a definition. + (tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs. + * tree.c (build_zc_wrapper): Remove. + + 2004-02-12 Zack Weinberg + + * cp-lang.c: Don't define LANG_HOOKS_BUILTIN_TYPE_DECLS. + * cp-tree.h: Don't declare cxx_builtin_type_decls. + * decl.c (builtin_type_decls, cxx_builtin_type_decls): Delete. + (record_builtin_type): Call debug_hooks->type_decl on the TYPE_DECL. + 2004-02-10 Mark Mitchell * typeck.c (lookup_destructor): Fix typo in error message. + 2004-02-09 Kazu Hirata + + * call.c, parser.c, tree.c: Fix comment typos. + 2004-02-07 Zack Weinberg Bug 13856 *************** i2004-06-11 Mark Mitchell ! * rtti.c, tree.c: Update copyright. ! 2003-02-06 Giovanni Bajo PR c++/14033 * decl.c (require_complete_types_for_parms): Do not insert error_mark_node in the parameter list. ! 2003-02-06 Giovanni Bajo PR c++/14028 * parser.c (cp_parser_enclosed_template_argument_list): Emit straight --- 7060,7074 ---- 2004-02-07 Kazu Hirata ! * rtti.c: Update copyright. ! 2004-02-06 Giovanni Bajo PR c++/14033 * decl.c (require_complete_types_for_parms): Do not insert error_mark_node in the parameter list. ! 2004-02-06 Giovanni Bajo PR c++/14028 * parser.c (cp_parser_enclosed_template_argument_list): Emit straight *************** i2004-06-11 Mark Mitchell + + * call.c (type_passed_as): Replace PROMOTE_PROTOTYPES with + targetm.calls.promote_prototypes. + 2004-02-05 Rainer Orth PR middle-end/13750 *************** i2004-06-11 Mark Mitchell ! Backport from mainline. ! 2003-11-05 Mark Mitchell ! * decl.c (cxx_push_function_context): Do not set ! current_function_is_thunk. ! * method.c (use_thunk): Set CALL_FROM_THUNK on the call to the ! actual function. 2004-02-04 Mark Mitchell --- 7097,7120 ---- PR c++/13714 * typeck.c (lookup_destructor): Tweak error message. ! 2004-02-05 Jan Hubicka ! * tree.c (cp_cannot_inline_tree_fn): Allow inlining of comdat ! functions. ! 2004-02-05 Giovanni Bajo ! PR c++/14008 ! * parser.c (cp_parser_diagnose_invalid_typename): Removed parsing ! code, only emits the diagnostic now. Added lookup of the identifier ! and support for qualified ids. ! (cp_parser_parse_and_diagnose_invalid_type_name): New function. ! Parse an (invalid) type name as id-expression within a declarator. ! (cp_parser_simple_declaration): Use it. ! (cp_parser_member_declaration): Likewise. ! (cp_parser_make_typename_type): New function. Handle errors through ! cp_parser_diagnose_invalid_typename. ! (cp_parser_elaborated_type_specifier): Use it. 2004-02-04 Mark Mitchell *************** i2004-06-11 Mark Mitchell + + * error.c, search.c: Update copyright. + 2004-02-04 Mark Mitchell PR c++/9941 * rtti.c (tinfo_base_init): Use import_export_tinfo to decide the linkage for the typeinfo name string. + 2004-02-04 Mark Mitchell + PR c++/13969 * cp-tree.h (fold_non_dependent_expr): New function. * parser.c (cp_parser_fold_non_dependent_expr): Remove. *************** i2004-06-11 Mark Mitchell PR c++/13997 * pt.c (more_specialized_class): Increase processing_template_decl --- 7153,7166 ---- (tsubst_qualified_id): Simplify. (tsubst_copy_and_build): Likewise. ! 2004-02-04 Mark Mitchell ! ! * decl.c (cxx_push_function_context): Do not set ! current_function_is_thunk. ! * method.c (use_thunk): Set CALL_FROM_THUNK on the call to the ! actual function. ! ! 2004-02-04 Giovanni Bajo PR c++/13997 * pt.c (more_specialized_class): Increase processing_template_decl *************** i2004-06-11 Mark Mitchell PR c++/13950 * parser.c (cp_parser_class_name): Robustify. PR c++/13970 * parser.c (cp_parser_cache_group): Do not consume the EOF token. - 2004-02-03 Mark Mitchell - - PR c++/13925 - * decl.c (start_function): Do not call pushdecl for any - instantiation or specialization of a primary template. - PR c++/14002 * semantics.c (finish_id_expression): Do not return an IDENTIFIER_NODE when lookup finds a PARM_DECL. PR c++/13978 * pt.c (build_non_dependent_expr): Do not build NON_DEPENDENT_EXPRs for FUNCTION_DECLs or TEMPLATE_DECLs. --- 7168,7191 ---- 2004-02-03 Mark Mitchell + PR c++/13925 + * decl.c (start_function): Do not call pushdecl for any + instantiation or specialization of a primary template. + + 2004-02-03 Mark Mitchell + PR c++/13950 * parser.c (cp_parser_class_name): Robustify. PR c++/13970 * parser.c (cp_parser_cache_group): Do not consume the EOF token. PR c++/14002 * semantics.c (finish_id_expression): Do not return an IDENTIFIER_NODE when lookup finds a PARM_DECL. + 2004-02-03 Mark Mitchell + PR c++/13978 * pt.c (build_non_dependent_expr): Do not build NON_DEPENDENT_EXPRs for FUNCTION_DECLs or TEMPLATE_DECLs. *************** i2004-06-11 Mark Mitchell ! ! DR206 ! PR c++/13813 ! * decl.c (grokdeclarator): Check immediatly type completeness for ! non-dependent types. ! ! 2004-01-30 Mark Mitchell PR c++/13113 * init.c (build_offset_ref): Improve error recovery for invalid --- 7198,7204 ---- * parser.c (cp_parser_simple_declaration): When skipping to the end of the statement swallow the terminating semicolon. ! 2004-02-02 Mark Mitchell PR c++/13113 * init.c (build_offset_ref): Improve error recovery for invalid *************** i2004-06-11 Mark Mitchell PR c++/13957 * pt.c (tsubst_qualified_id): Improved error message when a type is expected but not found. 2004-01-30 Michael Matz * parser.c (cp_parser_labeled_statement): Accept case ranges. ! 2004-01-28 Jan Hubicka --- 7219,7257 ---- * call.c (convert_class_to_reference): Keep better track of pedantically invalid user-defined conversions. ! 2004-02-01 Giovanni Bajo PR c++/13957 * pt.c (tsubst_qualified_id): Improved error message when a type is expected but not found. + 2004-01-31 Kazu Hirata + + * class.c: Fix comment typos. + * decl.c: Likewise. + * error.c: Likewise. + * parser.c: Likewise. + * pt.c: Likewise. + * search.c: Likewise. + * typeck.c: Likewise. + + 2004-01-30 Richard Henderson + + PR c++/13693 + * method.c (use_thunk): Don't force_target_expr for void thunks. + * tree.c (build_target_expr_with_type): Assert non-void type. + (force_target_expr): Likewise. + 2004-01-30 Michael Matz * parser.c (cp_parser_labeled_statement): Accept case ranges. ! 2004-01-30 Giovanni Bajo ! DR206 ! PR c++/13813 ! * decl.c (grokdeclarator): Check immediatly type completeness for ! non-dependent types. 2004-01-30 Giovanni Bajo *************** i2004-06-11 Mark Mitchell * parser.c (cp_parser_template_id): Parse tentatively `[:' after a template name as it was `<::' (digraph typo). --- 7259,7271 ---- * call.c (convert_arg_to_ellipsis): Don't emit a warning if within a sizeof expression.block ! 2004-01-29 Mark Mitchell ! ! PR c++/13883 ! * mangle.c (write_encoding): Correct encoding of member template ! constructors. ! ! 2004-01-28 Giovanni Bajo * parser.c (cp_parser_template_id): Parse tentatively `[:' after a template name as it was `<::' (digraph typo). *************** i2004-06-11 Mark Mitchell - - PR c++/13883 - * mangle.c (write_encoding): Correct encoding of member template - constructors. - 2004-01-28 Mark Mitchell PR c++/13791 * typeck.c (merge_types): Do not merge attributes into TYPENAME_TYPEs. - 2004-01-28 Mark Mitchell - PR c++/13736 * parser.c (cp_parser_direct_declarator): Do not prevent backtracking inside a parenthesized declarator. (cp_parser_parameter_declaration): Fix typo in comment. 2004-01-26 Kaveh R. Ghazi * cp-tree.h (language_function, lang_type_header): Use --- 7276,7311 ---- (cp_parser_class_name): Likewise. (cp_lexer_get_preprocessor_token): Use c_lex_with_flags. 2004-01-28 Mark Mitchell PR c++/13791 * typeck.c (merge_types): Do not merge attributes into TYPENAME_TYPEs. PR c++/13736 * parser.c (cp_parser_direct_declarator): Do not prevent backtracking inside a parenthesized declarator. (cp_parser_parameter_declaration): Fix typo in comment. + 2004-01-28 Jan Hubicka + + * semantics.c (expand_body) Do emit_associated_thunks before + expansion. + + 2004-01-27 Devang Patel + + * name-lookup.c: Include "debug.h" + (do_namespace_alias): Invoke debug_hooks to emit debug info + for namespace alias. + (do_local_using_decl): Invoke debug_hooks to emit debug info + for using decl. + (do_class_using_decl): Same. + (do_toplevel_using_decl): Same. + (do_using_directive): Same. + (cp_emit_debug_info_for_using): New function. + * Make-lang.in (cp/parser.o): Depend on debug.h + (cp/name-lookup.o): Same. + 2004-01-26 Kaveh R. Ghazi * cp-tree.h (language_function, lang_type_header): Use *************** i2004-06-11 Mark Mitchell - * class.c (add_method): Just check processing_template_decl to determine whether or not we are within a template. * decl2.c (maybe_retrofit_in_chrg): Likewise. --- 7318,7323 ---- *************** i2004-06-11 Mark Mitchell : Likewise. - 2004-01-24 Kazu Hirata - - * call.c: Update copyright. - * class.c: Likewise. - * decl2.c: Likewise. - * except.c: Likewise. - * expr.c: Likewise. - * init.c: Likewise. - * mangle.c: Likewise. - * optimize.c: Likewise. - * typeck.c: Likewise. - * typeck2.c: Likewise. - 2004-01-23 Andrew Pinski PR c++/13701 --- 7367,7372 ---- *************** i2004-06-11 Mark Mitchell + + * optimize.c, typeck2.c: Update copyright. + + 2004-01-21 Kazu Hirata + + * Make-lang.in, call.c, class.c, decl2.c, except.c, expr.c, + init.c, mangle.c, typeck.c: Update copyright. + 2004-01-21 Zdenek Dvorak * parser.c (cp_parser_class_specifier): Prevent garbage collection. *************** i2004-06-11 Mark Mitchell * Make-lang.in (CXX_INSTALL_NAME, GXX_INSTALL_NAME, CXX_TARGET_INSTALL_NAME, GXX_TARGET_INSTALL_NAME): Define via a --- 7394,7400 ---- (c++.man, c++.srcman): New rules. (c++.install-man): Revamp rule. ! 2004-01-20 Kelley Cook * Make-lang.in (CXX_INSTALL_NAME, GXX_INSTALL_NAME, CXX_TARGET_INSTALL_NAME, GXX_TARGET_INSTALL_NAME): Define via a *************** i2004-06-11 Mark Mitchell " or ".", treat the entire expression as erroneous. - 2004-01-19 Mark Mitchell - PR c++/13592 * call.c (build_field_call): Remove. (n_build_method_call): Likewise. --- 7407,7412 ---- *************** i2004-06-11 Mark Mitchell PR c++/9021 ! PR c++/11005 * parser.c (cp_parser_elaborated_type_specifier): Warn about attributes and discard. * decl.c (xref_tag): Don't overwite existing attributes with --- 7517,7523 ---- 2004-01-14 Danny Smith PR c++/9021 ! PR c++/11005 * parser.c (cp_parser_elaborated_type_specifier): Warn about attributes and discard. * decl.c (xref_tag): Don't overwite existing attributes with *************** i2004-06-11 Mark Mitchell : Remove obsolete array index tweaking. ! 2003-01-12 Steven Bosscher PR c++/13558 * parser.c (cp_parser_member_declaration): Any non-type is also --- 7545,7551 ---- PR c++/13474 * pt.c (tsubst) : Remove obsolete array index tweaking. ! 2004-01-12 Steven Bosscher PR c++/13558 * parser.c (cp_parser_member_declaration): Any non-type is also diff -Nrcpad gcc-3.4.3/gcc/cp/ChangeLog.3 gcc-4.0.0/gcc/cp/ChangeLog.3 *** gcc-3.4.3/gcc/cp/ChangeLog.3 Thu Jan 1 00:43:21 2004 --- gcc-4.0.0/gcc/cp/ChangeLog.3 Mon Feb 2 18:55:07 2004 *************** *** 1082,1088 **** expression, always set TFF_NO_FUNCTION_ARGUMENTS in the flags. ! 2003-10-08 Giovanni Bajo PR c++/11097 * pt.c (tsubst_decl): Substitute also the DECL_NAME node of --- 1082,1088 ---- expression, always set TFF_NO_FUNCTION_ARGUMENTS in the flags. ! 2003-10-08 Giovanni Bajo PR c++/11097 * pt.c (tsubst_decl): Substitute also the DECL_NAME node of *************** *** 3631,3637 **** (value- or type-) dependent expression as DECL_INITIAL is a valid constant-expression (at parser time). ! 2003-06-30 Giovanni Bajo PR c++/11106 * error.c (dump_decl): Call dump_decl to dump the DECL_NAME for a --- 3631,3637 ---- (value- or type-) dependent expression as DECL_INITIAL is a valid constant-expression (at parser time). ! 2003-06-30 Giovanni Bajo PR c++/11106 * error.c (dump_decl): Call dump_decl to dump the DECL_NAME for a diff -Nrcpad gcc-3.4.3/gcc/cp/ChangeLog.tree-ssa gcc-4.0.0/gcc/cp/ChangeLog.tree-ssa *** gcc-3.4.3/gcc/cp/ChangeLog.tree-ssa Thu Jan 1 00:00:00 1970 --- gcc-4.0.0/gcc/cp/ChangeLog.tree-ssa Thu May 13 06:40:12 2004 *************** *** 0 **** --- 1,566 ---- + 2004-04-19 Richard Henderson + + * except.c (check_handlers_1): Use locus stored in master for warning. + * tree.c (cp_walk_subtrees): Save and restore input_location. + + 2004-04-12 Diego Novillo + + * cp-lang.c (LANG_HOOKS_RTL_EXPAND_START): Remove. + (LANG_HOOKS_RTL_EXPAND_STMT): Remove. + * semantics.c (cxx_expand_function_start): Remove. + + 2004-04-12 Richard Henderson + + * except.c (check_handlers_1): Use EXPR_LOCUS instead of STMT_LINENO. + * semantics.c (finalize_nrv_r): Likewise. + * tree.c (cp_walk_subtrees): Likewise. + * parser.c (cp_parser_statement): Save and restore entire locus; + set EXPR_LOCUS. + * pt.c (tsubst_expr): Don't special-case LABEL_STMT. + + 2004-04-01 Diego Novillo + + * name-lookup.c (innermost_nonclass_level): Check for + error_mark_node. + + 2004-03-25 Diego Novillo + + * parser.c (cp_parser_class_specifier): Initialize + variable 'attributes'. + + 2004-03-17 Richard Henderson + + * cp-lang.c (cxx_types_compatible_p): Use + same_type_ignoring_top_level_qualifiers_p. + + 2004-03-16 Dale Johannesen + + * cp-lang.c (cxx_types_compatible_p): New. + LANG_HOOKS_TYPES_COMPATIBLE_P: New. + + 2004-03-10 Jason Merrill + + PR c++/14452 + * tree.c (stabilize_init): Return whether or not it worked. + * init.c (build_new_1): If not, use a sentry. + * cp-tree.h: Adjust prototype. + + 2004-03-01 Jeff Law + + * init.c (build_vec_delete_1): Convert 2nd argument to NE_EXPR to + the proper type. + + 2004-02-24 Jason Merrill + + PR c++/13944 + * except.c (do_free_exception): Remove #if 0 wrapper. + (build_throw): Use it if we elide a copy into the exception object. + + * tree.c (stabilize_call): Fix thinko. + + 2004-02-19 Steven Bosscher + + * decl.c (poplevel): Don't output nested inline functions. + + 2004-02-16 Richard Henderson + + * call.c (build_call, build_over_call, build_new_method_call): Add + static chain operand to call_expr. + * decl.c (build_offset_ref_call_from_tree): Likewise. + * parser.c (cp_parser_postfix_expression): Likewise. + * semantics.c (finish_call_expr): Likewise. + * cp-lang.c (cp_expand_decl): Don't declare_nonlocal_label. + + 2004-02-09 Richard Henderson + + * cp-lang.c (LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P): New. + * cp-tree.h (cp_missing_noreturn_ok_p): Declare. + * decl.c (cp_missing_noreturn_ok_p): Export. + (cxx_init_decl_processing): Don't set lang_missing_noreturn_ok_p. + + 2004-02-06 Andrew Pinski + + PR c/13863 + * cp-lang.c (LANG_HOOKS_DECL_UNINIT): Remove. + + 2004-02-03 Richard Henderson + + PR middle-end/13325 + * call.c, cvt.c, init.c, typeck.c: Use TREE_NO_WARNING instead + of TREE_NO_UNUSED_WARNING. + * cvt.c (convert_to_void): Also use it for "has no effect" warning. + + 2004-01-30 Frank Ch. Eigler + + * cp-mudflap.c (mflang_flush_calls): Mark static ctor as TREE_USED. + + 2004-01-12 Jason Merrill + + * cp-lang.c (ok_to_generate_alias_set_for_type): Remove. + (cxx_get_alias_set): Allow all types. + + 2004-01-08 Frank Ch. Eigler + + * cp-mudflap.c (mflang_flush_calls): mf_mark synthetic function. + + 2004-01-04 Richard Henderson + + * call.c (build_over_call): Don't create a save_expr of an + aggregate, but rather its address. + + 2004-01-01 Richard Henderson + + * expr.c (cxx_expand_expr): Don't handle THROW_EXPR, or + MUST_NOT_THROW_EXPR. + * semantics.c (genrtl_try_block, genrtl_eh_spec_block, + genrtl_handler, cp_expand_stmt): Remove. + (init_cp_semantics): Don't set lang_expand_stmt. + + 2003-12-31 Richard Henderson + + * cp-mudflap.c (mflang_register_call): Remove. + + 2003-12-18 Jason Merrill + + PR c++/12453 + * cp-simplify.c (cp_gimplify_init_expr): Look inside STMT_EXPRs + and COMPOUND_EXPRs to find an AGGR_INIT_EXPR. + + 2003-12-16 Jason Merrill + + PR middle-end/12920 + * decl.c (grokdeclarator): Immediately layout an + ARRAY_TYPE used in a pointer-to-array declarator. + + 2003-12-16 Jan Hubicka + + Revert until initializers are made language independent: + * cp-lang.c (LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR): Kill. + * cp-tree.h (cxx_callgraph_analyze_expr): Kill. + * decl2.c (cxx_callgraph_analyze_expr): Kill. + + 2003-12-14 Jan Hubicka + + * cp-lang.c (LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR): Kill. + * cp-tree.h (cxx_callgraph_analyze_expr): Kill. + * decl2.c (cxx_callgraph_analyze_expr): Kill. + + 2003-11-24 Richard Henderson + + * Make-lang.in (tree.o, typeck.o): Remove -Wno-error. + + 2003-11-20 Richard Henderson + + * call.c (build_java_interface_fn_ref): Use build_address+convert. + * except.c (build_eh_type_type): Likewise. + * class.c (build_base_path): Use convert+build_indirect_ref. + * init.c (expand_virtual_init): Likewise. + * rtti.c (get_tinfo_decl_dynamic): Use convert. + + 2003-11-20 Frank Ch. Eigler + + * cp-mudflap.c (mflang_flush_calls): Adapt to direct expansion of + synthetic function, bypassing callgraph code. + * cp-decl2.c (finish_file): Call mudflap after callgraph-based + expansion. + + 2003-11-17 Jason Merrill + + * init.c (build_new_1): Preevaluate initializer. Simplify EH code. + (build_init): Call a constructor rather than call build_aggr_init + for classes. + * except.c (stabilize_throw_expr): Remove. + (build_throw): Use stabilize_init instead of stabilize_throw_expr. + * tree.c (stabilize_call, stabilize_init): New fns. + * call.c (build_over_call): A constructor no longer returns the + address of the object. + + 2003-11-16 Richard Henderson + + * typeck.c (pointer_diff): Remove unused variable. + + 2003-11-16 Jason Merrill + + PR optimization/11269 + * semantics.c (finalize_nrv_r): Rename from nullify_returns_r. + Also replace uses of the nrv with our RESULT_DECL. + (cxx_expand_function_start): Don't mess with the nrv. + (finalize_nrv): New fn. + * cp-tree.h: Declare it. + * decl.c (finish_function): Call it. + * tree.c (cp_copy_res_decl_for_inlining): Don't mess with the nrv. + + 2003-11-10 Richard Henderson + + * cp-simplify.c (gimplify_must_not_throw_expr): Replace add_tree + with append_to_statement_list. + + 2003-10-30 Richard Henderson + + * decl.c (pop_switch): Call c_do_switch_warnings. + + 2003-10-23 Richard Henderson + + * cp-simplify.c (cp_gimplify_expr): Return gimplify_status. + + 2003-10-16 Richard Henderson + + * decl.c (finish_function): Don't check flag_disable_gimple. + + 2003-10-14 Richard Henderson + + * decl.c (finish_function): Always gimplify; call c_warn_unused_result. + + 2003-10-13 Richard Henderson + + * pt.c (push_tinst_level): Use annotate_with_locus. + + 2003-10-12 Richard Henderson + + * call.c (call_builtin_trap): Use implicit_built_in_decls. + * class.c (build_base_path): Set TREE_INVARIANT. + (build_vtbl_ref_1, build_vtbl_initializer): Likewise. + * decl.c (build_enumerator): Likewise. + * init.c (build_zero_init): Likewise. + * pt.c (push_inline_template_parms_recursive): Likewise. + (build_template_parm_index, reduce_template_parm_level): Likewise. + (process_template_parm): Likewise. + * rtti.c (tinfo_base_init, generic_initializer): Likewise. + (ptr_initializer, ptm_initializer, class_initializer): Likewise. + * typeck.c (build_ptrmemfunc1): Likewise. + * typeck2.c (process_init_constructor): Likewise. + + * calls.c (dfs_accumulate_vtbl_inits): Rely on build to set + TREE_CONSTANT. + (build_vtbl_initializer): Likewise. + * init.c (build_vtbl_address): Likewise. + * rtti.c (tinfo_base_init): Likewise. + * tree.c (make_ptrmem_cst): Likewise. + * typeck.c (decay_conversion): Likewise. + (get_member_function_from_ptrfunc, build_binary_op): Likewise. + (pointer_diff, build_address, build_nop, build_unary_op): Likewise. + + 2003-09-30 Richard Henderson + + * decl.c (finish_function): Set cfun->function_end_locus. + + 2003-09-24 Jason Merrill + + * class.c, decl.c, decl2.c, error.c, init.c, lex.c, method.c, + pt.c, semantics.c, tree.c: Revert from TREE_LOCUS to + DECL_SOURCE_LOCATION. + + 2003-09-17 Richard Henderson + + * decl.c (cxx_init_decl_processing): Don't using_eh_for_cleanups + if exceptions are disabled. + + 2003-09-03 Richard Henderson + + * cp-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): Use expand_stmt_toplev. + + 2003-09-03 Richard Henderson + + * decl.c (finish_function): Fix misapplied patch. Don't + free_after_parsing or free_after_compilation. For real this time. + + 2003-08-22 Jason Merrill + + * cp-simplify.c (cp_gimplify_init_expr): Update use of predicates. + + 2003-08-21 Jason Merrill + + * cp-simplify.c (cp_gimplify_expr): Use simplify_aggr_init_expr. + (cp_gimplify_init_expr): Don't call it here. + (gimplify_aggr_init_expr): Remove. + + 2003-08-19 Jason Merrill + + * typeck.c (build_array_ref): Also build ARRAY_REFs from + INDIRECT_REFs of ARRAY_TYPE. + + * semantics.c (finish_id_expression): Unshare aliases. + + 2003-08-12 Diego Novillo + + * optimize.c (optimize_function): Do not call dump_function. + + 2003-08-08 Jason Merrill + + * optimize.c (optimize_function): Restore support for + !keep_function_tree_in_gimple_form. + + 2003-07-27 Andreas Jaeger + + * cp-lang.c: Convert K&R prototypes to ISO C90. + * cp-simplify.c: Likewise. + * cp-mudflap.c: Likewise. + + 2003-06-13 Frank Ch. Eigler + + * semantics.c (expand_body): Call mudflap_c_function just before + rtl expansion of function body; don't interfere with inlining. + * optimize.c (optimize_function): Remove mudflap call. + + 2003-06-13 Diego Novillo + + * cp-lang.c, cp-simplify.c, cp-tree.h, decl.c, optimize.c, + semantics.c, tree.c: Rename SIMPLE to GIMPLE everywhere. + + 2003-06-05 Frank Ch. Eigler + + * cp-mudflap.c (mflang_register_call): Give the synthetic decl + undefined (not zero) size. + + 2003-06-05 Frank Ch. Eigler + + * cp-mudflap.c (mx_flag): Remove. Update callers to use mf_mark. + + 2003-05-24 Diego Novillo + + * Make-lang.in (optimize.o): Add dependency on tree-simple.h + * decl.c (grokdeclarator): Don't abort when the declarator is + ERROR_MARK_NODE. + * optimize.c (optimize_function): Unshare all trees after + optimizing inline calls. + + 2003-05-12 Diego Novillo + + * class.c (dump_array): Call CONSTRUCTOR_ELTS to access + the operand of a CONSTRUCTOR node. + + 2003-05-07 Diego Novillo + + * decl.c (grokdeclarator): Fix thinko in handling + ERROR_MARK declarators. + + 2003-05-07 Diego Novillo + + * decl.c (grokdeclarator): Handle ERROR_MARK declarators. + + 2003-05-07 Jason Merrill + + * semantics.c (expand_body): Call expand_stmt when + -fdisable-simple is given. + + 2003-04-21 Jeff Law + + * optimize.c (optimize_function_tree): Do run the tree-ssa + optimizers. + + 2003-04-16 Jeff Law + + * optimize.c (optimize_function): No longer check + flag_disable_simple. + + 2003-04-15 Jeff Law + + * pt.c (instantiate_decl): If CFUN is null, then we will + need to push to the toplevel. + + * Makefile.in (decl.o): Depends on tree-flow.h. + * decl.c (finish_function): Call set_has_hidden_use when + nullifying returns for named value return optimization. + + 2003-04-02 Jason Merrill + + * cp-simplify.c (cp_simplify_expr) : + Change type of constant to RECORD_TYPE. + + 2003-03-10 Jeff Law + + * optimize.c (optimize_function): Avoid unnecessary + simplification of the function tree. + + 2003-03-02 Diego Novillo + + * decl.c: Replace DECL_SOURCE_LOCATION with TREE_LOCUS + everywhere. + + 2003-02-28 Frank Ch. Eigler + + * decl2.c (finish_file): Adjust timing of mudflap_finish_file call + to account for unit-at-a-time compilation. + + 2003-02-07 Jason Merrill + + * cp-simplify.c (cp_simplify_expr): Handle BASELINK. + + * parser.c (cp_parser_primary_expression): Unshare a COMPONENT_REF + from an ALIAS_DECL. + + 2003-02-05 Jason Merrill + + * cp-simplify.c (genericize_try_block): Do genericize catch blocks. + + 2003-02-03 Diego Novillo + + * parser.c (cp_parser_asm_definition): Call finish_asm_stmt with + 'volatile_p' directly. + * typeck.c (build_binary_op): Initialize variable 'type'. + * Make-lang.in (cp/tree.o-warn): Add -Wno-error. + + 2003-01-29 Frank Ch. Eigler + + * cp-mudflap.c (mflang_register_call): Adapt to mf-runtime.h API + change. + + 2003-01-15 Jeff Law + + * class.c: Use TREE_FILENAME and TREE_LINENO to extract + file/line information from tree nodes. Remove EXPR_WITH_FILE_LOCATION + nodes. Use annotate_with_file_line to attach file/line information + to tree nodes. Use TREE_LOCUS to copy file/line information + from one node to another. + * decl2.c, error.c, init.c, lex.c, method.c: Likewise. + * optimize.c: Likewise. + * cp-tree.def (TINST_LEVEL): New tree node. + * cp-tree.h (TINST_DECL): Update now that we no longer use + EXPR_WITH_FILE_LOCATION to represent the TINST_DECL information. + (TINST_FILE, TINST_LINE): Kill. + * decl.c: Use TREE_FILENAME and TREE_LINENO to extract + file/line information from tree nodes. Use annotate_witH_file_line + to add file/line information to tree nodes. Use TREE_LOCUS + to copy file/line information from one node to another. + (duplicate_decls): Make sure to copy TREE_LOCUS information + from the old decl to the new decl. + (finish_function): Save and restore file/line information + around genericizing the function tree. + * pt.c (lookup_template_class): Use TREE_LOCUS to copy file/line + information from one node to another. + (push_tinst_level): Generate a TINST_LEVEL node rather than + using EXPR_WITH_FILE_LOCATION nodes. Use annotate_with_file_line + to annotate the new node with file/line information. + (pop_tinst_level): Use TREE_LINENO and TREE_FILENAME to extract + file/line information from nodes. + (tsubst_friend_function, instantiate_class_template): Likewise. + (tsubst_decl, instantiate_decl, tsubst_enum): Likewise. + * semantics.c: Use annotate_with_file_line to annotate tree + nodes with file/line information. Use TREE_FILENAME and TREE_LINENO + to extract file/line information from tree nodes. + (expand_body): Restore file/line information slightly earlier. + tree.c (cp_walk_subtrees): Set lineno appropriately. + (cp_copy_res_decl_for_inlining): Use TREE_LOCUS to copy file/line + information from one node to another. + + 2003-01-13 Frank Ch. Eigler + + Prototype C++ mudflap support. + * Make-lang.in (CXX_OBJS): Add cp/cp-mudflap.o and dependencies. + * cp-mudflap.c: New file with C++ front-end mflang_* routines. + * decl2.c (finish_file): Divert to mudflap if appropriate. + * optimize.c (optimize_function): Ditto. + + 2003-01-02 Jason Merrill + + * Make-lang.in (CXX_C_OBJS): Replace old-tree-inline.o with + tree-inline.o. + + * optimize.c (dump_function): Move to ../tree-dump.c. + + * cp-simplify.c (cp_simplify_expr): Handle PTRMEM_CST, INIT_EXPR, + MODIFY_EXPR and EMPTY_CLASS_EXPR. + (cp_simplify_stmt): Handle USING_STMT. + (cp_simplify_init_expr): New fn. + * cvt.c (build_up_reference): Don't push the decl. + * class.c (build_vtable_entry_ref, build_vtbl_ref_1): Unshare the + vtable address. + * init.c (build_vtbl_address): Likewise. + * cp-lang.c (LANG_HOOKS_UNSAVE_EXPR_NOW): Remove. + * decl.c (lookup_name_real): Unshare the expansion of an ALIAS_DECL. + (finish_function): Don't genericize templates. + * parse.y (parse_asm_stmt): Fix prototype. + * semantics.c (expand_body): Don't expand if we saw errors. + Drop support for expanding non-GENERIC code. + + * cp-simplify.c (cp_simplify_stmt): Handle HANDLER and EH_SPEC_BLOCK. + (genericize_try_block): Always build a TRY_CATCH_EXPR. + (genericize_catch_block): New fn. + (genericize_eh_spec_block): New fn. + (cp_simplify_expr): Handle THROW_EXPR and MUST_NOT_THROW_EXPR. + (simplify_must_not_throw_expr): New fn. + * except.c (wrap_cleanups_r): Make the MUST_NOT_THROW_EXPR void. + (build_throw): Likewise. + + 2002-12-14 Jason Merrill + + * optimize.c (dump_function): Use pretty dumpers. + (optimize_function): Don't do .original dump here. + + 2002-12-03 Diego Novillo + + * cp-simplify.c: Include coretypes.h and tm.h. + + 2002-11-24 Jason Merrill + + Gimplify C++ cleanups. + * decl.c (finish_function): Call c_genericize. + * cp-simplify.c (cp_simplify_stmt): New fn. + (genericize_try_block): New fn. + (cp_simplify_expr): Move INIT_EXPR/TARGET_EXPR code + to ../gimplify.c. Handle AGGR_INIT_EXPR. + (simplify_target_expr): Move to ../gimplify.c. + (maybe_fixup_loop_cond): Remove. + (simplify_aggr_init_expr): Split out from... + * semantics.c (simplify_aggr_init_exprs_r): ...here. + (expand_body): Don't simplify AGGR_INIT_EXPRs here + if we're gimplifying. Handle expanding generic trees. + * tree.c (init_tree): Set lang_simplify_stmt. + * cp-tree.h: Declare the new fns. + + * optimize.c (optimize_function): Do pretty dumps. + + 2002-10-04 Jason Merrill + + * Make-lang.in (CXX_C_OBJS): Add gimplify.o. + + 2002-09-24 Jason Merrill + + * parse.y (parse_asm_stmt): New fn. + (simple_stmt): Use it. + * semantics.c (finish_asm_stmt): Change cv_qualifier parm to + volatile_p. + * cp-tree.h: Adjust prototype. + * pt.c (tsubst_expr): Adjust call. + + 2002-08-23 Diego Novillo + + * Make-lang.in (CXX_C_OBJS): Add tree-dchain.o + + 2002-08-11 Jason Merrill + + * cp-simplify.c (maybe_fixup_loop_cond): Move here. + (cp_simplify_expr): Call it. + (simplify_target_expr): Remove pre_p parm. + + 2002-08-09 Jason Merrill + + * cp-simplify.c (cp_simplify_expr): New fn. + (simplify_target_expr): New fn. + (cp_simplify_function_tree): Remove. + * cp-lang.c (LANG_HOOKS_SIMPLIFY_FUNCTION_TREE): Don't define. + (LANG_HOOKS_SIMPLIFY_EXPR): Define. + * optimize.c (optimize_function): De-hook simplify_function_tree. + * cp-tree.h: Declare cp_simplify_expr. + + 2002-07-17 Daniel Berlin + + * Make-lang.in (CXX_C_OBJS): Add tree-alias-ecr.c, + tree-alias-type.o, tree-alias-steen.o, disjoint-set.o. + + 2002-06-21 Andreas Jaeger + + * Make-lang.in (cp-simplify.o): New. + + 2002-06-18 Jason Merrill + + * cp-simplify.c: New file. + * Make-lang.in: Add it. + * cp-tree.h: Declare cp_simplify_function_tree. + * cp-lang.c (LANG_HOOKS_SIMPLIFY_FUNCTION_TREE): Define. + * optimize.c (optimize_function): Call tree optimizers (but not yet). + + Local Variables: + mode: change-log + change-log-default-name: "ChangeLog.tree-ssa" + End: diff -Nrcpad gcc-3.4.3/gcc/cp/Make-lang.in gcc-4.0.0/gcc/cp/Make-lang.in *** gcc-3.4.3/gcc/cp/Make-lang.in Mon Aug 23 18:03:06 2004 --- gcc-4.0.0/gcc/cp/Make-lang.in Tue Jan 18 11:45:31 2005 *************** *** 1,5 **** # Top level -*- makefile -*- fragment for GNU C++. ! # Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. #This file is part of GCC. --- 1,6 ---- # Top level -*- makefile -*- fragment for GNU C++. ! # Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, ! # 2005 # Free Software Foundation, Inc. #This file is part of GCC. *************** g++-cross$(exeext): g++$(exeext) *** 73,94 **** # 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 \ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \ ! c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o ! # Language-specific object files. ! CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parser.o cp/ptree.o cp/rtti.o \ cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ ! cp/mangle.o cp/cp-lang.o cp/name-lookup.o cp/cxx-pretty-print.o # Use strict warnings for this front end. ! cp-warn = $(STRICT_WARN) $(WERROR) ! cc1plus$(exeext): $(CXX_OBJS) $(CXX_C_OBJS) $(BACKEND) \ ! libcpp.a $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ ! $(CXX_OBJS) $(CXX_C_OBJS) $(BACKEND) libcpp.a $(LIBS) # Special build rules. $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf --- 74,99 ---- # 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 \ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \ ! c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \ ! c-gimplify.o tree-inline.o ! # Language-specific object files for C++ and Objective C++. ! CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parser.o cp/ptree.o cp/rtti.o \ cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ ! cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \ ! cp/cp-gimplify.o tree-mudflap.o $(CXX_C_OBJS) ! ! # Language-specific object files for C++. ! CXX_OBJS = cp/cp-lang.o stub-objc.o $(CXX_AND_OBJCXX_OBJS) # Use strict warnings for this front end. ! cp-warn = $(STRICT_WARN) ! cc1plus$(exeext): $(CXX_OBJS) $(BACKEND) $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ ! $(CXX_OBJS) $(BACKEND) $(LIBS) # Special build rules. $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf *************** $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.g *** 97,103 **** gtype-cp.h gt-cp-call.h gt-cp-decl.h gt-cp-decl2.h : s-gtype; @true gt-cp-pt.h gt-cp-repo.h gt-cp-parser.h gt-cp-method.h : s-gtype; @true ! gt-cp-tree.h gt-cp-mangle.h gt-cp-name-lookup.h: s-gtype; @true # # Build hooks: --- 102,108 ---- gtype-cp.h gt-cp-call.h gt-cp-decl.h gt-cp-decl2.h : s-gtype; @true gt-cp-pt.h gt-cp-repo.h gt-cp-parser.h gt-cp-method.h : s-gtype; @true ! gt-cp-tree.h gt-cp-mangle.h gt-cp-name-lookup.h gt-cp-typeck2.h: s-gtype; @true # # Build hooks: *************** c++.man: doc/g++.1 *** 120,126 **** --- 125,135 ---- c++.srcman: doc/g++.1 -cp -p $^ $(srcdir)/doc + # 'make check' in gcc/ looks for check-c++, as do all toplevel C++-related + # check targets. However, our DejaGNU framework requires 'check-g++' as its + # entry point. We feed the former to the latter here. check-c++ : check-g++ + # List of targets that can use the generic check- rule and its // variant. lang_checks += check-g++ # *************** CXX_TREE_H = $(TREE_H) cp/name-lookup.h *** 214,243 **** CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H) ! cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h \ c-pragma.h toplev.h output.h input.h cp/operators.def $(TM_P_H) ! cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \ ! $(LANGHOOKS_DEF_H) c-common.h $(CXX_PRETTY_PRINT_H) $(DIAGNOSTIC_H) ! cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_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 ! cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \ ! output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \ ! diagnostic.h cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \ ! diagnostic.h convert.h cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H) convert.h cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \ diagnostic.h intl.h gt-cp-call.h convert.h target.h cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H) cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \ ! except.h cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \ $(TM_P_H) $(TARGET_H) gt-cp-method.h cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h ! cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H) cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_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) $(TM_H) --- 223,258 ---- CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H) ! cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h \ c-pragma.h toplev.h output.h input.h cp/operators.def $(TM_P_H) ! cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \ ! $(LANGHOOKS_DEF_H) c-common.h gtype-cp.h $(CXX_PRETTY_PRINT_H) $(DIAGNOSTIC_H) \ ! cp/cp-objcp-common.h ! cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h \ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \ cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \ ! debug.h gt-cp-decl.h timevar.h $(TREE_FLOW_H) ! cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h $(EXPR_H) \ ! output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h \ ! c-pragma.h ! cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ! $(TM_H) $(TREE_H) $(CXX_TREE_H) c-common.h toplev.h langhooks.h \ ! $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h $(CXX_PRETTY_PRINT_H) \ ! cp/cp-objcp-common.h cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \ ! diagnostic.h gt-cp-typeck2.h cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \ ! diagnostic.h convert.h c-common.h cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H) convert.h cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \ diagnostic.h intl.h gt-cp-call.h convert.h target.h cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H) cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \ ! except.h $(TARGET_H) cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \ $(TM_P_H) $(TARGET_H) gt-cp-method.h cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h ! cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_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) $(TM_H) *************** cp/except.o: cp/except.c $(CXX_TREE_H) $ *** 246,271 **** cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \ except.h $(TM_P_H) ! cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/lex.h \ ! toplev.h $(RTL_H) except.h tree-inline.h gt-cp-pt.h cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \ flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \ gt-cp-repo.h ! cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \ flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \ ! tree-inline.h cgraph.h cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_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) $(TM_H) toplev.h real.h gt-cp-mangle.h \ $(TARGET_H) $(TM_P_H) ! cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) diagnostic.h gt-cp-parser.h output.h cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(CXX_TREE_H) timevar.h gt-cp-name-lookup.h toplev.h \ ! $(DIAGNOSTIC_H) flags.h cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) --- 261,289 ---- cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \ except.h $(TM_P_H) ! cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h \ ! toplev.h $(RTL_H) except.h tree-inline.h pointer-set.h gt-cp-pt.h cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \ flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \ gt-cp-repo.h ! cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) except.h toplev.h \ flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \ ! tree-inline.h cgraph.h $(TARGET_H) c-common.h cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \ ! input.h $(PARAMS_H) debug.h tree-inline.h tree-gimple.h $(TARGET_H) cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \ $(TARGET_H) $(TM_P_H) ! cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) diagnostic.h gt-cp-parser.h \ ! output.h ! cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) toplev.h c-common.h \ ! $(TM_H) coretypes.h pointer-set.h cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(CXX_TREE_H) timevar.h gt-cp-name-lookup.h toplev.h \ ! $(DIAGNOSTIC_H) flags.h debug.h cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) diff -Nrcpad gcc-3.4.3/gcc/cp/call.c gcc-4.0.0/gcc/cp/call.c *** gcc-3.4.3/gcc/cp/call.c Thu Aug 12 00:34:17 2004 --- gcc-4.0.0/gcc/cp/call.c Sun Apr 3 12:07:22 2005 *************** *** 1,6 **** /* Functions related to invoking methods and overloaded functions. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) and modified by Brendan Kehoe (brendan@cygnus.com). --- 1,6 ---- /* Functions related to invoking methods and overloaded functions. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) and modified by Brendan Kehoe (brendan@cygnus.com). *************** Boston, MA 02111-1307, USA. */ *** 40,58 **** #include "target.h" #include "convert.h" static struct z_candidate * tourney (struct z_candidate *); static int equal_functions (tree, tree); static int joust (struct z_candidate *, struct z_candidate *, bool); ! static int compare_ics (tree, tree); static tree build_over_call (struct z_candidate *, int); static tree build_java_interface_fn_ref (tree, tree); #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 (enum tree_code, enum tree_code, tree, tree, tree, const char *); static tree build_object_call (tree, tree); --- 40,142 ---- #include "target.h" #include "convert.h" + /* The various kinds of conversion. */ + + typedef enum conversion_kind { + ck_identity, + ck_lvalue, + ck_qual, + ck_std, + ck_ptr, + ck_pmem, + ck_base, + ck_ref_bind, + ck_user, + ck_ambig, + ck_rvalue + } conversion_kind; + + /* The rank of the conversion. Order of the enumerals matters; better + conversions should come earlier in the list. */ + + typedef enum conversion_rank { + cr_identity, + cr_exact, + cr_promotion, + cr_std, + cr_pbool, + cr_user, + cr_ellipsis, + cr_bad + } conversion_rank; + + /* An implicit conversion sequence, in the sense of [over.best.ics]. + The first conversion to be performed is at the end of the chain. + That conversion is always an cr_identity conversion. */ + + typedef struct conversion conversion; + struct conversion { + /* The kind of conversion represented by this step. */ + conversion_kind kind; + /* The rank of this conversion. */ + conversion_rank rank; + BOOL_BITFIELD user_conv_p : 1; + BOOL_BITFIELD ellipsis_p : 1; + BOOL_BITFIELD this_p : 1; + BOOL_BITFIELD bad_p : 1; + /* If KIND is ck_ref_bind ck_base_conv, true to indicate that a + temporary should be created to hold the result of the + conversion. */ + BOOL_BITFIELD need_temporary_p : 1; + /* If KIND is ck_identity or ck_base_conv, true to indicate that the + copy constructor must be accessible, even though it is not being + used. */ + BOOL_BITFIELD check_copy_constructor_p : 1; + /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion + from a pointer-to-derived to pointer-to-base is being performed. */ + BOOL_BITFIELD base_p : 1; + /* The type of the expression resulting from the conversion. */ + tree type; + union { + /* The next conversion in the chain. Since the conversions are + arranged from outermost to innermost, the NEXT conversion will + actually be performed before this conversion. This variant is + used only when KIND is neither ck_identity nor ck_ambig. */ + conversion *next; + /* The expression at the beginning of the conversion chain. This + variant is used only if KIND is ck_identity or ck_ambig. */ + tree expr; + } u; + /* The function candidate corresponding to this conversion + sequence. This field is only used if KIND is ck_user. */ + struct z_candidate *cand; + }; + + #define CONVERSION_RANK(NODE) \ + ((NODE)->bad_p ? cr_bad \ + : (NODE)->ellipsis_p ? cr_ellipsis \ + : (NODE)->user_conv_p ? cr_user \ + : (NODE)->rank) + + static struct obstack conversion_obstack; + static bool conversion_obstack_initialized; + static struct z_candidate * tourney (struct z_candidate *); static int equal_functions (tree, tree); static int joust (struct z_candidate *, struct z_candidate *, bool); ! static int compare_ics (conversion *, conversion *); static tree build_over_call (struct z_candidate *, int); static tree build_java_interface_fn_ref (tree, tree); #define convert_like(CONV, EXPR) \ ! convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \ ! /*issue_conversion_warnings=*/true, \ ! /*c_cast_p=*/false) #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \ ! convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \ ! /*issue_conversion_warnings=*/true, \ ! /*c_cast_p=*/false) ! static tree convert_like_real (conversion *, tree, tree, int, int, bool, ! bool); static void op_error (enum tree_code, enum tree_code, tree, tree, tree, const char *); static tree build_object_call (tree, tree); *************** static struct z_candidate *add_conv_cand *** 85,134 **** (struct z_candidate **, tree, tree, tree, tree, tree); static struct z_candidate *add_function_candidate (struct z_candidate **, tree, tree, tree, tree, tree, int); ! static tree implicit_conversion (tree, tree, tree, int); ! static tree standard_conversion (tree, tree, tree); ! static tree reference_binding (tree, tree, tree, int); ! static tree build_conv (enum tree_code, tree, tree); ! static bool is_subseq (tree, tree); ! static tree maybe_handle_ref_bind (tree *); ! static void maybe_handle_implicit_object (tree *); static struct z_candidate *add_candidate ! (struct z_candidate **, tree, tree, tree, tree, tree, int); ! static tree source_type (tree); static void add_warning (struct z_candidate *, struct z_candidate *); static bool reference_related_p (tree, tree); static bool reference_compatible_p (tree, tree); ! static tree convert_class_to_reference (tree, tree, tree); ! static tree direct_reference_binding (tree, tree); static bool promoted_arithmetic_type_p (tree); ! static tree conditional_conversion (tree, tree); static char *name_as_c_string (tree, tree, bool *); static tree call_builtin_trap (void); static tree prep_operand (tree); static void add_candidates (tree, tree, tree, bool, tree, tree, int, struct z_candidate **); ! static tree merge_conversion_sequences (tree, tree); static bool magic_varargs_p (tree); static tree build_temp (tree, tree, int, void (**)(const char *, ...)); static void check_constructor_callable (tree, tree); - tree - build_vfield_ref (tree datum, tree type) - { - 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) - && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type)) - datum = convert_to_base (datum, type, /*check_access=*/false); - - return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)), - datum, TYPE_VFIELD (type)); - } - /* Returns nonzero iff the destructor name specified in NAME (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many forms... */ --- 169,202 ---- (struct z_candidate **, tree, tree, tree, tree, tree); static struct z_candidate *add_function_candidate (struct z_candidate **, tree, tree, tree, tree, tree, int); ! static conversion *implicit_conversion (tree, tree, tree, int); ! static conversion *standard_conversion (tree, tree, tree, int); ! static conversion *reference_binding (tree, tree, tree, int); ! static conversion *build_conv (conversion_kind, tree, conversion *); ! static bool is_subseq (conversion *, conversion *); ! static tree maybe_handle_ref_bind (conversion **); ! static void maybe_handle_implicit_object (conversion **); static struct z_candidate *add_candidate ! (struct z_candidate **, tree, tree, size_t, ! conversion **, tree, tree, int); ! static tree source_type (conversion *); static void add_warning (struct z_candidate *, struct z_candidate *); static bool reference_related_p (tree, tree); static bool reference_compatible_p (tree, tree); ! static conversion *convert_class_to_reference (tree, tree, tree); ! static conversion *direct_reference_binding (tree, conversion *); static bool promoted_arithmetic_type_p (tree); ! static conversion *conditional_conversion (tree, tree); static char *name_as_c_string (tree, tree, bool *); static tree call_builtin_trap (void); static tree prep_operand (tree); static void add_candidates (tree, tree, tree, bool, tree, tree, int, struct z_candidate **); ! static conversion *merge_conversion_sequences (conversion *, conversion *); static bool magic_varargs_p (tree); static tree build_temp (tree, tree, int, void (**)(const char *, ...)); static void check_constructor_callable (tree, tree); /* Returns nonzero iff the destructor name specified in NAME (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many forms... */ *************** check_dtor_name (tree basetype, tree nam *** 155,171 **** else name = get_type_value (name); } - /* In the case of: - - template struct S { ~S(); }; - int i; - i.~S(); - - NAME will be a class template. */ - else if (DECL_CLASS_TEMPLATE_P (name)) - return false; else ! abort (); if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name)) return true; --- 223,240 ---- else name = get_type_value (name); } else ! { ! /* In the case of: ! ! template struct S { ~S(); }; ! int i; ! i.~S(); ! ! NAME will be a class template. */ ! gcc_assert (DECL_CLASS_TEMPLATE_P (name)); ! return false; ! } if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name)) return true; *************** build_call (tree function, tree parms) *** 249,259 **** /* We invoke build_call directly for several library functions. These may have been declared normally if we're building libgcc, so we can't just check DECL_ARTIFICIAL. */ ! if (DECL_ARTIFICIAL (decl) ! || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "__", 2)) ! mark_used (decl); ! else ! abort (); } /* Don't pass empty class objects by value. This is useful --- 318,327 ---- /* We invoke build_call directly for several library functions. These may have been declared normally if we're building libgcc, so we can't just check DECL_ARTIFICIAL. */ ! gcc_assert (DECL_ARTIFICIAL (decl) ! || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), ! "__", 2)); ! mark_used (decl); } /* Don't pass empty class objects by value. This is useful *************** build_call (tree function, tree parms) *** 264,275 **** if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) { ! tree t = build (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp))); ! TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t), ! TREE_VALUE (tmp), t); } ! function = build (CALL_EXPR, result_type, function, parms); TREE_HAS_CONSTRUCTOR (function) = is_constructor; TREE_NOTHROW (function) = nothrow; --- 332,343 ---- if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) { ! tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp))); ! TREE_VALUE (tmp) = build2 (COMPOUND_EXPR, TREE_TYPE (t), ! TREE_VALUE (tmp), t); } ! function = build3 (CALL_EXPR, result_type, function, parms, NULL_TREE); TREE_HAS_CONSTRUCTOR (function) = is_constructor; TREE_NOTHROW (function) = nothrow; *************** build_call (tree function, tree parms) *** 309,315 **** /* New overloading code. */ ! struct z_candidate GTY(()) { /* The FUNCTION_DECL that will be called if this candidate is selected by overload resolution. */ tree fn; --- 377,391 ---- /* New overloading code. */ ! typedef struct z_candidate z_candidate; ! ! typedef struct candidate_warning candidate_warning; ! struct candidate_warning { ! z_candidate *loser; ! candidate_warning *next; ! }; ! ! struct z_candidate { /* The FUNCTION_DECL that will be called if this candidate is selected by overload resolution. */ tree fn; *************** struct z_candidate GTY(()) { *** 317,327 **** tree args; /* The implicit conversion sequences for each of the arguments to FN. */ ! tree convs; /* If FN is a user-defined conversion, the standard conversion sequence from the type returned by FN to the desired destination type. */ ! tree second_conv; int viable; /* 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 --- 393,405 ---- tree args; /* The implicit conversion sequences for each of the arguments to FN. */ ! conversion **convs; ! /* The number of implicit conversion sequences. */ ! size_t num_convs; /* If FN is a user-defined conversion, the standard conversion sequence from the type returned by FN to the desired destination type. */ ! conversion *second_conv; int viable; /* 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 *************** struct z_candidate GTY(()) { *** 335,378 **** 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; }; - #define IDENTITY_RANK 0 - #define EXACT_RANK 1 - #define PROMO_RANK 2 - #define STD_RANK 3 - #define PBOOL_RANK 4 - #define USER_RANK 5 - #define ELLIPSIS_RANK 6 - #define BAD_RANK 7 - - #define ICS_RANK(NODE) \ - (ICS_BAD_FLAG (NODE) ? BAD_RANK \ - : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ - : ICS_USER_FLAG (NODE) ? USER_RANK \ - : ICS_STD_RANK (NODE)) - - #define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE) - - #define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE) - #define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) - #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE) - #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE) - - /* In a REF_BIND or a BASE_CONV, this indicates that a temporary - should be created to hold the result of the conversion. */ - #define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE) - - /* TRUE in an IDENTITY_CONV or BASE_CONV if the copy constructor must - be accessible, even though it is not being used. */ - #define CHECK_COPY_CONSTRUCTOR_P(NODE) TREE_LANG_FLAG_5 (NODE) - - #define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1)) - #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn) - /* Returns true iff T is a null pointer constant in the sense of [conv.ptr]. */ --- 413,423 ---- the `this' pointer must correspond to the most derived class indicated by the CONVERSION_PATH. */ tree conversion_path; ! tree template_decl; ! candidate_warning *warnings; ! z_candidate *next; }; /* Returns true iff T is a null pointer constant in the sense of [conv.ptr]. */ *************** null_ptr_cst_p (tree t) *** 383,397 **** A null pointer constant is an integral constant expression (_expr.const_) rvalue of integer type that evaluates to zero. */ ! if (DECL_INTEGRAL_CONSTANT_VAR_P (t)) ! t = decl_constant_value (t); if (t == null_node || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))) return true; return false; } - /* Returns nonzero if PARMLIST consists of only default parms and/or ellipsis. */ --- 428,440 ---- A null pointer constant is an integral constant expression (_expr.const_) rvalue of integer type that evaluates to zero. */ ! t = integral_constant_value (t); if (t == null_node || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))) return true; return false; } /* Returns nonzero if PARMLIST consists of only default parms and/or ellipsis. */ *************** sufficient_parms_p (tree parmlist) *** 405,446 **** return true; } ! static tree ! build_conv (enum tree_code code, tree type, tree from) { ! tree t; ! int rank = ICS_STD_RANK (from); /* We can't use buildl1 here because CODE could be USER_CONV, which takes two arguments. In that case, the caller is responsible for filling in the second argument. */ ! t = make_node (code); ! TREE_TYPE (t) = type; ! TREE_OPERAND (t, 0) = from; switch (code) { ! case PTR_CONV: ! case PMEM_CONV: ! case BASE_CONV: ! case STD_CONV: ! if (rank < STD_RANK) ! rank = STD_RANK; break; ! case QUAL_CONV: ! if (rank < EXACT_RANK) ! rank = EXACT_RANK; default: break; } ! ICS_STD_RANK (t) = rank; ! ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from)); ! ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from); return t; } tree strip_top_quals (tree t) { --- 448,573 ---- return true; } ! /* Allocate N bytes of memory from the conversion obstack. The memory ! is zeroed before being returned. */ ! ! static void * ! conversion_obstack_alloc (size_t n) { ! void *p; ! if (!conversion_obstack_initialized) ! { ! gcc_obstack_init (&conversion_obstack); ! conversion_obstack_initialized = true; ! } ! p = obstack_alloc (&conversion_obstack, n); ! memset (p, 0, n); ! return p; ! } ! ! /* Dynamically allocate a conversion. */ ! ! static conversion * ! alloc_conversion (conversion_kind kind) ! { ! conversion *c; ! c = conversion_obstack_alloc (sizeof (conversion)); ! c->kind = kind; ! return c; ! } ! ! #ifdef ENABLE_CHECKING ! ! /* Make sure that all memory on the conversion obstack has been ! freed. */ ! ! void ! validate_conversion_obstack (void) ! { ! if (conversion_obstack_initialized) ! gcc_assert ((obstack_next_free (&conversion_obstack) ! == obstack_base (&conversion_obstack))); ! } ! ! #endif /* ENABLE_CHECKING */ ! ! /* Dynamically allocate an array of N conversions. */ ! ! static conversion ** ! alloc_conversions (size_t n) ! { ! return conversion_obstack_alloc (n * sizeof (conversion *)); ! } ! ! static conversion * ! build_conv (conversion_kind code, tree type, conversion *from) ! { ! conversion *t; ! conversion_rank rank = CONVERSION_RANK (from); /* We can't use buildl1 here because CODE could be USER_CONV, which takes two arguments. In that case, the caller is responsible for filling in the second argument. */ ! t = alloc_conversion (code); ! t->type = type; ! t->u.next = from; switch (code) { ! case ck_ptr: ! case ck_pmem: ! case ck_base: ! case ck_std: ! if (rank < cr_std) ! rank = cr_std; break; ! case ck_qual: ! if (rank < cr_exact) ! rank = cr_exact; ! break; default: break; } ! t->rank = rank; ! t->user_conv_p = (code == ck_user || from->user_conv_p); ! t->bad_p = from->bad_p; ! t->base_p = false; return t; } + /* Build a representation of the identity conversion from EXPR to + itself. The TYPE should match the type of EXPR, if EXPR is non-NULL. */ + + static conversion * + build_identity_conv (tree type, tree expr) + { + conversion *c; + + c = alloc_conversion (ck_identity); + c->type = type; + c->u.expr = expr; + + return c; + } + + /* Converting from EXPR to TYPE was ambiguous in the sense that there + were multiple user-defined conversions to accomplish the job. + Build a conversion that indicates that ambiguity. */ + + static conversion * + build_ambiguous_conv (tree type, tree expr) + { + conversion *c; + + c = alloc_conversion (ck_ambig); + c->type = type; + c->u.expr = expr; + + return c; + } + tree strip_top_quals (tree t) { *************** strip_top_quals (tree t) *** 453,463 **** TO, if any. For proper handling of null pointer constants, you must also pass the expression EXPR to convert from. */ ! static tree ! standard_conversion (tree to, tree from, tree expr) { enum tree_code fcode, tcode; ! tree conv; bool fromref = false; to = non_reference (to); --- 580,590 ---- TO, if any. For proper handling of null pointer constants, you must also pass the expression EXPR to convert from. */ ! static conversion * ! standard_conversion (tree to, tree from, tree expr, int flags) { enum tree_code fcode, tcode; ! conversion *conv; bool fromref = false; to = non_reference (to); *************** standard_conversion (tree to, tree from, *** 474,502 **** { expr = instantiate_type (to, expr, tf_conv); if (expr == error_mark_node) ! return NULL_TREE; from = TREE_TYPE (expr); } fcode = TREE_CODE (from); tcode = TREE_CODE (to); ! conv = build1 (IDENTITY_CONV, from, expr); ! if (fcode == FUNCTION_TYPE) { from = build_pointer_type (from); fcode = TREE_CODE (from); ! conv = build_conv (LVALUE_CONV, from, conv); } else if (fcode == ARRAY_TYPE) { from = build_pointer_type (TREE_TYPE (from)); fcode = TREE_CODE (from); ! conv = build_conv (LVALUE_CONV, from, conv); } else if (fromref || (expr && lvalue_p (expr))) ! conv = build_conv (RVALUE_CONV, from, conv); /* Allow conversion between `__complex__' data types. */ if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE) --- 601,628 ---- { expr = instantiate_type (to, expr, tf_conv); if (expr == error_mark_node) ! return NULL; from = TREE_TYPE (expr); } fcode = TREE_CODE (from); tcode = TREE_CODE (to); ! conv = build_identity_conv (from, expr); if (fcode == FUNCTION_TYPE) { from = build_pointer_type (from); fcode = TREE_CODE (from); ! conv = build_conv (ck_lvalue, from, conv); } else if (fcode == ARRAY_TYPE) { from = build_pointer_type (TREE_TYPE (from)); fcode = TREE_CODE (from); ! conv = build_conv (ck_lvalue, from, conv); } else if (fromref || (expr && lvalue_p (expr))) ! conv = build_conv (ck_rvalue, from, conv); /* Allow conversion between `__complex__' data types. */ if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE) *************** standard_conversion (tree to, tree from, *** 504,519 **** /* The standard conversion sequence to convert FROM to TO is the standard conversion sequence to perform componentwise conversion. */ ! tree part_conv = standard_conversion ! (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE); if (part_conv) { ! conv = build_conv (TREE_CODE (part_conv), to, conv); ! ICS_STD_RANK (conv) = ICS_STD_RANK (part_conv); } else ! conv = NULL_TREE; return conv; } --- 630,645 ---- /* The standard conversion sequence to convert FROM to TO is the standard conversion sequence to perform componentwise conversion. */ ! conversion *part_conv = standard_conversion ! (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, flags); if (part_conv) { ! conv = build_conv (part_conv->kind, to, conv); ! conv->rank = part_conv->rank; } else ! conv = NULL; return conv; } *************** standard_conversion (tree to, tree from, *** 523,549 **** if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)) && expr && null_ptr_cst_p (expr)) ! conv = build_conv (STD_CONV, to, conv); ! else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE ! && TREE_CODE (TREE_TYPE (to)) == VECTOR_TYPE ! && TREE_CODE (TREE_TYPE (from)) == VECTOR_TYPE ! && ((*targetm.vector_opaque_p) (TREE_TYPE (to)) ! || (*targetm.vector_opaque_p) (TREE_TYPE (from)))) ! conv = build_conv (STD_CONV, to, conv); else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE) || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE)) { /* For backwards brain damage compatibility, allow interconversion of pointers and integers with a pedwarn. */ ! conv = build_conv (STD_CONV, to, conv); ! ICS_BAD_FLAG (conv) = 1; } else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE) { /* For backwards brain damage compatibility, allow interconversion of enums and integers with a pedwarn. */ ! conv = build_conv (STD_CONV, to, conv); ! ICS_BAD_FLAG (conv) = 1; } else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE) || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from))) --- 649,669 ---- if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)) && expr && null_ptr_cst_p (expr)) ! conv = build_conv (ck_std, to, conv); else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE) || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE)) { /* For backwards brain damage compatibility, allow interconversion of pointers and integers with a pedwarn. */ ! conv = build_conv (ck_std, to, conv); ! conv->bad_p = true; } else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE) { /* For backwards brain damage compatibility, allow interconversion of enums and integers with a pedwarn. */ ! conv = build_conv (ck_std, to, conv); ! conv->bad_p = true; } else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE) || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from))) *************** standard_conversion (tree to, tree from, *** 562,568 **** from = build_pointer_type (cp_build_qualified_type (void_type_node, cp_type_quals (TREE_TYPE (from)))); ! conv = build_conv (PTR_CONV, from, conv); } else if (TYPE_PTRMEM_P (from)) { --- 682,688 ---- from = build_pointer_type (cp_build_qualified_type (void_type_node, cp_type_quals (TREE_TYPE (from)))); ! conv = build_conv (ck_ptr, from, conv); } else if (TYPE_PTRMEM_P (from)) { *************** standard_conversion (tree to, tree from, *** 576,582 **** { from = build_ptrmem_type (tbase, TYPE_PTRMEM_POINTED_TO_TYPE (from)); ! conv = build_conv (PMEM_CONV, from, conv); } else if (!same_type_p (fbase, tbase)) return NULL; --- 696,702 ---- { from = build_ptrmem_type (tbase, TYPE_PTRMEM_POINTED_TO_TYPE (from)); ! conv = build_conv (ck_pmem, from, conv); } else if (!same_type_p (fbase, tbase)) return NULL; *************** standard_conversion (tree to, tree from, *** 591,606 **** _class.derived_) of D. If B is an inaccessible (clause _class.access_) or ambiguous (_class.member.lookup_) base class of D, a program ! that necessitates this conversion is ill-formed. */ ! /* Therefore, we use DERIVED_FROM_P, and not ! ACESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test. */ && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) { from = cp_build_qualified_type (TREE_TYPE (to), cp_type_quals (TREE_TYPE (from))); from = build_pointer_type (from); ! conv = build_conv (PTR_CONV, from, conv); } if (tcode == POINTER_TYPE) --- 711,727 ---- _class.derived_) of D. If B is an inaccessible (clause _class.access_) or ambiguous (_class.member.lookup_) base class of D, a program ! that necessitates this conversion is ill-formed. ! Therefore, we use DERIVED_FROM_P, and do not check ! access or uniqueness. */ && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) { from = cp_build_qualified_type (TREE_TYPE (to), cp_type_quals (TREE_TYPE (from))); from = build_pointer_type (from); ! conv = build_conv (ck_ptr, from, conv); ! conv->base_p = true; } if (tcode == POINTER_TYPE) *************** standard_conversion (tree to, tree from, *** 617,633 **** if (same_type_p (from, to)) /* OK */; else if (comp_ptr_ttypes (to_pointee, from_pointee)) ! conv = build_conv (QUAL_CONV, to, conv); else if (expr && string_conv_p (to, expr, 0)) /* converting from string constant to char *. */ ! conv = build_conv (QUAL_CONV, to, conv); else if (ptr_reasonably_similar (to_pointee, from_pointee)) { ! conv = build_conv (PTR_CONV, to, conv); ! ICS_BAD_FLAG (conv) = 1; } else ! return 0; from = to; } --- 738,754 ---- if (same_type_p (from, to)) /* OK */; else if (comp_ptr_ttypes (to_pointee, from_pointee)) ! conv = build_conv (ck_qual, to, conv); else if (expr && string_conv_p (to, expr, 0)) /* converting from string constant to char *. */ ! conv = build_conv (ck_qual, to, conv); else if (ptr_reasonably_similar (to_pointee, from_pointee)) { ! conv = build_conv (ck_ptr, to, conv); ! conv->bad_p = true; } else ! return NULL; from = to; } *************** standard_conversion (tree to, tree from, *** 650,656 **** TREE_TYPE (fromfn), TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); from = build_ptrmemfunc_type (build_pointer_type (from)); ! conv = build_conv (PMEM_CONV, from, conv); } else if (tcode == BOOLEAN_TYPE) { --- 771,778 ---- TREE_TYPE (fromfn), TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); from = build_ptrmemfunc_type (build_pointer_type (from)); ! conv = build_conv (ck_pmem, from, conv); ! conv->base_p = true; } else if (tcode == BOOLEAN_TYPE) { *************** standard_conversion (tree to, tree from, *** 663,678 **** || fcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (from)) { ! conv = build_conv (STD_CONV, to, conv); if (fcode == POINTER_TYPE || TYPE_PTRMEM_P (from) || (TYPE_PTRMEMFUNC_P (from) ! && ICS_STD_RANK (conv) < PBOOL_RANK)) ! ICS_STD_RANK (conv) = PBOOL_RANK; return conv; } ! return NULL_TREE; } /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ --- 785,800 ---- || fcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (from)) { ! conv = build_conv (ck_std, to, conv); if (fcode == POINTER_TYPE || TYPE_PTRMEM_P (from) || (TYPE_PTRMEMFUNC_P (from) ! && conv->rank < cr_pbool)) ! conv->rank = cr_pbool; return conv; } ! return NULL; } /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ *************** standard_conversion (tree to, tree from, *** 681,711 **** { if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) return 0; ! conv = build_conv (STD_CONV, to, conv); /* Give this a better rank if it's a promotion. */ if (same_type_p (to, type_promotes_to (from)) ! && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK) ! ICS_STD_RANK (conv) = PROMO_RANK; } else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE ! && ((*targetm.vector_opaque_p) (from) ! || (*targetm.vector_opaque_p) (to))) ! return build_conv (STD_CONV, to, conv); ! else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) && is_properly_derived_from (from, to)) { ! if (TREE_CODE (conv) == RVALUE_CONV) ! conv = TREE_OPERAND (conv, 0); ! conv = build_conv (BASE_CONV, to, conv); /* The derived-to-base conversion indicates the initialization of a parameter with base type from an object of a derived type. A temporary object is created to hold the result of the conversion. */ ! NEED_TEMPORARY_P (conv) = 1; } else ! return 0; return conv; } --- 803,833 ---- { if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) return 0; ! conv = build_conv (ck_std, to, conv); /* Give this a better rank if it's a promotion. */ if (same_type_p (to, type_promotes_to (from)) ! && conv->u.next->rank <= cr_promotion) ! conv->rank = cr_promotion; } else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE ! && vector_types_convertible_p (from, to)) ! return build_conv (ck_std, to, conv); ! else if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE) ! && IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) && is_properly_derived_from (from, to)) { ! if (conv->kind == ck_rvalue) ! conv = conv->u.next; ! conv = build_conv (ck_base, to, conv); /* The derived-to-base conversion indicates the initialization of a parameter with base type from an object of a derived type. A temporary object is created to hold the result of the conversion. */ ! conv->need_temporary_p = true; } else ! return NULL; return conv; } *************** reference_compatible_p (tree t1, tree t2 *** 745,756 **** /* Determine whether or not the EXPR (of class type S) can be converted to T as in [over.match.ref]. */ ! static tree convert_class_to_reference (tree t, tree s, tree expr) { tree conversions; tree arglist; ! tree conv; tree reference_type; struct z_candidate *candidates; struct z_candidate *cand; --- 867,878 ---- /* Determine whether or not the EXPR (of class type S) can be converted to T as in [over.match.ref]. */ ! static conversion * convert_class_to_reference (tree t, tree s, tree expr) { tree conversions; tree arglist; ! conversion *conv; tree reference_type; struct z_candidate *candidates; struct z_candidate *cand; *************** convert_class_to_reference (tree t, tree *** 758,764 **** conversions = lookup_conversions (s); if (!conversions) ! return NULL_TREE; /* [over.match.ref] --- 880,886 ---- conversions = lookup_conversions (s); if (!conversions) ! return NULL; /* [over.match.ref] *************** convert_class_to_reference (tree t, tree *** 782,789 **** error messages, which we should not issue now because we are just trying to find a conversion operator. Therefore, we use NULL, cast to the appropriate type. */ ! arglist = build_int_2 (0, 0); ! TREE_TYPE (arglist) = build_pointer_type (s); arglist = build_tree_list (NULL_TREE, arglist); reference_type = build_reference_type (t); --- 904,910 ---- error messages, which we should not issue now because we are just trying to find a conversion operator. Therefore, we use NULL, cast to the appropriate type. */ ! arglist = build_int_cst (build_pointer_type (s), 0); arglist = build_tree_list (NULL_TREE, arglist); reference_type = build_reference_type (t); *************** convert_class_to_reference (tree t, tree *** 838,854 **** 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))); ! ICS_BAD_FLAG (cand->second_conv) ! |= ICS_BAD_FLAG (TREE_VEC_ELT (cand->convs, 0)); } } conversions = TREE_CHAIN (conversions); --- 959,976 ---- if (cand) { + conversion *identity_conv; /* Build a standard conversion sequence indicating the binding from the reference type returned by the function to the desired REFERENCE_TYPE. */ + identity_conv + = build_identity_conv (TREE_TYPE (TREE_TYPE + (TREE_TYPE (cand->fn))), + NULL_TREE); cand->second_conv = (direct_reference_binding ! (reference_type, identity_conv)); ! cand->second_conv->bad_p |= cand->convs[0]->bad_p; } } conversions = TREE_CHAIN (conversions); *************** convert_class_to_reference (tree t, tree *** 858,868 **** /* If none of the conversion functions worked out, let our caller know. */ if (!any_viable_p) ! return NULL_TREE; cand = tourney (candidates); if (!cand) ! return NULL_TREE; /* Now that we know that this is the function we're going to use fix the dummy first argument. */ --- 980,990 ---- /* If none of the conversion functions worked out, let our caller know. */ if (!any_viable_p) ! return NULL; cand = tourney (candidates); if (!cand) ! return NULL; /* Now that we know that this is the function we're going to use fix the dummy first argument. */ *************** convert_class_to_reference (tree t, tree *** 872,888 **** /* 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; return cand->second_conv; } --- 994,1010 ---- /* Build a user-defined conversion sequence representing the conversion. */ ! conv = build_conv (ck_user, TREE_TYPE (TREE_TYPE (cand->fn)), ! build_identity_conv (TREE_TYPE (expr), expr)); ! conv->cand = 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) ! conv->bad_p = true; return cand->second_conv; } *************** convert_class_to_reference (tree t, tree *** 891,904 **** expression represented by the implicit conversion sequence CONV. Return a conversion sequence for this binding. */ ! static tree ! direct_reference_binding (tree type, tree conv) { 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); --- 1013,1025 ---- expression represented by the implicit conversion sequence CONV. Return a conversion sequence for this binding. */ ! static conversion * ! direct_reference_binding (tree type, conversion *conv) { tree t; ! gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); ! gcc_assert (TREE_CODE (conv->type) != REFERENCE_TYPE); t = TREE_TYPE (type); *************** direct_reference_binding (tree type, tre *** 918,933 **** either an identity conversion or, if the conversion function returns an entity of a type that is a derived class of the parameter type, a derived-to-base conversion. */ ! if (!same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (conv))) { /* Represent the derived-to-base conversion. */ ! conv = build_conv (BASE_CONV, t, conv); /* We will actually be binding to the base-class subobject in the derived class, so we mark this conversion appropriately. That way, convert_like knows not to generate a temporary. */ ! NEED_TEMPORARY_P (conv) = 0; } ! return build_conv (REF_BIND, type, conv); } /* Returns the conversion path from type FROM to reference type TO for --- 1039,1054 ---- either an identity conversion or, if the conversion function returns an entity of a type that is a derived class of the parameter type, a derived-to-base conversion. */ ! if (!same_type_ignoring_top_level_qualifiers_p (t, conv->type)) { /* Represent the derived-to-base conversion. */ ! conv = build_conv (ck_base, t, conv); /* We will actually be binding to the base-class subobject in the derived class, so we mark this conversion appropriately. That way, convert_like knows not to generate a temporary. */ ! conv->need_temporary_p = false; } ! return build_conv (ck_ref_bind, type, conv); } /* Returns the conversion path from type FROM to reference type TO for *************** direct_reference_binding (tree type, tre *** 936,945 **** reference will be bound to a temporary, NEED_TEMPORARY_P is set for the conversion returned. */ ! static tree reference_binding (tree rto, tree rfrom, tree expr, int flags) { ! tree conv = NULL_TREE; tree to = TREE_TYPE (rto); tree from = rfrom; bool related_p; --- 1057,1066 ---- reference will be bound to a temporary, NEED_TEMPORARY_P is set for the conversion returned. */ ! static conversion * reference_binding (tree rto, tree rfrom, tree expr, int flags) { ! conversion *conv = NULL; tree to = TREE_TYPE (rto); tree from = rfrom; bool related_p; *************** reference_binding (tree rto, tree rfrom, *** 950,956 **** { expr = instantiate_type (to, expr, tf_none); if (expr == error_mark_node) ! return NULL_TREE; from = TREE_TYPE (expr); } --- 1071,1077 ---- { expr = instantiate_type (to, expr, tf_none); if (expr == error_mark_node) ! return NULL; from = TREE_TYPE (expr); } *************** reference_binding (tree rto, tree rfrom, *** 980,986 **** the reference is bound directly to the initializer expression lvalue. */ ! conv = build1 (IDENTITY_CONV, from, expr); conv = direct_reference_binding (rto, conv); if ((lvalue_p & clk_bitfield) != 0 || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to))) --- 1101,1107 ---- the reference is bound directly to the initializer expression lvalue. */ ! conv = build_identity_conv (from, expr); conv = direct_reference_binding (rto, conv); if ((lvalue_p & clk_bitfield) != 0 || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to))) *************** reference_binding (tree rto, tree rfrom, *** 995,1001 **** reference is volatile, or isn't const, then we cannot make a temporary, so we just issue an error when the conversion actually occurs. */ ! NEED_TEMPORARY_P (conv) = 1; return conv; } --- 1116,1122 ---- reference is volatile, or isn't const, then we cannot make a temporary, so we just issue an error when the conversion actually occurs. */ ! conv->need_temporary_p = true; return conv; } *************** reference_binding (tree rto, tree rfrom, *** 1022,1028 **** /* From this point on, we conceptually need temporaries, even if we elide them. Only the cases above are "direct bindings". */ if (flags & LOOKUP_NO_TEMP_BIND) ! return NULL_TREE; /* [over.ics.rank] --- 1143,1149 ---- /* From this point on, we conceptually need temporaries, even if we elide them. Only the cases above are "direct bindings". */ if (flags & LOOKUP_NO_TEMP_BIND) ! return NULL; /* [over.ics.rank] *************** reference_binding (tree rto, tree rfrom, *** 1039,1045 **** Otherwise, the reference shall be to a non-volatile const type. */ if (!CP_TYPE_CONST_NON_VOLATILE_P (to)) ! return NULL_TREE; /* [dcl.init.ref] --- 1160,1166 ---- Otherwise, the reference shall be to a non-volatile const type. */ if (!CP_TYPE_CONST_NON_VOLATILE_P (to)) ! return NULL; /* [dcl.init.ref] *************** reference_binding (tree rto, tree rfrom, *** 1059,1068 **** conversion, just as for direct binding. */ if (CLASS_TYPE_P (from) && compatible_p) { ! conv = build1 (IDENTITY_CONV, from, expr); conv = direct_reference_binding (rto, conv); if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE)) ! CHECK_COPY_CONSTRUCTOR_P (TREE_OPERAND (conv, 0)) = 1; return conv; } --- 1180,1189 ---- conversion, just as for direct binding. */ if (CLASS_TYPE_P (from) && compatible_p) { ! conv = build_identity_conv (from, expr); conv = direct_reference_binding (rto, conv); if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE)) ! conv->u.next->check_copy_constructor_p = true; return conv; } *************** reference_binding (tree rto, tree rfrom, *** 1074,1089 **** T2, cv1 must be the same cv-qualification as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. */ if (related_p && !at_least_as_qualified_p (to, from)) ! return NULL_TREE; conv = implicit_conversion (to, from, expr, flags); if (!conv) ! return NULL_TREE; ! conv = build_conv (REF_BIND, rto, conv); /* This reference binding, unlike those above, requires the creation of a temporary. */ ! NEED_TEMPORARY_P (conv) = 1; return conv; } --- 1195,1210 ---- T2, cv1 must be the same cv-qualification as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. */ if (related_p && !at_least_as_qualified_p (to, from)) ! return NULL; conv = implicit_conversion (to, from, expr, flags); if (!conv) ! return NULL; ! conv = build_conv (ck_ref_bind, rto, conv); /* This reference binding, unlike those above, requires the creation of a temporary. */ ! conv->need_temporary_p = true; return conv; } *************** reference_binding (tree rto, tree rfrom, *** 1093,1111 **** FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is significant. */ ! static tree implicit_conversion (tree to, tree from, tree expr, int flags) { ! tree conv; if (from == error_mark_node || to == error_mark_node || expr == error_mark_node) ! return NULL_TREE; if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, flags); else ! conv = standard_conversion (to, from, expr); if (conv) return conv; --- 1214,1232 ---- FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is significant. */ ! static conversion * implicit_conversion (tree to, tree from, tree expr, int flags) { ! conversion *conv; if (from == error_mark_node || to == error_mark_node || expr == error_mark_node) ! return NULL; if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, flags); else ! conv = standard_conversion (to, from, expr, flags); if (conv) return conv; *************** implicit_conversion (tree to, tree from, *** 1128,1134 **** return conv; } ! return NULL_TREE; } /* Add a new entry to the list of candidates. Used by the add_*_candidate --- 1249,1255 ---- return conv; } ! return NULL; } /* Add a new entry to the list of candidates. Used by the add_*_candidate *************** implicit_conversion (tree to, tree from, *** 1136,1149 **** static struct z_candidate * add_candidate (struct z_candidate **candidates, ! tree fn, tree args, tree convs, tree access_path, ! tree conversion_path, int viable) { ! struct z_candidate *cand = ggc_alloc_cleared (sizeof (struct z_candidate)); cand->fn = fn; cand->args = args; cand->convs = convs; cand->access_path = access_path; cand->conversion_path = conversion_path; cand->viable = viable; --- 1257,1274 ---- static struct z_candidate * add_candidate (struct z_candidate **candidates, ! tree fn, tree args, ! size_t num_convs, conversion **convs, ! tree access_path, tree conversion_path, ! int viable) { ! struct z_candidate *cand ! = conversion_obstack_alloc (sizeof (struct z_candidate)); cand->fn = fn; cand->args = args; cand->convs = convs; + cand->num_convs = num_convs; cand->access_path = access_path; cand->conversion_path = conversion_path; cand->viable = viable; *************** add_function_candidate (struct z_candida *** 1168,1174 **** { tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); int i, len; ! tree convs; tree parmnode, argnode; tree orig_arglist; int viable = 1; --- 1293,1299 ---- { tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); int i, len; ! conversion **convs; tree parmnode, argnode; tree orig_arglist; int viable = 1; *************** add_function_candidate (struct z_candida *** 1190,1196 **** orig_arglist = arglist; len = list_length (arglist); ! convs = make_tree_vec (len); /* 13.3.2 - Viable functions [over.match.viable] First, to be a viable function, a candidate function shall have enough --- 1315,1321 ---- orig_arglist = arglist; len = list_length (arglist); ! convs = alloc_conversions (len); /* 13.3.2 - Viable functions [over.match.viable] First, to be a viable function, a candidate function shall have enough *************** add_function_candidate (struct z_candida *** 1228,1234 **** { tree arg = TREE_VALUE (argnode); tree argtype = lvalue_type (arg); ! tree t; int is_this; if (parmnode == void_list_node) --- 1353,1359 ---- { tree arg = TREE_VALUE (argnode); tree argtype = lvalue_type (arg); ! conversion *t; int is_this; if (parmnode == void_list_node) *************** add_function_candidate (struct z_candida *** 1262,1282 **** } else { ! t = build1 (IDENTITY_CONV, argtype, arg); ! ICS_ELLIPSIS_FLAG (t) = 1; } if (t && is_this) ! ICS_THIS_FLAG (t) = 1; ! TREE_VEC_ELT (convs, i) = t; if (! t) { viable = 0; break; } ! if (ICS_BAD_FLAG (t)) viable = -1; if (parmnode) --- 1387,1407 ---- } else { ! t = build_identity_conv (argtype, arg); ! t->ellipsis_p = true; } if (t && is_this) ! t->this_p = true; ! convs[i] = t; if (! t) { viable = 0; break; } ! if (t->bad_p) viable = -1; if (parmnode) *************** add_function_candidate (struct z_candida *** 1285,1292 **** } out: ! return add_candidate (candidates, fn, orig_arglist, convs, access_path, ! conversion_path, viable); } /* Create an overload candidate for the conversion function FN which will --- 1410,1417 ---- } out: ! return add_candidate (candidates, fn, orig_arglist, len, convs, ! access_path, conversion_path, viable); } /* Create an overload candidate for the conversion function FN which will *************** add_conv_candidate (struct z_candidate * *** 1306,1319 **** { tree totype = TREE_TYPE (TREE_TYPE (fn)); int i, len, viable, flags; ! tree parmlist, convs, parmnode, argnode; for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; ) parmlist = TREE_TYPE (parmlist); parmlist = TYPE_ARG_TYPES (parmlist); len = list_length (arglist) + 1; ! convs = make_tree_vec (len); parmnode = parmlist; argnode = arglist; viable = 1; --- 1431,1445 ---- { tree totype = TREE_TYPE (TREE_TYPE (fn)); int i, len, viable, flags; ! tree parmlist, parmnode, argnode; ! conversion **convs; for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; ) parmlist = TREE_TYPE (parmlist); parmlist = TYPE_ARG_TYPES (parmlist); len = list_length (arglist) + 1; ! convs = alloc_conversions (len); parmnode = parmlist; argnode = arglist; viable = 1; *************** add_conv_candidate (struct z_candidate * *** 1327,1333 **** { tree arg = i == 0 ? obj : TREE_VALUE (argnode); tree argtype = lvalue_type (arg); ! tree t; if (i == 0) t = implicit_conversion (totype, argtype, arg, flags); --- 1453,1459 ---- { tree arg = i == 0 ? obj : TREE_VALUE (argnode); tree argtype = lvalue_type (arg); ! conversion *t; if (i == 0) t = implicit_conversion (totype, argtype, arg, flags); *************** add_conv_candidate (struct z_candidate * *** 1337,1351 **** t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); else { ! t = build1 (IDENTITY_CONV, argtype, arg); ! ICS_ELLIPSIS_FLAG (t) = 1; } ! TREE_VEC_ELT (convs, i) = t; if (! t) break; ! if (ICS_BAD_FLAG (t)) viable = -1; if (i == 0) --- 1463,1477 ---- t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); else { ! t = build_identity_conv (argtype, arg); ! t->ellipsis_p = true; } ! convs[i] = t; if (! t) break; ! if (t->bad_p) viable = -1; if (i == 0) *************** add_conv_candidate (struct z_candidate * *** 1362,1369 **** if (!sufficient_parms_p (parmnode)) viable = 0; ! return add_candidate (candidates, totype, arglist, convs, access_path, ! conversion_path, viable); } static void --- 1488,1495 ---- if (!sufficient_parms_p (parmnode)) viable = 0; ! return add_candidate (candidates, totype, arglist, len, convs, ! access_path, conversion_path, viable); } static void *************** build_builtin_candidate (struct z_candid *** 1371,1384 **** tree type1, tree type2, tree *args, tree *argtypes, int flags) { ! tree t, convs; int viable = 1, i; tree types[2]; types[0] = type1; types[1] = type2; ! convs = make_tree_vec (args[2] ? 3 : (args[1] ? 2 : 1)); for (i = 0; i < 2; ++i) { --- 1497,1513 ---- tree type1, tree type2, tree *args, tree *argtypes, int flags) { ! conversion *t; ! conversion **convs; ! size_t num_convs; int viable = 1, i; tree types[2]; types[0] = type1; types[1] = type2; ! num_convs = args[2] ? 3 : (args[1] ? 2 : 1); ! convs = alloc_conversions (num_convs); for (i = 0; i < 2; ++i) { *************** build_builtin_candidate (struct z_candid *** 1390,1415 **** { viable = 0; /* We need something for printing the candidate. */ ! t = build1 (IDENTITY_CONV, types[i], NULL_TREE); } ! else if (ICS_BAD_FLAG (t)) viable = 0; ! TREE_VEC_ELT (convs, i) = t; } /* For COND_EXPR we rearranged the arguments; undo that now. */ if (args[2]) { ! TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); ! TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); if (t) ! TREE_VEC_ELT (convs, 0) = t; else viable = 0; } ! add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs, /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE, viable); --- 1519,1545 ---- { viable = 0; /* We need something for printing the candidate. */ ! t = build_identity_conv (types[i], NULL_TREE); } ! else if (t->bad_p) viable = 0; ! convs[i] = t; } /* For COND_EXPR we rearranged the arguments; undo that now. */ if (args[2]) { ! convs[2] = convs[1]; ! convs[1] = convs[0]; t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); if (t) ! convs[0] = t; else viable = 0; } ! add_candidate (candidates, fnname, /*args=*/NULL_TREE, ! num_convs, convs, /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE, viable); *************** add_builtin_candidate (struct z_candidat *** 1771,1777 **** return; default: ! abort (); } type1 = build_reference_type (type1); break; --- 1901,1907 ---- return; default: ! gcc_unreachable (); } type1 = build_reference_type (type1); break; *************** add_builtin_candidate (struct z_candidat *** 1808,1814 **** break; default: ! abort (); } /* If we're dealing with two pointer types or two enumeral types, --- 1938,1944 ---- break; default: ! gcc_unreachable (); } /* If we're dealing with two pointer types or two enumeral types, *************** add_template_candidate_real (struct z_ca *** 2052,2058 **** if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl) || DECL_BASE_CONSTRUCTOR_P (tmpl)) ! && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl))) args_without_in_chrg = TREE_CHAIN (args_without_in_chrg); i = fn_type_unification (tmpl, explicit_targs, targs, --- 2182,2188 ---- if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl) || DECL_BASE_CONSTRUCTOR_P (tmpl)) ! && CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl))) args_without_in_chrg = TREE_CHAIN (args_without_in_chrg); i = fn_type_unification (tmpl, explicit_targs, targs, *************** add_template_candidate_real (struct z_ca *** 2122,2130 **** for this will point at template template <> S::f(int), so that we can find the definition. For the purposes of overload resolution, however, we want the original TMPL. */ ! cand->template = tree_cons (tmpl, targs, NULL_TREE); else ! cand->template = DECL_TEMPLATE_INFO (fn); return cand; } --- 2252,2260 ---- for this will point at template template <> S::f(int), so that we can find the definition. For the purposes of overload resolution, however, we want the original TMPL. */ ! cand->template_decl = tree_cons (tmpl, targs, NULL_TREE); else ! cand->template_decl = DECL_TEMPLATE_INFO (fn); return cand; } *************** any_strictly_viable (struct z_candidate *** 2202,2211 **** return false; } static tree build_this (tree obj) { ! /* Fix this to work on non-lvalues. */ return build_unary_op (ADDR_EXPR, obj, 0); } --- 2332,2349 ---- return false; } + /* OBJ is being used in an expression like "OBJ.f (...)". In other + words, it is about to become the "this" pointer for a member + function call. Take the address of the object. */ + static tree build_this (tree obj) { ! /* In a template, we are only concerned about the type of the ! expression, so we can take a shortcut. */ ! if (processing_template_decl) ! return build_address (obj); ! return build_unary_op (ADDR_EXPR, obj, 0); } *************** print_z_candidate (const char *msgstr, s *** 2234,2251 **** { if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE) { ! if (TREE_VEC_LENGTH (candidate->convs) == 3) inform ("%s %D(%T, %T, %T) ", msgstr, candidate->fn, ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)), ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)), ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 2))); ! else if (TREE_VEC_LENGTH (candidate->convs) == 2) inform ("%s %D(%T, %T) ", msgstr, candidate->fn, ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)), ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1))); else inform ("%s %D(%T) ", msgstr, candidate->fn, ! TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0))); } else if (TYPE_P (candidate->fn)) inform ("%s %T ", msgstr, candidate->fn); --- 2372,2389 ---- { if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE) { ! if (candidate->num_convs == 3) inform ("%s %D(%T, %T, %T) ", msgstr, candidate->fn, ! candidate->convs[0]->type, ! candidate->convs[1]->type, ! candidate->convs[2]->type); ! else if (candidate->num_convs == 2) inform ("%s %D(%T, %T) ", msgstr, candidate->fn, ! candidate->convs[0]->type, ! candidate->convs[1]->type); else inform ("%s %D(%T) ", msgstr, candidate->fn, ! candidate->convs[0]->type); } else if (TYPE_P (candidate->fn)) inform ("%s %T ", msgstr, candidate->fn); *************** print_z_candidates (struct z_candidate * *** 2311,2338 **** /* 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; } --- 2449,2475 ---- /* 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 two sequences into a single sequence, and return the merged sequence. */ ! static conversion * ! merge_conversion_sequences (conversion *user_seq, conversion *std_seq) { ! conversion **t; ! gcc_assert (user_seq->kind == ck_user); /* Find the end of the second conversion sequence. */ t = &(std_seq); ! while ((*t)->kind != ck_identity) ! t = &((*t)->u.next); /* Replace the identity conversion with the user conversion sequence. */ *t = user_seq; /* The entire sequence is a user-conversion sequence. */ ! std_seq->user_conv_p = true; return std_seq; } *************** build_user_type_conversion_1 (tree totyp *** 2348,2370 **** { struct z_candidate *candidates, *cand; tree fromtype = TREE_TYPE (expr); ! tree ctors = NULL_TREE, convs = NULL_TREE; tree args = NULL_TREE; bool any_viable_p; /* We represent conversion within a hierarchy using RVALUE_CONV and BASE_CONV, as specified by [over.best.ics]; these become plain constructor calls, as specified in [dcl.init]. */ ! my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype) ! || !DERIVED_FROM_P (totype, fromtype), 20011226); if (IS_AGGR_TYPE (totype)) ! ctors = lookup_fnfields (TYPE_BINFO (totype), ! complete_ctor_identifier, ! 0); if (IS_AGGR_TYPE (fromtype)) ! convs = lookup_conversions (fromtype); candidates = 0; flags |= LOOKUP_NO_CONVERSION; --- 2485,2507 ---- { struct z_candidate *candidates, *cand; tree fromtype = TREE_TYPE (expr); ! tree ctors = NULL_TREE; ! tree conv_fns = NULL_TREE; ! conversion *conv = NULL; tree args = NULL_TREE; bool any_viable_p; /* We represent conversion within a hierarchy using RVALUE_CONV and BASE_CONV, as specified by [over.best.ics]; these become plain constructor calls, as specified in [dcl.init]. */ ! gcc_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype) ! || !DERIVED_FROM_P (totype, fromtype)); if (IS_AGGR_TYPE (totype)) ! ctors = lookup_fnfields (totype, complete_ctor_identifier, 0); if (IS_AGGR_TYPE (fromtype)) ! conv_fns = lookup_conversions (fromtype); candidates = 0; flags |= LOOKUP_NO_CONVERSION; *************** build_user_type_conversion_1 (tree totyp *** 2375,2388 **** ctors = BASELINK_FUNCTIONS (ctors); ! t = build_int_2 (0, 0); ! TREE_TYPE (t) = build_pointer_type (totype); args = build_tree_list (NULL_TREE, expr); /* We should never try to call the abstract or base constructor from here. */ ! my_friendly_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) ! && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)), ! 20011226); args = tree_cons (NULL_TREE, t, args); } for (; ctors; ctors = OVL_NEXT (ctors)) --- 2512,2523 ---- ctors = BASELINK_FUNCTIONS (ctors); ! t = build_int_cst (build_pointer_type (totype), 0); args = build_tree_list (NULL_TREE, expr); /* We should never try to call the abstract or base constructor from here. */ ! gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) ! && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors))); args = tree_cons (NULL_TREE, t, args); } for (; ctors; ctors = OVL_NEXT (ctors)) *************** build_user_type_conversion_1 (tree totyp *** 2405,2420 **** flags); if (cand) ! cand->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); } ! if (convs) args = build_tree_list (NULL_TREE, build_this (expr)); ! for (; convs; convs = TREE_CHAIN (convs)) { tree fns; ! tree conversion_path = TREE_PURPOSE (convs); int convflags = LOOKUP_NO_CONVERSION; /* If we are called to convert to a reference type, we are trying to --- 2540,2555 ---- flags); if (cand) ! cand->second_conv = build_identity_conv (totype, NULL_TREE); } ! if (conv_fns) args = build_tree_list (NULL_TREE, build_this (expr)); ! for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns)) { tree fns; ! tree conversion_path = TREE_PURPOSE (conv_fns); int convflags = LOOKUP_NO_CONVERSION; /* If we are called to convert to a reference type, we are trying to *************** build_user_type_conversion_1 (tree totyp *** 2424,2430 **** 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); --- 2559,2565 ---- if (TREE_CODE (totype) == REFERENCE_TYPE) convflags |= LOOKUP_NO_TEMP_BIND; ! for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); *************** build_user_type_conversion_1 (tree totyp *** 2452,2466 **** if (cand) { ! tree ics = implicit_conversion (totype, ! TREE_TYPE (TREE_TYPE (cand->fn)), ! 0, convflags); cand->second_conv = ics; ! if (ics == NULL_TREE) cand->viable = 0; ! else if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) cand->viable = -1; } } --- 2587,2602 ---- if (cand) { ! conversion *ics ! = implicit_conversion (totype, ! TREE_TYPE (TREE_TYPE (cand->fn)), ! 0, convflags); cand->second_conv = ics; ! if (!ics) cand->viable = 0; ! else if (candidates->viable == 1 && ics->bad_p) cand->viable = -1; } } *************** build_user_type_conversion_1 (tree totyp *** 2475,2490 **** { if (flags & LOOKUP_COMPLAIN) { ! error ("conversion from `%T' to `%T' is ambiguous", fromtype, totype); print_z_candidates (candidates); } cand = candidates; /* any one will do */ ! cand->second_conv = build1 (AMBIG_CONV, totype, expr); ! ICS_USER_FLAG (cand->second_conv) = 1; 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. */ --- 2611,2626 ---- { if (flags & LOOKUP_COMPLAIN) { ! error ("conversion from %qT to %qT is ambiguous", fromtype, totype); print_z_candidates (candidates); } cand = candidates; /* any one will do */ ! cand->second_conv = build_ambiguous_conv (totype, expr); ! cand->second_conv->user_conv_p = true; if (!any_strictly_viable (candidates)) ! cand->second_conv->bad_p = true; /* If there are viable candidates, don't set ICS_BAD_FLAG; an ambiguous conversion is no worse than another user-defined conversion. */ *************** build_user_type_conversion_1 (tree totyp *** 2493,2511 **** } /* Build the user conversion sequence. */ ! convs = build_conv ! (USER_CONV, (DECL_CONSTRUCTOR_P (cand->fn) ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), ! 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) = 1; return cand; } --- 2629,2647 ---- } /* Build the user conversion sequence. */ ! conv = build_conv ! (ck_user, (DECL_CONSTRUCTOR_P (cand->fn) ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), ! build_identity_conv (TREE_TYPE (expr), expr)); ! conv->cand = cand; /* Combine it with the second conversion sequence. */ ! cand->second_conv = merge_conversion_sequences (conv, cand->second_conv); if (cand->viable == -1) ! cand->second_conv->bad_p = true; return cand; } *************** build_user_type_conversion (tree totype, *** 2518,2526 **** if (cand) { ! if (TREE_CODE (cand->second_conv) == AMBIG_CONV) return error_mark_node; ! return convert_from_reference (convert_like (cand->second_conv, expr)); } return NULL_TREE; } --- 2654,2663 ---- if (cand) { ! if (cand->second_conv->kind == ck_ambig) return error_mark_node; ! expr = convert_like (cand->second_conv, expr); ! return convert_from_reference (expr); } return NULL_TREE; } *************** resolve_args (tree args) *** 2542,2549 **** error ("invalid use of void expression"); return error_mark_node; } - arg = convert_from_reference (arg); - TREE_VALUE (t) = arg; } return args; } --- 2679,2684 ---- *************** perform_overload_resolution (tree fn, *** 2574,2586 **** *any_viable_p = true; /* 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) { --- 2709,2719 ---- *any_viable_p = true; /* Check FN and ARGS. */ ! gcc_assert (TREE_CODE (fn) == FUNCTION_DECL ! || TREE_CODE (fn) == TEMPLATE_DECL ! || TREE_CODE (fn) == OVERLOAD ! || TREE_CODE (fn) == TEMPLATE_ID_EXPR); ! gcc_assert (!args || TREE_CODE (args) == TREE_LIST); if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) { *************** build_new_function_call (tree fn, tree a *** 2612,2622 **** --- 2745,2760 ---- { struct z_candidate *candidates, *cand; bool any_viable_p; + void *p; + tree result; args = resolve_args (args); if (args == error_mark_node) return error_mark_node; + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p); if (!cand) *************** build_new_function_call (tree fn, tree a *** 2626,2642 **** if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) fn = TREE_OPERAND (fn, 0); if (!any_viable_p) ! error ("no matching function for call to `%D(%A)'", DECL_NAME (OVL_CURRENT (fn)), args); else ! error ("call of overloaded `%D(%A)' is ambiguous", DECL_NAME (OVL_CURRENT (fn)), args); if (candidates) print_z_candidates (candidates); ! return error_mark_node; } ! return build_over_call (cand, LOOKUP_NORMAL); } /* Build a call to a global operator new. FNNAME is the name of the --- 2764,2785 ---- if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) fn = TREE_OPERAND (fn, 0); if (!any_viable_p) ! error ("no matching function for call to %<%D(%A)%>", DECL_NAME (OVL_CURRENT (fn)), args); else ! error ("call of overloaded %<%D(%A)%> is ambiguous", DECL_NAME (OVL_CURRENT (fn)), args); if (candidates) print_z_candidates (candidates); ! result = error_mark_node; } + else + result = build_over_call (cand, LOOKUP_NORMAL); ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return result; } /* Build a call to a global operator new. FNNAME is the name of the *************** build_operator_new_call (tree fnname, tr *** 2660,2666 **** if (args == error_mark_node) return args; ! fns = lookup_function_nonclass (fnname, args); /* Figure out what function is being called. */ cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p); --- 2803,2818 ---- if (args == error_mark_node) return args; ! /* Based on: ! ! [expr.new] ! ! If this lookup fails to find the name, or if the allocated type ! is not a class type, the allocation function's name is looked ! up in the global scope. ! ! we disregard block-scope declarations of "operator new". */ ! fns = lookup_function_nonclass (fnname, args, /*block_p=*/false); /* Figure out what function is being called. */ cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p); *************** build_operator_new_call (tree fnname, tr *** 2670,2679 **** if (!cand) { if (!any_viable_p) ! error ("no matching function for call to `%D(%A)'", DECL_NAME (OVL_CURRENT (fns)), args); else ! error ("call of overloaded `%D(%A)' is ambiguous", DECL_NAME (OVL_CURRENT (fns)), args); if (candidates) print_z_candidates (candidates); --- 2822,2831 ---- if (!cand) { if (!any_viable_p) ! error ("no matching function for call to %<%D(%A)%>", DECL_NAME (OVL_CURRENT (fns)), args); else ! error ("call of overloaded %<%D(%A)%> is ambiguous", DECL_NAME (OVL_CURRENT (fns)), args); if (candidates) print_z_candidates (candidates); *************** build_object_call (tree obj, tree args) *** 2734,2739 **** --- 2886,2893 ---- tree fns, convs, mem_args = NULL_TREE; tree type = TREE_TYPE (obj); bool any_viable_p; + tree result = NULL_TREE; + void *p; if (TYPE_PTRMEMFUNC_P (type)) { *************** build_object_call (tree obj, tree args) *** 2752,2757 **** --- 2906,2914 ---- if (args == error_mark_node) return error_mark_node; + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + if (fns) { tree base = BINFO_TYPE (BASELINK_BINFO (fns)); *************** build_object_call (tree obj, tree args) *** 2805,2835 **** candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { ! error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args); print_z_candidates (candidates); ! return error_mark_node; } ! ! cand = tourney (candidates); ! if (cand == 0) { ! error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args); ! print_z_candidates (candidates); ! return error_mark_node; } ! /* Since cand->fn will be a type, not a function, for a conversion ! function, we must be careful not to unconditionally look at ! DECL_NAME here. */ ! if (TREE_CODE (cand->fn) == FUNCTION_DECL ! && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR) ! return build_over_call (cand, LOOKUP_NORMAL); ! ! obj = convert_like_with_context ! (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1); ! /* FIXME */ ! return build_function_call (obj, args); } static void --- 2962,2998 ---- candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { ! error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args); print_z_candidates (candidates); ! result = error_mark_node; } ! else { ! cand = tourney (candidates); ! if (cand == 0) ! { ! error ("call of %<(%T) (%A)%> is ambiguous", TREE_TYPE (obj), args); ! print_z_candidates (candidates); ! result = error_mark_node; ! } ! /* Since cand->fn will be a type, not a function, for a conversion ! function, we must be careful not to unconditionally look at ! DECL_NAME here. */ ! else if (TREE_CODE (cand->fn) == FUNCTION_DECL ! && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR) ! result = build_over_call (cand, LOOKUP_NORMAL); ! else ! { ! obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1); ! obj = convert_from_reference (obj); ! result = build_function_call (obj, args); ! } } ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! return result; } static void *************** op_error (enum tree_code code, enum tree *** 2846,2875 **** switch (code) { case COND_EXPR: ! error ("%s for ternary 'operator?:' in '%E ? %E : %E'", problem, arg1, arg2, arg3); break; case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: ! error ("%s for 'operator%s' in '%E%s'", problem, opname, arg1, opname); break; case ARRAY_REF: ! error ("%s for 'operator[]' in '%E[%E]'", problem, arg1, arg2); break; case REALPART_EXPR: case IMAGPART_EXPR: ! error ("%s for '%s' in '%s %E'", problem, opname, opname, arg1); break; default: if (arg2) ! error ("%s for 'operator%s' in '%E %s %E'", problem, opname, arg1, opname, arg2); else ! error ("%s for 'operator%s' in '%s%E'", problem, opname, opname, arg1); break; } --- 3009,3038 ---- switch (code) { case COND_EXPR: ! error ("%s for ternary % in %<%E ? %E : %E%>", problem, arg1, arg2, arg3); break; case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: ! error ("%s for % in %<%E%s%>", problem, opname, arg1, opname); break; case ARRAY_REF: ! error ("%s for % in %<%E[%E]%>", problem, arg1, arg2); break; case REALPART_EXPR: case IMAGPART_EXPR: ! error ("%s for %qs in %<%s %E%>", problem, opname, opname, arg1); break; default: if (arg2) ! error ("%s for % in %<%E %s %E%>", problem, opname, arg1, opname, arg2); else ! error ("%s for % in %<%s%E%>", problem, opname, opname, arg1); break; } *************** op_error (enum tree_code code, enum tree *** 2878,2889 **** /* Return the implicit conversion sequence that could be used to convert E1 to E2 in [expr.cond]. */ ! static tree conditional_conversion (tree e1, tree e2) { tree t1 = non_reference (TREE_TYPE (e1)); tree t2 = non_reference (TREE_TYPE (e2)); ! tree conv; bool good_base; /* [expr.cond] --- 3041,3052 ---- /* Return the implicit conversion sequence that could be used to convert E1 to E2 in [expr.cond]. */ ! static conversion * conditional_conversion (tree e1, tree e2) { tree t1 = non_reference (TREE_TYPE (e1)); tree t2 = non_reference (TREE_TYPE (e2)); ! conversion *conv; bool good_base; /* [expr.cond] *************** conditional_conversion (tree e1, tree e2 *** 2917,2932 **** { if (good_base && at_least_as_qualified_p (t2, t1)) { ! conv = build1 (IDENTITY_CONV, t1, e1); if (!same_type_p (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2))) ! conv = build_conv (BASE_CONV, t2, conv); else ! conv = build_conv (RVALUE_CONV, t2, conv); return conv; } else ! return NULL_TREE; } else /* [expr.cond] --- 3080,3095 ---- { if (good_base && at_least_as_qualified_p (t2, t1)) { ! conv = build_identity_conv (t1, e1); if (!same_type_p (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2))) ! conv = build_conv (ck_base, t2, conv); else ! conv = build_conv (ck_rvalue, t2, conv); return conv; } else ! return NULL; } else /* [expr.cond] *************** build_conditional_expr (tree arg1, tree *** 2945,2955 **** { tree arg2_type; tree arg3_type; ! tree result; tree result_type = NULL_TREE; bool lvalue_p = true; struct z_candidate *candidates = 0; struct z_candidate *cand; /* As a G++ extension, the second argument to the conditional can be omitted. (So that `a ? : c' is roughly equivalent to `a ? a : --- 3108,3119 ---- { tree arg2_type; tree arg3_type; ! tree result = NULL_TREE; tree result_type = NULL_TREE; bool lvalue_p = true; struct z_candidate *candidates = 0; struct z_candidate *cand; + void *p; /* As a G++ extension, the second argument to the conditional can be omitted. (So that `a ? : c' is roughly equivalent to `a ? a : *************** build_conditional_expr (tree arg1, tree *** 3014,3020 **** We must avoid calling force_rvalue for expressions of type "void" because it will complain that their value is being ! used. */ if (TREE_CODE (arg2) == THROW_EXPR && TREE_CODE (arg3) != THROW_EXPR) { --- 3178,3184 ---- We must avoid calling force_rvalue for expressions of type "void" because it will complain that their value is being ! used. */ if (TREE_CODE (arg2) == THROW_EXPR && TREE_CODE (arg3) != THROW_EXPR) { *************** build_conditional_expr (tree arg1, tree *** 3035,3041 **** result_type = void_type_node; else { ! error ("`%E' has type `void' and is not a throw-expression", VOID_TYPE_P (arg2_type) ? arg2 : arg3); return error_mark_node; } --- 3199,3205 ---- result_type = void_type_node; else { ! error ("%qE has type % and is not a throw-expression", VOID_TYPE_P (arg2_type) ? arg2 : arg3); return error_mark_node; } *************** build_conditional_expr (tree arg1, tree *** 3051,3059 **** else if (!same_type_p (arg2_type, arg3_type) && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type))) { ! tree conv2 = conditional_conversion (arg2, arg3); ! tree conv3 = conditional_conversion (arg3, arg2); /* [expr.cond] If both can be converted, or one can be converted but the --- 3215,3229 ---- else if (!same_type_p (arg2_type, arg3_type) && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type))) { ! conversion *conv2; ! conversion *conv3; + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + + conv2 = conditional_conversion (arg2, arg3); + conv3 = conditional_conversion (arg3, arg2); + /* [expr.cond] If both can be converted, or one can be converted but the *************** build_conditional_expr (tree arg1, tree *** 3063,3089 **** one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section. */ ! if ((conv2 && !ICS_BAD_FLAG (conv2) ! && conv3 && !ICS_BAD_FLAG (conv3)) ! || (conv2 && TREE_CODE (conv2) == AMBIG_CONV) ! || (conv3 && TREE_CODE (conv3) == AMBIG_CONV)) { error ("operands to ?: have different types"); ! return error_mark_node; } ! else if (conv2 && !ICS_BAD_FLAG (conv2)) { arg2 = convert_like (conv2, arg2); arg2 = convert_from_reference (arg2); arg2_type = TREE_TYPE (arg2); } ! else if (conv3 && !ICS_BAD_FLAG (conv3)) { arg3 = convert_like (conv3, arg3); arg3 = convert_from_reference (arg3); arg3_type = TREE_TYPE (arg3); } /* If, after the conversion, both operands have class type, treat the cv-qualification of both operands as if it were the union of the cv-qualification of the operands. --- 3233,3265 ---- one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section. */ ! if ((conv2 && !conv2->bad_p ! && conv3 && !conv3->bad_p) ! || (conv2 && conv2->kind == ck_ambig) ! || (conv3 && conv3->kind == ck_ambig)) { error ("operands to ?: have different types"); ! result = error_mark_node; } ! else if (conv2 && !conv2->bad_p) { arg2 = convert_like (conv2, arg2); arg2 = convert_from_reference (arg2); arg2_type = TREE_TYPE (arg2); } ! else if (conv3 && !conv3->bad_p) { arg3 = convert_like (conv3, arg3); arg3 = convert_from_reference (arg3); arg3_type = TREE_TYPE (arg3); } + /* Free all the conversions we allocated. */ + obstack_free (&conversion_obstack, p); + + if (result) + return result; + /* If, after the conversion, both operands have class type, treat the cv-qualification of both operands as if it were the union of the cv-qualification of the operands. *************** build_conditional_expr (tree arg1, tree *** 3094,3100 **** conversion to "volatile X", what is the type of the second operand after this step? Making it be "const X" (matching the first operand) seems wrong, as that discards the ! qualification without actuall performing a copy. Leaving it as "volatile X" seems wrong as that will result in the conditional expression failing altogether, even though, according to this step, the one operand could be converted to --- 3270,3276 ---- conversion to "volatile X", what is the type of the second operand after this step? Making it be "const X" (matching the first operand) seems wrong, as that discards the ! qualification without actually performing a copy. Leaving it as "volatile X" seems wrong as that will result in the conditional expression failing altogether, even though, according to this step, the one operand could be converted to *************** build_conditional_expr (tree arg1, tree *** 3132,3138 **** && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type))) { tree args[3]; ! tree conv; bool any_viable_p; /* Rearrange the arguments so that add_builtin_candidate only has --- 3308,3314 ---- && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type))) { tree args[3]; ! conversion *conv; bool any_viable_p; /* Rearrange the arguments so that add_builtin_candidate only has *************** build_conditional_expr (tree arg1, tree *** 3172,3182 **** Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section. */ ! conv = TREE_VEC_ELT (cand->convs, 0); arg1 = convert_like (conv, arg1); ! conv = TREE_VEC_ELT (cand->convs, 1); arg2 = convert_like (conv, arg2); ! conv = TREE_VEC_ELT (cand->convs, 2); arg3 = convert_like (conv, arg3); } --- 3348,3358 ---- Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section. */ ! conv = cand->convs[0]; arg1 = convert_like (conv, arg1); ! conv = cand->convs[1]; arg2 = convert_like (conv, arg2); ! conv = cand->convs[2]; arg3 = convert_like (conv, arg3); } *************** build_conditional_expr (tree arg1, tree *** 3226,3232 **** if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) ! warning ("enumeral mismatch in conditional expression: `%T' vs `%T'", arg2_type, arg3_type); else if (extra_warnings && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE --- 3402,3408 ---- if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) ! warning ("enumeral mismatch in conditional expression: %qT vs %qT", arg2_type, arg3_type); else if (extra_warnings && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE *************** build_conditional_expr (tree arg1, tree *** 3277,3283 **** } valid_operands: ! result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3)); /* We can't use result_type below, as fold might have returned a throw_expr. */ --- 3453,3460 ---- } valid_operands: ! result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1, ! arg2, arg3)); /* We can't use result_type below, as fold might have returned a throw_expr. */ *************** prep_operand (tree operand) *** 3304,3310 **** { if (operand) { - operand = convert_from_reference (operand); if (CLASS_TYPE_P (TREE_TYPE (operand)) && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand))) /* Make sure the template type is instantiated now. */ --- 3481,3486 ---- *************** build_new_op (enum tree_code code, int f *** 3387,3394 **** struct z_candidate *candidates = 0, *cand; tree arglist, fnname; tree args[3]; enum tree_code code2 = NOP_EXPR; ! tree conv; bool strict_p; bool any_viable_p; --- 3563,3573 ---- struct z_candidate *candidates = 0, *cand; tree arglist, fnname; tree args[3]; + tree result = NULL_TREE; + bool result_valid_p = false; enum tree_code code2 = NOP_EXPR; ! conversion *conv; ! void *p; bool strict_p; bool any_viable_p; *************** build_new_op (enum tree_code code, int f *** 3415,3421 **** case VEC_DELETE_EXPR: case DELETE_EXPR: /* Use build_op_new_call and build_op_delete_call instead. */ ! abort (); case CALL_EXPR: return build_object_call (arg1, arg2); --- 3594,3600 ---- case VEC_DELETE_EXPR: case DELETE_EXPR: /* Use build_op_new_call and build_op_delete_call instead. */ ! gcc_unreachable (); case CALL_EXPR: return build_object_call (arg1, arg2); *************** build_new_op (enum tree_code code, int f *** 3450,3458 **** arglist = tree_cons (NULL_TREE, arg2, arglist); arglist = tree_cons (NULL_TREE, arg1, arglist); /* Add namespace-scope operators to the list of functions to consider. */ ! add_candidates (lookup_function_nonclass (fnname, arglist), arglist, NULL_TREE, false, NULL_TREE, NULL_TREE, flags, &candidates); /* Add class-member operators to the candidate set. */ --- 3629,3640 ---- arglist = tree_cons (NULL_TREE, arg2, arglist); arglist = tree_cons (NULL_TREE, arg1, arglist); + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + /* Add namespace-scope operators to the list of functions to consider. */ ! add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true), arglist, NULL_TREE, false, NULL_TREE, NULL_TREE, flags, &candidates); /* Add class-member operators to the candidate set. */ *************** build_new_op (enum tree_code code, int f *** 3460,3468 **** { tree fns; ! fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1); if (fns == error_mark_node) ! return fns; if (fns) add_candidates (BASELINK_FUNCTIONS (fns), arglist, NULL_TREE, false, --- 3642,3653 ---- { tree fns; ! fns = lookup_fnfields (TREE_TYPE (arg1), fnname, 1); if (fns == error_mark_node) ! { ! result = error_mark_node; ! goto user_defined_result_ready; ! } if (fns) add_candidates (BASELINK_FUNCTIONS (fns), arglist, NULL_TREE, false, *************** build_new_op (enum tree_code code, int f *** 3518,3628 **** /* Look for an `operator++ (int)'. If they didn't have one, then we fall back to the old way of doing things. */ if (flags & LOOKUP_COMPLAIN) ! pedwarn ("no `%D(int)' declared for postfix `%s', trying prefix operator instead", ! fnname, ! operator_name_info[code].name); if (code == POSTINCREMENT_EXPR) code = PREINCREMENT_EXPR; else code = PREDECREMENT_EXPR; ! return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE, ! overloaded_p); ! /* The caller will deal with these. */ case ADDR_EXPR: case COMPOUND_EXPR: case COMPONENT_REF: ! return NULL_TREE; default: break; } - if (flags & LOOKUP_COMPLAIN) - { - op_error (code, code2, arg1, arg2, arg3, "no match"); - print_z_candidates (candidates); - } - return error_mark_node; } ! ! cand = tourney (candidates); ! if (cand == 0) { ! if (flags & LOOKUP_COMPLAIN) { ! op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); ! print_z_candidates (candidates); } ! return error_mark_node; ! } ! ! if (TREE_CODE (cand->fn) == FUNCTION_DECL) ! { ! if (overloaded_p) ! *overloaded_p = true; ! ! if (warn_synth ! && fnname == ansi_assopname (NOP_EXPR) ! && DECL_ARTIFICIAL (cand->fn) ! && candidates->next ! && ! candidates->next->next) { ! warning ("using synthesized `%#D' for copy assignment", ! cand->fn); ! cp_warning_at (" where cfront would use `%#D'", ! cand == candidates ! ? candidates->next->fn ! : candidates->fn); } ! return build_over_call (cand, LOOKUP_NORMAL); ! } ! /* Check for comparison of different enum types. */ ! switch (code) ! { ! case GT_EXPR: ! case LT_EXPR: ! case GE_EXPR: ! case LE_EXPR: ! case EQ_EXPR: ! case NE_EXPR: ! if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE ! && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE ! && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) ! != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))) ! { ! warning ("comparison between `%#T' and `%#T'", ! TREE_TYPE (arg1), TREE_TYPE (arg2)); } - break; - default: - break; } ! /* We need to strip any leading REF_BIND so that bitfields don't cause ! errors. This should not remove any important conversions, because ! builtins don't apply to class objects directly. */ ! conv = TREE_VEC_ELT (cand->convs, 0); ! if (TREE_CODE (conv) == REF_BIND) ! conv = TREE_OPERAND (conv, 0); ! arg1 = convert_like (conv, arg1); ! if (arg2) ! { ! conv = TREE_VEC_ELT (cand->convs, 1); ! if (TREE_CODE (conv) == REF_BIND) ! conv = TREE_OPERAND (conv, 0); ! arg2 = convert_like (conv, arg2); ! } ! if (arg3) ! { ! conv = TREE_VEC_ELT (cand->convs, 2); ! if (TREE_CODE (conv) == REF_BIND) ! conv = TREE_OPERAND (conv, 0); ! arg3 = convert_like (conv, arg3); ! } ! builtin: switch (code) { case MODIFY_EXPR: --- 3703,3823 ---- /* Look for an `operator++ (int)'. If they didn't have one, then we fall back to the old way of doing things. */ if (flags & LOOKUP_COMPLAIN) ! pedwarn ("no %<%D(int)%> declared for postfix %qs, " ! "trying prefix operator instead", ! fnname, ! operator_name_info[code].name); if (code == POSTINCREMENT_EXPR) code = PREINCREMENT_EXPR; else code = PREDECREMENT_EXPR; ! result = build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE, ! overloaded_p); ! break; ! /* The caller will deal with these. */ case ADDR_EXPR: case COMPOUND_EXPR: case COMPONENT_REF: ! result = NULL_TREE; ! result_valid_p = true; ! break; default: + if (flags & LOOKUP_COMPLAIN) + { + op_error (code, code2, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); + } + result = error_mark_node; break; } } ! else { ! cand = tourney (candidates); ! if (cand == 0) { ! if (flags & LOOKUP_COMPLAIN) ! { ! op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); ! print_z_candidates (candidates); ! } ! result = error_mark_node; } ! else if (TREE_CODE (cand->fn) == FUNCTION_DECL) { ! if (overloaded_p) ! *overloaded_p = true; ! ! result = build_over_call (cand, LOOKUP_NORMAL); } + else + { + /* Give any warnings we noticed during overload resolution. */ + if (cand->warnings) + { + struct candidate_warning *w; + for (w = cand->warnings; w; w = w->next) + joust (cand, w->loser, 1); + } ! /* Check for comparison of different enum types. */ ! switch (code) ! { ! case GT_EXPR: ! case LT_EXPR: ! case GE_EXPR: ! case LE_EXPR: ! case EQ_EXPR: ! case NE_EXPR: ! if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE ! && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE ! && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) ! != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))) ! { ! warning ("comparison between %q#T and %q#T", ! TREE_TYPE (arg1), TREE_TYPE (arg2)); ! } ! break; ! default: ! break; ! } ! /* We need to strip any leading REF_BIND so that bitfields ! don't cause errors. This should not remove any important ! conversions, because builtins don't apply to class ! objects directly. */ ! conv = cand->convs[0]; ! if (conv->kind == ck_ref_bind) ! conv = conv->u.next; ! arg1 = convert_like (conv, arg1); ! if (arg2) ! { ! conv = cand->convs[1]; ! if (conv->kind == ck_ref_bind) ! conv = conv->u.next; ! arg2 = convert_like (conv, arg2); ! } ! if (arg3) ! { ! conv = cand->convs[2]; ! if (conv->kind == ck_ref_bind) ! conv = conv->u.next; ! arg3 = convert_like (conv, arg3); ! } } } ! user_defined_result_ready: ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! if (result || result_valid_p) ! return result; ! ! builtin: switch (code) { case MODIFY_EXPR: *************** builtin: *** 3672,3679 **** return build_conditional_expr (arg1, arg2, arg3); case MEMBER_REF: ! return build_m_component_ref ! (build_indirect_ref (arg1, NULL), arg2); /* The caller will deal with these. */ case ADDR_EXPR: --- 3867,3873 ---- return build_conditional_expr (arg1, arg2, arg3); case MEMBER_REF: ! return build_m_component_ref (build_indirect_ref (arg1, NULL), arg2); /* The caller will deal with these. */ case ADDR_EXPR: *************** builtin: *** 3682,3690 **** return NULL_TREE; default: ! abort (); ! return NULL_TREE; } } /* Build a call to operator delete. This has to be handled very specially, --- 3876,3884 ---- return NULL_TREE; default: ! gcc_unreachable (); } + return NULL_TREE; } /* Build a call to operator delete. This has to be handled very specially, *************** builtin: *** 3696,3707 **** CODE is either DELETE_EXPR or VEC_DELETE_EXPR. ADDR is the pointer to be deleted. SIZE is the size of the memory block to be deleted. ! FLAGS are the usual overloading flags. PLACEMENT is the corresponding placement new call, or NULL_TREE. */ tree build_op_delete_call (enum tree_code code, tree addr, tree size, ! int flags, tree placement) { tree fn = NULL_TREE; tree fns, fnname, argtypes, args, type; --- 3890,3902 ---- CODE is either DELETE_EXPR or VEC_DELETE_EXPR. ADDR is the pointer to be deleted. SIZE is the size of the memory block to be deleted. ! GLOBAL_P is true if the delete-expression should not consider ! class-specific delete operators. PLACEMENT is the corresponding placement new call, or NULL_TREE. */ tree build_op_delete_call (enum tree_code code, tree addr, tree size, ! bool global_p, tree placement) { tree fn = NULL_TREE; tree fns, fnname, argtypes, args, type; *************** build_op_delete_call (enum tree_code cod *** 3714,3720 **** fnname = ansi_opname (code); ! if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)) /* In [class.free] If the result of the lookup is ambiguous or inaccessible, or if --- 3909,3917 ---- fnname = ansi_opname (code); ! if (CLASS_TYPE_P (type) ! && COMPLETE_TYPE_P (complete_type (type)) ! && !global_p) /* In [class.free] If the result of the lookup is ambiguous or inaccessible, or if *************** build_op_delete_call (enum tree_code cod *** 3742,3748 **** call_expr = placement; /* Extract the function. */ alloc_fn = get_callee_fndecl (call_expr); ! my_friendly_assert (alloc_fn != NULL_TREE, 20020327); /* Then the second parm type. */ argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))); /* Also the second argument. */ --- 3939,3945 ---- call_expr = placement; /* Extract the function. */ alloc_fn = get_callee_fndecl (call_expr); ! gcc_assert (alloc_fn != NULL_TREE); /* Then the second parm type. */ argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))); /* Also the second argument. */ *************** build_op_delete_call (enum tree_code cod *** 3827,3833 **** /* The placement args might not be suitable for overload resolution at this point, so build the call directly. */ mark_used (fn); ! return build_cxx_call (fn, args, args); } else return build_function_call (fn, args); --- 4024,4030 ---- /* The placement args might not be suitable for overload resolution at this point, so build the call directly. */ mark_used (fn); ! return build_cxx_call (fn, args); } else return build_function_call (fn, args); *************** build_op_delete_call (enum tree_code cod *** 3838,3844 **** if (placement) return NULL_TREE; ! error ("no suitable `operator %s' for `%T'", operator_name_info[(int)code].name, type); return error_mark_node; } --- 4035,4041 ---- if (placement) return NULL_TREE; ! error ("no suitable % for %qT", operator_name_info[(int)code].name, type); return error_mark_node; } *************** build_op_delete_call (enum tree_code cod *** 3850,3865 **** bool enforce_access (tree basetype_path, tree decl) { ! my_friendly_assert (TREE_CODE (basetype_path) == TREE_VEC, 20030624); ! if (!accessible_p (basetype_path, decl)) { if (TREE_PRIVATE (decl)) ! cp_error_at ("`%+#D' is private", decl); else if (TREE_PROTECTED (decl)) ! cp_error_at ("`%+#D' is protected", decl); else ! cp_error_at ("`%+#D' is inaccessible", decl); error ("within this context"); return false; } --- 4047,4062 ---- bool enforce_access (tree basetype_path, tree decl) { ! gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO); ! if (!accessible_p (basetype_path, decl, true)) { if (TREE_PRIVATE (decl)) ! cp_error_at ("%q+#D is private", decl); else if (TREE_PROTECTED (decl)) ! cp_error_at ("%q+#D is protected", decl); else ! cp_error_at ("%q+#D is inaccessible", decl); error ("within this context"); return false; } *************** check_constructor_callable (tree type, t *** 3876,3883 **** build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! TYPE_BINFO (type), LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING | LOOKUP_CONSTRUCTOR_CALLABLE); } --- 4073,4081 ---- build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! type, LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING + | LOOKUP_NO_CONVERSION | LOOKUP_CONSTRUCTOR_CALLABLE); } *************** build_temp (tree expr, tree type, int fl *** 3897,3904 **** expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! TYPE_BINFO (type), ! flags); if (warningcount > savew) *diagnostic_fn = warning; else if (errorcount > savee) --- 4095,4101 ---- expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! type, flags); if (warningcount > savew) *diagnostic_fn = warning; else if (errorcount > savee) *************** build_temp (tree expr, tree type, int fl *** 3915,3977 **** being called to continue a conversion chain. It is negative when a 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 (tree convs, tree expr, tree fn, int argnum, int inner, ! bool issue_conversion_warnings) { ! tree totype = TREE_TYPE (convs); void (*diagnostic_fn)(const char *, ...); ! if (ICS_BAD_FLAG (convs) ! && TREE_CODE (convs) != USER_CONV ! && TREE_CODE (convs) != AMBIG_CONV ! && TREE_CODE (convs) != REF_BIND) { ! tree t = convs; ! for (; t; t = TREE_OPERAND (t, 0)) { ! if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t)) { 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, ! /*issue_conversion_warnings=*/false); ! else if (TREE_CODE (t) == IDENTITY_CONV) break; } ! pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype); if (fn) ! pedwarn (" initializing argument %P of `%D'", argnum, fn); return cp_convert (totype, expr); } if (issue_conversion_warnings) - expr = dubious_conversion_warnings - (totype, expr, "converting", fn, argnum); - switch (TREE_CODE (convs)) { ! case USER_CONV: { ! struct z_candidate *cand = USER_CONV_CAND (convs); tree convfn = cand->fn; tree args; if (DECL_CONSTRUCTOR_P (convfn)) { ! tree t = build_int_2 (0, 0); ! TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn)); args = build_tree_list (NULL_TREE, expr); ! if (DECL_HAS_IN_CHARGE_PARM_P (convfn) ! || DECL_HAS_VTT_PARM_P (convfn)) ! /* We should never try to call the abstract or base constructor ! from here. */ ! abort (); args = tree_cons (NULL_TREE, t, args); } else --- 4112,4216 ---- being called to continue a conversion chain. It is negative when a reference binding will be applied, positive otherwise. If ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious ! conversions will be emitted if appropriate. If C_CAST_P is true, ! this conversion is coming from a C-style cast; in that case, ! conversions to inaccessible bases are permitted. */ static tree ! convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ! int inner, bool issue_conversion_warnings, ! bool c_cast_p) { ! tree totype = convs->type; void (*diagnostic_fn)(const char *, ...); ! if (convs->bad_p ! && convs->kind != ck_user ! && convs->kind != ck_ambig ! && convs->kind != ck_ref_bind) { ! conversion *t = convs; ! for (; t; t = convs->u.next) { ! if (t->kind == ck_user || !t->bad_p) { expr = convert_like_real (t, expr, fn, argnum, 1, ! /*issue_conversion_warnings=*/false, ! /*c_cast_p=*/false); break; } ! else if (t->kind == ck_ambig) return convert_like_real (t, expr, fn, argnum, 1, ! /*issue_conversion_warnings=*/false, ! /*c_cast_p=*/false); ! else if (t->kind == ck_identity) break; } ! pedwarn ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype); if (fn) ! pedwarn (" initializing argument %P of %qD", argnum, fn); return cp_convert (totype, expr); } if (issue_conversion_warnings) { ! tree t = non_reference (totype); ! ! /* Issue warnings about peculiar, but valid, uses of NULL. */ ! if (ARITHMETIC_TYPE_P (t) && expr == null_node) ! { ! if (fn) ! warning ("passing NULL to non-pointer argument %P of %qD", ! argnum, fn); ! else ! warning ("converting to non-pointer type %qT from NULL", t); ! } ! ! /* Warn about assigning a floating-point type to an integer type. */ ! if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE ! && TREE_CODE (t) == INTEGER_TYPE) ! { ! if (fn) ! warning ("passing %qT for argument %P to %qD", ! TREE_TYPE (expr), argnum, fn); ! else ! warning ("converting to %qT from %qT", t, TREE_TYPE (expr)); ! } ! /* And warn about assigning a negative value to an unsigned ! variable. */ ! else if (TYPE_UNSIGNED (t) && TREE_CODE (t) != BOOLEAN_TYPE) ! { ! if (TREE_CODE (expr) == INTEGER_CST && TREE_NEGATED_INT (expr)) ! { ! if (fn) ! warning ("passing negative value %qE for argument %P to %qD", ! expr, argnum, fn); ! else ! warning ("converting negative value %qE to %qT", expr, t); ! } ! ! overflow_warning (expr); ! } ! } ! ! switch (convs->kind) ! { ! case ck_user: { ! struct z_candidate *cand = convs->cand; tree convfn = cand->fn; tree args; if (DECL_CONSTRUCTOR_P (convfn)) { ! tree t = build_int_cst (build_pointer_type (DECL_CONTEXT (convfn)), ! 0); args = build_tree_list (NULL_TREE, expr); ! /* We should never try to call the abstract or base constructor ! from here. */ ! gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (convfn) ! && !DECL_HAS_VTT_PARM_P (convfn)); args = tree_cons (NULL_TREE, t, args); } else *************** convert_like_real (tree convs, tree expr *** 4007,4067 **** { if (fn) diagnostic_fn ! (" initializing argument %P of `%D' from result of `%D'", argnum, fn, convfn); else diagnostic_fn ! (" initializing temporary from result of `%D'", convfn); } expr = build_cplus_new (totype, expr); } return expr; } ! case IDENTITY_CONV: if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, tf_error | tf_warning); ! /* Convert a non-array constant variable to its underlying ! value, unless we are about to bind it to a reference, in ! which case we need to leave it as an lvalue. */ ! if (inner >= 0 ! && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE) ! expr = decl_constant_value (expr); ! if (CHECK_COPY_CONSTRUCTOR_P (convs)) check_constructor_callable (totype, expr); - return expr; ! case AMBIG_CONV: /* Call build_user_type_conversion again for the error. */ return build_user_type_conversion ! (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL); default: break; }; ! expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum, ! TREE_CODE (convs) == REF_BIND ? -1 : 1, ! /*issue_conversion_warnings=*/false); if (expr == error_mark_node) return error_mark_node; ! switch (TREE_CODE (convs)) { ! case RVALUE_CONV: if (! IS_AGGR_TYPE (totype)) return expr; /* Else fall through. */ ! case BASE_CONV: ! if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs)) { /* We are going to bind a reference directly to a base-class subobject of EXPR. */ ! if (CHECK_COPY_CONSTRUCTOR_P (convs)) check_constructor_callable (TREE_TYPE (expr), expr); /* Build an expression for `*((base*) &expr)'. */ expr = build_unary_op (ADDR_EXPR, expr, 0); ! expr = perform_implicit_conversion (build_pointer_type (totype), ! expr); expr = build_indirect_ref (expr, "implicit conversion"); return expr; } --- 4246,4305 ---- { if (fn) diagnostic_fn ! (" initializing argument %P of %qD from result of %qD", argnum, fn, convfn); else diagnostic_fn ! (" initializing temporary from result of %qD", convfn); } expr = build_cplus_new (totype, expr); } return expr; } ! case ck_identity: if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, tf_error | tf_warning); ! /* Convert a constant to its underlying value, unless we are ! about to bind it to a reference, in which case we need to ! leave it as an lvalue. */ ! if (inner >= 0) ! expr = integral_constant_value (expr); ! if (convs->check_copy_constructor_p) check_constructor_callable (totype, expr); return expr; ! case ck_ambig: /* Call build_user_type_conversion again for the error. */ return build_user_type_conversion ! (totype, convs->u.expr, LOOKUP_NORMAL); default: break; }; ! expr = convert_like_real (convs->u.next, expr, fn, argnum, ! convs->kind == ck_ref_bind ? -1 : 1, ! /*issue_conversion_warnings=*/false, ! c_cast_p); if (expr == error_mark_node) return error_mark_node; ! switch (convs->kind) { ! case ck_rvalue: if (! IS_AGGR_TYPE (totype)) return expr; /* Else fall through. */ ! case ck_base: ! if (convs->kind == ck_base && !convs->need_temporary_p) { /* We are going to bind a reference directly to a base-class subobject of EXPR. */ ! if (convs->check_copy_constructor_p) check_constructor_callable (TREE_TYPE (expr), expr); /* Build an expression for `*((base*) &expr)'. */ expr = build_unary_op (ADDR_EXPR, expr, 0); ! expr = convert_to_base (expr, build_pointer_type (totype), ! !c_cast_p, /*nonnull=*/true); expr = build_indirect_ref (expr, "implicit conversion"); return expr; } *************** convert_like_real (tree convs, tree expr *** 4072,4103 **** expr = build_temp (expr, totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, &diagnostic_fn); if (diagnostic_fn && fn) ! diagnostic_fn (" initializing argument %P of `%D'", argnum, fn); return build_cplus_new (totype, expr); ! case REF_BIND: { tree ref_type = totype; /* If necessary, create a temporary. */ ! if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr)) { ! tree type = TREE_TYPE (TREE_OPERAND (convs, 0)); if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))) { /* If the reference is volatile or non-const, we cannot create a temporary. */ - cp_lvalue_kind lvalue = real_lvalue_p (expr); - if (lvalue & clk_bitfield) ! error ("cannot bind bitfield `%E' to `%T'", expr, ref_type); else if (lvalue & clk_packed) ! error ("cannot bind packed field `%E' to `%T'", expr, ref_type); else ! error ("cannot bind rvalue `%E' to `%T'", expr, ref_type); return error_mark_node; } expr = build_target_expr_with_type (expr, type); --- 4310,4354 ---- expr = build_temp (expr, totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, &diagnostic_fn); if (diagnostic_fn && fn) ! diagnostic_fn (" initializing argument %P of %qD", argnum, fn); return build_cplus_new (totype, expr); ! case ck_ref_bind: { tree ref_type = totype; /* If necessary, create a temporary. */ ! if (convs->need_temporary_p || !lvalue_p (expr)) { ! tree type = convs->u.next->type; ! cp_lvalue_kind lvalue = real_lvalue_p (expr); if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))) { /* If the reference is volatile or non-const, we cannot create a temporary. */ if (lvalue & clk_bitfield) ! error ("cannot bind bitfield %qE to %qT", expr, ref_type); else if (lvalue & clk_packed) ! error ("cannot bind packed field %qE to %qT", expr, ref_type); else ! error ("cannot bind rvalue %qE to %qT", expr, ref_type); ! return error_mark_node; ! } ! /* If the source is a packed field, and we must use a copy ! constructor, then building the target expr will require ! binding the field to the reference parameter to the ! copy constructor, and we'll end up with an infinite ! loop. If we can use a bitwise copy, then we'll be ! OK. */ ! if ((lvalue & clk_packed) ! && CLASS_TYPE_P (type) ! && !TYPE_HAS_TRIVIAL_INIT_REF (type)) ! { ! error ("cannot bind packed field %qE to %qT", ! expr, ref_type); return error_mark_node; } expr = build_target_expr_with_type (expr, type); *************** convert_like_real (tree convs, tree expr *** 4118,4131 **** return build_nop (ref_type, expr); } ! case LVALUE_CONV: return decay_conversion (expr); ! case QUAL_CONV: /* Warn about deprecated conversion if appropriate. */ string_conv_p (totype, expr, 1); break; ! default: break; } --- 4369,4392 ---- return build_nop (ref_type, expr); } ! case ck_lvalue: return decay_conversion (expr); ! case ck_qual: /* Warn about deprecated conversion if appropriate. */ string_conv_p (totype, expr, 1); break; ! ! case ck_ptr: ! if (convs->base_p) ! expr = convert_to_base (expr, totype, !c_cast_p, ! /*nonnull=*/false); ! return build_nop (totype, expr); ! ! case ck_pmem: ! return convert_ptrmem (totype, expr, /*allow_inverse_p=*/false, ! c_cast_p); ! default: break; } *************** convert_like_real (tree convs, tree expr *** 4138,4146 **** static tree call_builtin_trap (void) { ! tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap")); ! my_friendly_assert (fn != NULL, 20030927); fn = build_call (fn, NULL_TREE); return fn; } --- 4399,4407 ---- static tree call_builtin_trap (void) { ! tree fn = implicit_built_in_decls[BUILT_IN_TRAP]; ! gcc_assert (fn != NULL); fn = build_call (fn, NULL_TREE); return fn; } *************** convert_arg_to_ellipsis (tree arg) *** 4182,4192 **** there is no need to emit a warning, since the expression won't be evaluated. We keep the builtin_trap just as a safety check. */ if (!skip_evaluation) ! warning ("cannot pass objects of non-POD type `%#T' through `...'; " "call will abort at runtime", TREE_TYPE (arg)); arg = call_builtin_trap (); ! arg = build (COMPOUND_EXPR, integer_type_node, arg, ! integer_zero_node); } return arg; --- 4443,4453 ---- there is no need to emit a warning, since the expression won't be evaluated. We keep the builtin_trap just as a safety check. */ if (!skip_evaluation) ! warning ("cannot pass objects of non-POD type %q#T through %<...%>; " "call will abort at runtime", TREE_TYPE (arg)); arg = call_builtin_trap (); ! arg = build2 (COMPOUND_EXPR, integer_type_node, arg, ! integer_zero_node); } return arg; *************** build_x_va_arg (tree expr, tree type) *** 4208,4219 **** if (! pod_type_p (type)) { /* Undefined behavior [expr.call] 5.2.2/7. */ ! warning ("cannot receive objects of non-POD type `%#T' through `...'; \ ! call will abort at runtime", ! type); expr = convert (build_pointer_type (type), null_node); ! expr = build (COMPOUND_EXPR, TREE_TYPE (expr), ! call_builtin_trap (), expr); expr = build_indirect_ref (expr, NULL); return expr; } --- 4469,4479 ---- if (! pod_type_p (type)) { /* Undefined behavior [expr.call] 5.2.2/7. */ ! warning ("cannot receive objects of non-POD type %q#T through %<...%>; " ! "call will abort at runtime", type); expr = convert (build_pointer_type (type), null_node); ! expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), ! call_builtin_trap (), expr); expr = build_indirect_ref (expr, NULL); return expr; } *************** convert_default_arg (tree type, tree arg *** 4252,4258 **** conversion cannot be performed. */ if (TREE_CODE (arg) == DEFAULT_ARG) { ! error ("the default argument for parameter %d of `%D' has " "not yet been parsed", parmnum, fn); return error_mark_node; --- 4512,4518 ---- conversion cannot be performed. */ if (TREE_CODE (arg) == DEFAULT_ARG) { ! error ("the default argument for parameter %d of %qD has " "not yet been parsed", parmnum, fn); return error_mark_node; *************** type_passed_as (tree type) *** 4291,4298 **** { /* 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) && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), --- 4551,4562 ---- { /* Pass classes with copy ctors by invisible reference. */ if (TREE_ADDRESSABLE (type)) ! { ! type = build_reference_type (type); ! /* There are no other pointers to this temporary. */ ! type = build_qualified_type (type, TYPE_QUAL_RESTRICT); ! } ! else if (targetm.calls.promote_prototypes (type) && INTEGRAL_TYPE_P (type) && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), *************** convert_for_arg_passing (tree type, tree *** 4312,4318 **** /* 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) && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), --- 4576,4582 ---- /* Pass classes with copy ctors by invisible reference. */ else if (TREE_ADDRESSABLE (type)) val = build1 (ADDR_EXPR, build_reference_type (type), val); ! else if (targetm.calls.promote_prototypes (type) && INTEGRAL_TYPE_P (type) && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), *************** build_over_call (struct z_candidate *can *** 4354,4363 **** { tree fn = cand->fn; tree args = cand->args; ! tree convs = cand->convs; tree converted_args = NULL_TREE; tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); ! tree conv, arg, val; int i = 0; int is_method = 0; --- 4618,4628 ---- { tree fn = cand->fn; tree args = cand->args; ! conversion **convs = cand->convs; ! conversion *conv; tree converted_args = NULL_TREE; tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); ! tree arg, val; int i = 0; int is_method = 0; *************** build_over_call (struct z_candidate *can *** 4370,4376 **** tree expr; tree return_type; return_type = TREE_TYPE (TREE_TYPE (fn)); ! expr = build (CALL_EXPR, return_type, fn, args); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; if (!VOID_TYPE_P (return_type)) --- 4635,4641 ---- tree expr; tree return_type; return_type = TREE_TYPE (TREE_TYPE (fn)); ! expr = build3 (CALL_EXPR, return_type, fn, args, NULL_TREE); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; if (!VOID_TYPE_P (return_type)) *************** build_over_call (struct z_candidate *can *** 4380,4387 **** /* Give any warnings we noticed during overload resolution. */ if (cand->warnings) ! for (val = cand->warnings; val; val = TREE_CHAIN (val)) ! joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1); if (DECL_FUNCTION_MEMBER_P (fn)) { --- 4645,4655 ---- /* Give any warnings we noticed during overload resolution. */ if (cand->warnings) ! { ! struct candidate_warning *w; ! for (w = cand->warnings; w; w = w->next) ! joust (cand, w->loser, 1); ! } if (DECL_FUNCTION_MEMBER_P (fn)) { *************** build_over_call (struct z_candidate *can *** 4411,4417 **** primary template because `B::g' and `B::g' may have different access. */ if (DECL_TEMPLATE_INFO (fn) ! && is_member_template (DECL_TI_TEMPLATE (fn))) perform_or_defer_access_check (cand->access_path, DECL_TI_TEMPLATE (fn)); else --- 4679,4685 ---- primary template because `B::g' and `B::g' may have different access. */ if (DECL_TEMPLATE_INFO (fn) ! && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn))) perform_or_defer_access_check (cand->access_path, DECL_TI_TEMPLATE (fn)); else *************** build_over_call (struct z_candidate *can *** 4429,4437 **** converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args); arg = TREE_CHAIN (arg); parm = TREE_CHAIN (parm); ! if (DECL_HAS_IN_CHARGE_PARM_P (fn)) ! /* We should never try to call the abstract constructor. */ ! abort (); if (DECL_HAS_VTT_PARM_P (fn)) { converted_args = tree_cons --- 4697,4705 ---- converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args); arg = TREE_CHAIN (arg); parm = TREE_CHAIN (parm); ! /* We should never try to call the abstract constructor. */ ! gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn)); ! if (DECL_HAS_VTT_PARM_P (fn)) { converted_args = tree_cons *************** build_over_call (struct z_candidate *can *** 4448,4456 **** 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); /* [class.mfct.nonstatic]: If a nonstatic member function of a class X is called for an object that is not of type X, or of a type --- 4716,4724 ---- tree converted_arg; tree base_binfo; ! if (convs[i]->bad_p) ! pedwarn ("passing %qT as % argument of %q#D discards qualifiers", ! TREE_TYPE (argtype), fn); /* [class.mfct.nonstatic]: If a nonstatic member function of a class X is called for an object that is not of type X, or of a type *************** build_over_call (struct z_candidate *can *** 4458,4481 **** So we can assume that anything passed as 'this' is non-null, and optimize accordingly. */ ! my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811); /* 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); /* Check that the base class is accessible. */ if (!accessible_base_p (TREE_TYPE (argtype), ! BINFO_TYPE (cand->conversion_path))) ! error ("`%T' is not an accessible base of `%T'", BINFO_TYPE (cand->conversion_path), TREE_TYPE (argtype)); /* 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); --- 4726,4749 ---- So we can assume that anything passed as 'this' is non-null, and optimize accordingly. */ ! gcc_assert (TREE_CODE (parmtype) == POINTER_TYPE); /* Convert to the base in which the function was declared. */ ! gcc_assert (cand->conversion_path != NULL_TREE); converted_arg = build_base_path (PLUS_EXPR, TREE_VALUE (arg), cand->conversion_path, 1); /* Check that the base class is accessible. */ if (!accessible_base_p (TREE_TYPE (argtype), ! BINFO_TYPE (cand->conversion_path), true)) ! error ("%qT is not an accessible base of %qT", BINFO_TYPE (cand->conversion_path), TREE_TYPE (argtype)); /* 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_unique, NULL); converted_arg = build_base_path (PLUS_EXPR, converted_arg, base_binfo, 1); *************** build_over_call (struct z_candidate *can *** 4491,4497 **** { tree type = TREE_VALUE (parm); ! conv = TREE_VEC_ELT (convs, i); val = convert_like_with_context (conv, TREE_VALUE (arg), fn, i - is_method); --- 4759,4765 ---- { tree type = TREE_VALUE (parm); ! conv = convs[i]; val = convert_like_with_context (conv, TREE_VALUE (arg), fn, i - is_method); *************** build_over_call (struct z_candidate *can *** 4521,4537 **** converted_args = nreverse (converted_args); ! if (warn_format) ! check_function_format (NULL, TYPE_ATTRIBUTES (TREE_TYPE (fn)), ! converted_args); /* Avoid actually calling copy constructors and copy assignment operators, if possible. */ if (! flag_elide_constructors) /* Do things the hard way. */; ! else if (TREE_VEC_LENGTH (convs) == 1 ! && DECL_COPY_CONSTRUCTOR_P (fn)) { tree targ; arg = skip_artificial_parms_for (fn, converted_args); --- 4789,4803 ---- converted_args = nreverse (converted_args); ! check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)), ! converted_args); /* Avoid actually calling copy constructors and copy assignment operators, if possible. */ if (! flag_elide_constructors) /* Do things the hard way. */; ! else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn)) { tree targ; arg = skip_artificial_parms_for (fn, converted_args); *************** build_over_call (struct z_candidate *can *** 4581,4587 **** tree to = stabilize_reference (build_indirect_ref (TREE_VALUE (args), 0)); ! val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg); return val; } } --- 4847,4853 ---- tree to = stabilize_reference (build_indirect_ref (TREE_VALUE (args), 0)); ! val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg); return val; } } *************** build_over_call (struct z_candidate *can *** 4594,4624 **** tree type = TREE_TYPE (to); tree as_base = CLASSTYPE_AS_BASE (type); ! arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) ! val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); else { ! /* We must only copy the non-tail padding parts. Use ! CLASSTYPE_AS_BASE for the bitwise copy. */ ! tree to_ptr, arg_ptr, to_as_base, arg_as_base, base_ptr_type; ! tree save_to; ! ! to_ptr = save_expr (build_unary_op (ADDR_EXPR, to, 0)); ! arg_ptr = build_unary_op (ADDR_EXPR, arg, 0); ! base_ptr_type = build_pointer_type (as_base); ! to_as_base = build_nop (base_ptr_type, to_ptr); ! to_as_base = build_indirect_ref (to_as_base, 0); ! arg_as_base = build_nop (base_ptr_type, arg_ptr); ! arg_as_base = build_indirect_ref (arg_as_base, 0); ! save_to = build_indirect_ref (to_ptr, 0); ! val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base); ! val = convert_to_void (val, NULL); ! val = build (COMPOUND_EXPR, type, val, save_to); ! TREE_NO_UNUSED_WARNING (val) = 1; } return val; --- 4860,4887 ---- tree type = TREE_TYPE (to); tree as_base = CLASSTYPE_AS_BASE (type); ! arg = TREE_VALUE (TREE_CHAIN (converted_args)); if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) ! { ! arg = build_indirect_ref (arg, 0); ! val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg); ! } else { ! /* We must only copy the non-tail padding parts. ! Use __builtin_memcpy for the bitwise copy. */ ! tree args, t; ! args = tree_cons (NULL, TYPE_SIZE_UNIT (as_base), NULL); ! args = tree_cons (NULL, arg, args); ! t = build_unary_op (ADDR_EXPR, to, 0); ! args = tree_cons (NULL, t, args); ! t = implicit_built_in_decls[BUILT_IN_MEMCPY]; ! t = build_call (t, args); ! t = convert (TREE_TYPE (TREE_VALUE (args)), t); ! val = build_indirect_ref (t, 0); } return val; *************** build_over_call (struct z_candidate *can *** 4632,4638 **** tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)), DECL_CONTEXT (fn), ba_any, NULL); ! my_friendly_assert (binfo && binfo != error_mark_node, 20010730); *p = build_base_path (PLUS_EXPR, *p, binfo, 1); if (TREE_SIDE_EFFECTS (*p)) --- 4895,4901 ---- tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)), DECL_CONTEXT (fn), ba_any, NULL); ! gcc_assert (binfo && binfo != error_mark_node); *p = build_base_path (PLUS_EXPR, *p, binfo, 1); if (TREE_SIDE_EFFECTS (*p)) *************** build_over_call (struct z_candidate *can *** 4641,4647 **** if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn))) fn = build_java_interface_fn_ref (fn, *p); else ! fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn)); TREE_TYPE (fn) = t; } else if (DECL_INLINE (fn)) --- 4904,4910 ---- if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn))) fn = build_java_interface_fn_ref (fn, *p); else ! fn = build_vfn_ref (*p, DECL_VINDEX (fn)); TREE_TYPE (fn) = t; } else if (DECL_INLINE (fn)) *************** build_over_call (struct z_candidate *can *** 4649,4681 **** 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))) ! { ! tree exp; ! exp = expand_tree_builtin (TREE_OPERAND (fn, 0), args, converted_args); ! if (exp) ! return exp; ! } ! ! fn = build_call (fn, converted_args); /* If this call might throw an exception, note that fact. */ fndecl = get_callee_fndecl (fn); --- 4912,4930 ---- else fn = build_addr_func (fn); ! return build_cxx_call (fn, converted_args); } ! /* Build and return a call to FN, using ARGS. This function performs no overload resolution, conversion, or other high-level operations. */ tree ! build_cxx_call (tree fn, tree args) { tree fndecl; ! fn = build_call (fn, args); /* If this call might throw an exception, note that fact. */ fndecl = get_callee_fndecl (fn); *************** build_cxx_call(tree fn, tree args, tree *** 4686,4692 **** /* 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; --- 4935,4941 ---- /* Some built-in function calls will be evaluated at compile-time in fold (). */ ! fn = fold_if_not_in_template (fn); if (VOID_TYPE_P (TREE_TYPE (fn))) return fn; *************** build_java_interface_fn_ref (tree fn, tr *** 4737,4747 **** if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL || DECL_CONTEXT (iface_ref) != iface) { ! error ("could not find class$ field in java interface type `%T'", iface); return error_mark_node; } ! iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref); /* Determine the itable index of FN. */ i = 1; --- 4986,4997 ---- if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL || DECL_CONTEXT (iface_ref) != iface) { ! error ("could not find class$ field in java interface type %qT", iface); return error_mark_node; } ! iface_ref = build_address (iface_ref); ! iface_ref = convert (build_pointer_type (iface), iface_ref); /* Determine the itable index of FN. */ i = 1; *************** build_java_interface_fn_ref (tree fn, tr *** 4753,4759 **** break; i++; } ! idx = build_int_2 (i, 0); lookup_args = tree_cons (NULL_TREE, klass_ref, tree_cons (NULL_TREE, iface_ref, --- 5003,5009 ---- break; i++; } ! idx = build_int_cst (NULL_TREE, i); lookup_args = tree_cons (NULL_TREE, klass_ref, tree_cons (NULL_TREE, iface_ref, *************** build_java_interface_fn_ref (tree fn, tr *** 4761,4776 **** lookup_fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (java_iface_lookup_fn)), java_iface_lookup_fn); ! return build (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE); } /* Returns the value to use for the in-charge parameter when making a ! call to a function with the indicated NAME. */ tree in_charge_arg_for_name (tree name) { ! if (name == base_ctor_identifier || name == base_dtor_identifier) return integer_zero_node; else if (name == complete_ctor_identifier) --- 5011,5028 ---- lookup_fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (java_iface_lookup_fn)), java_iface_lookup_fn); ! return build3 (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE); } /* Returns the value to use for the in-charge parameter when making a ! call to a function with the indicated NAME. ! ! FIXME:Can't we find a neater way to do this mapping? */ tree in_charge_arg_for_name (tree name) { ! if (name == base_ctor_identifier || name == base_dtor_identifier) return integer_zero_node; else if (name == complete_ctor_identifier) *************** in_charge_arg_for_name (tree name) *** 4782,4788 **** /* This function should only be called with one of the names listed above. */ ! abort (); return NULL_TREE; } --- 5034,5040 ---- /* This function should only be called with one of the names listed above. */ ! gcc_unreachable (); return NULL_TREE; } *************** build_special_member_call (tree instance *** 4806,4827 **** /* 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 --- 5058,5086 ---- /* The type of the subobject to be constructed or destroyed. */ tree class_type; ! gcc_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)); ! if (TYPE_P (binfo)) ! { ! /* Resolve the name. */ ! if (!complete_type_or_else (binfo, NULL_TREE)) ! return error_mark_node; ! ! binfo = TYPE_BINFO (binfo); ! } ! ! gcc_assert (binfo != NULL_TREE); class_type = BINFO_TYPE (binfo); /* Handle the special case where INSTANCE is NULL_TREE. */ if (name == complete_ctor_identifier && !instance) { ! instance = build_int_cst (build_pointer_type (class_type), 0); instance = build1 (INDIRECT_REF, class_type, instance); } else *************** build_special_member_call (tree instance *** 4829,4835 **** if (name == complete_dtor_identifier || name == base_dtor_identifier || name == deleting_dtor_identifier) ! my_friendly_assert (args == NULL_TREE, 20020712); /* Convert to the base class, if necessary. */ if (!same_type_ignoring_top_level_qualifiers_p --- 5088,5094 ---- if (name == complete_dtor_identifier || name == base_dtor_identifier || name == deleting_dtor_identifier) ! gcc_assert (args == NULL_TREE); /* Convert to the base class, if necessary. */ if (!same_type_ignoring_top_level_qualifiers_p *************** build_special_member_call (tree instance *** 4850,4860 **** } } ! 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); --- 5109,5115 ---- } } ! gcc_assert (instance != NULL_TREE); fns = lookup_fnfields (binfo, name, 1); *************** build_special_member_call (tree instance *** 4863,4869 **** the subobject. */ if ((name == base_ctor_identifier || name == base_dtor_identifier) ! && TYPE_USES_VIRTUAL_BASECLASSES (class_type)) { tree vtt; tree sub_vtt; --- 5118,5124 ---- the subobject. */ if ((name == base_ctor_identifier || name == base_dtor_identifier) ! && CLASSTYPE_VBASECLASSES (class_type)) { tree vtt; tree sub_vtt; *************** build_special_member_call (tree instance *** 4873,4886 **** 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); ! 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); } --- 5128,5141 ---- Otherwise, we look it up using the VTT we were given. */ vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type)); vtt = decay_conversion (vtt); ! vtt = build3 (COND_EXPR, TREE_TYPE (vtt), ! build2 (EQ_EXPR, boolean_type_node, ! current_in_charge_parm, integer_zero_node), ! current_vtt_parm, ! vtt); ! gcc_assert (BINFO_SUBVTT_INDEX (binfo)); ! sub_vtt = build2 (PLUS_EXPR, TREE_TYPE (vtt), vtt, ! BINFO_SUBVTT_INDEX (binfo)); args = tree_cons (NULL_TREE, sub_vtt, args); } *************** build_new_method_call (tree instance, tr *** 4957,4964 **** tree orig_instance; tree orig_fns; tree orig_args; ! my_friendly_assert (instance != NULL_TREE, 20020729); if (error_operand_p (instance) || error_operand_p (fns) --- 5212,5220 ---- tree orig_instance; tree orig_fns; tree orig_args; + void *p; ! gcc_assert (instance != NULL_TREE); if (error_operand_p (instance) || error_operand_p (fns) *************** build_new_method_call (tree instance, tr *** 4985,4998 **** if (args == error_mark_node) return error_mark_node; - 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)) { ! error ("call to non-function `%D'", fns); return error_mark_node; } --- 5241,5252 ---- if (args == error_mark_node) return error_mark_node; basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance)); instance_ptr = build_this (instance); if (!BASELINK_P (fns)) { ! error ("call to non-function %qD", fns); return error_mark_node; } *************** build_new_method_call (tree instance, tr *** 5009,5024 **** template_only = 1; } ! my_friendly_assert (TREE_CODE (fns) == FUNCTION_DECL ! || TREE_CODE (fns) == TEMPLATE_DECL ! || TREE_CODE (fns) == OVERLOAD, ! 20020712); /* 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'", fns, instance, basetype); return error_mark_node; --- 5263,5278 ---- template_only = 1; } ! gcc_assert (TREE_CODE (fns) == FUNCTION_DECL ! || TREE_CODE (fns) == TEMPLATE_DECL ! || TREE_CODE (fns) == OVERLOAD); /* 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 %qD in %qE, which is of non-aggregate " ! "type %qT", fns, instance, basetype); return error_mark_node; *************** build_new_method_call (tree instance, tr *** 5031,5039 **** { /* 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); } /* It's OK to call destructors on cv-qualified objects. Therefore, --- 5285,5293 ---- { /* Callers should explicitly indicate whether they want to construct the complete object or just the part without virtual bases. */ ! gcc_assert (name != ctor_identifier); /* Similarly for destructors. */ ! gcc_assert (name != dtor_identifier); } /* It's OK to call destructors on cv-qualified objects. Therefore, *************** build_new_method_call (tree instance, tr *** 5048,5053 **** --- 5302,5310 ---- class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE); mem_args = tree_cons (NULL_TREE, instance_ptr, args); + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + for (fn = fns; fn; fn = OVL_NEXT (fn)) { tree t = OVL_CURRENT (fn); *************** build_new_method_call (tree instance, tr *** 5085,5093 **** candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { - /* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */ - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; if (!COMPLETE_TYPE_P (basetype)) cxx_incomplete_type_error (instance_ptr, basetype); else --- 5342,5347 ---- *************** build_new_method_call (tree instance, tr *** 5096,5163 **** bool free_p; pretty_name = name_as_c_string (name, basetype, &free_p); ! error ("no matching function for call to `%T::%s(%A)%#V'", basetype, pretty_name, user_args, TREE_TYPE (TREE_TYPE (instance_ptr))); if (free_p) free (pretty_name); } print_z_candidates (candidates); ! return error_mark_node; } ! ! cand = tourney (candidates); ! if (cand == 0) { ! char *pretty_name; ! bool free_p; ! ! pretty_name = name_as_c_string (name, basetype, &free_p); ! error ("call of overloaded `%s(%A)' is ambiguous", pretty_name, ! user_args); ! print_z_candidates (candidates); ! if (free_p) ! free (pretty_name); ! return error_mark_node; ! } ! if (DECL_PURE_VIRTUAL_P (cand->fn) ! && instance == current_class_ref ! && (DECL_CONSTRUCTOR_P (current_function_decl) ! || DECL_DESTRUCTOR_P (current_function_decl)) ! && ! (flags & LOOKUP_NONVIRTUAL) ! && value_member (cand->fn, CLASSTYPE_PURE_VIRTUALS (basetype))) ! error ((DECL_CONSTRUCTOR_P (current_function_decl) ? ! "abstract virtual `%#D' called from constructor" ! : "abstract virtual `%#D' called from destructor"), ! cand->fn); ! if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ! && is_dummy_object (instance_ptr)) ! { ! error ("cannot call member function `%D' without object", cand->fn); ! return error_mark_node; ! } ! if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) ! && resolves_to_fixed_type_p (instance, 0)) ! flags |= LOOKUP_NONVIRTUAL; ! if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE) ! call = build_over_call (cand, flags); ! else ! { ! call = build_over_call (cand, flags); ! /* 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 (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance)) ! call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call); } ! if (processing_template_decl && call != error_mark_node) ! return build_min_non_dep ! (CALL_EXPR, call, ! build_min_nt (COMPONENT_REF, orig_instance, orig_fns), ! orig_args); return call; } --- 5350,5430 ---- bool free_p; pretty_name = name_as_c_string (name, basetype, &free_p); ! error ("no matching function for call to %<%T::%s(%A)%#V%>", basetype, pretty_name, user_args, TREE_TYPE (TREE_TYPE (instance_ptr))); if (free_p) free (pretty_name); } print_z_candidates (candidates); ! call = error_mark_node; } ! else { ! cand = tourney (candidates); ! if (cand == 0) ! { ! char *pretty_name; ! bool free_p; ! pretty_name = name_as_c_string (name, basetype, &free_p); ! error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name, ! user_args); ! print_z_candidates (candidates); ! if (free_p) ! free (pretty_name); ! call = error_mark_node; ! } ! else ! { ! if (!(flags & LOOKUP_NONVIRTUAL) ! && DECL_PURE_VIRTUAL_P (cand->fn) ! && instance == current_class_ref ! && (DECL_CONSTRUCTOR_P (current_function_decl) ! || DECL_DESTRUCTOR_P (current_function_decl))) ! /* This is not an error, it is runtime undefined ! behavior. */ ! warning ((DECL_CONSTRUCTOR_P (current_function_decl) ? ! "abstract virtual %q#D called from constructor" ! : "abstract virtual %q#D called from destructor"), ! cand->fn); ! ! if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ! && is_dummy_object (instance_ptr)) ! { ! error ("cannot call member function %qD without object", ! cand->fn); ! call = error_mark_node; ! } ! else ! { ! if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) ! && resolves_to_fixed_type_p (instance, 0)) ! flags |= LOOKUP_NONVIRTUAL; ! call = build_over_call (cand, flags); ! /* 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 (TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE ! && !is_dummy_object (instance_ptr) ! && TREE_SIDE_EFFECTS (instance)) ! call = build2 (COMPOUND_EXPR, TREE_TYPE (call), ! instance, call); ! } ! } } ! if (processing_template_decl && call != error_mark_node) ! call = (build_min_non_dep ! (CALL_EXPR, call, ! build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE), ! orig_args, NULL_TREE)); ! ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! return call; } *************** build_new_method_call (tree instance, tr *** 5165,5201 **** subsequence of ICS2. */ static bool ! is_subseq (tree ics1, tree ics2) { /* We can assume that a conversion of the same code between the same types indicates a subsequence since we only get here if the types we are converting from are the same. */ ! while (TREE_CODE (ics1) == RVALUE_CONV ! || TREE_CODE (ics1) == LVALUE_CONV) ! ics1 = TREE_OPERAND (ics1, 0); while (1) { ! while (TREE_CODE (ics2) == RVALUE_CONV ! || TREE_CODE (ics2) == LVALUE_CONV) ! ics2 = TREE_OPERAND (ics2, 0); ! if (TREE_CODE (ics2) == USER_CONV ! || TREE_CODE (ics2) == AMBIG_CONV ! || TREE_CODE (ics2) == IDENTITY_CONV) /* At this point, ICS1 cannot be a proper subsequence of ICS2. We can get a USER_CONV when we are comparing the second standard conversion sequence of two user conversion sequences. */ return false; ! ics2 = TREE_OPERAND (ics2, 0); ! if (TREE_CODE (ics2) == TREE_CODE (ics1) ! && same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1)) ! && same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)), ! TREE_TYPE (TREE_OPERAND (ics1, 0)))) return true; } } --- 5432,5468 ---- subsequence of ICS2. */ static bool ! is_subseq (conversion *ics1, conversion *ics2) { /* We can assume that a conversion of the same code between the same types indicates a subsequence since we only get here if the types we are converting from are the same. */ ! while (ics1->kind == ck_rvalue ! || ics1->kind == ck_lvalue) ! ics1 = ics1->u.next; while (1) { ! while (ics2->kind == ck_rvalue ! || ics2->kind == ck_lvalue) ! ics2 = ics2->u.next; ! if (ics2->kind == ck_user ! || ics2->kind == ck_ambig ! || ics2->kind == ck_identity) /* At this point, ICS1 cannot be a proper subsequence of ICS2. We can get a USER_CONV when we are comparing the second standard conversion sequence of two user conversion sequences. */ return false; ! ics2 = ics2->u.next; ! if (ics2->kind == ics1->kind ! && same_type_p (ics2->type, ics1->type) ! && same_type_p (ics2->u.next->type, ! ics1->u.next->type)) return true; } } *************** is_properly_derived_from (tree derived, *** 5223,5231 **** modify it accordingly. */ static void ! maybe_handle_implicit_object (tree *ics) { ! if (ICS_THIS_FLAG (*ics)) { /* [over.match.funcs] --- 5490,5498 ---- modify it accordingly. */ static void ! maybe_handle_implicit_object (conversion **ics) { ! if ((*ics)->this_p) { /* [over.match.funcs] *************** maybe_handle_implicit_object (tree *ics) *** 5234,5253 **** where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. */ ! tree t = *ics; tree reference_type; /* The `this' parameter is a pointer to a class type. Make the implicit conversion talk about a reference to that same class type. */ ! reference_type = TREE_TYPE (TREE_TYPE (*ics)); reference_type = build_reference_type (reference_type); ! if (TREE_CODE (t) == QUAL_CONV) ! t = TREE_OPERAND (t, 0); ! if (TREE_CODE (t) == PTR_CONV) ! t = TREE_OPERAND (t, 0); ! t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE); t = direct_reference_binding (reference_type, t); *ics = t; } --- 5501,5520 ---- where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. */ ! conversion *t = *ics; tree reference_type; /* The `this' parameter is a pointer to a class type. Make the implicit conversion talk about a reference to that same class type. */ ! reference_type = TREE_TYPE (t->type); reference_type = build_reference_type (reference_type); ! if (t->kind == ck_qual) ! t = t->u.next; ! if (t->kind == ck_ptr) ! t = t->u.next; ! t = build_identity_conv (TREE_TYPE (t->type), NULL_TREE); t = direct_reference_binding (reference_type, t); *ics = t; } *************** maybe_handle_implicit_object (tree *ics) *** 5258,5272 **** leave *ICS unchanged and return NULL_TREE. */ static tree ! maybe_handle_ref_bind (tree *ics) { ! if (TREE_CODE (*ics) == REF_BIND) { ! tree old_ics = *ics; ! tree type = TREE_TYPE (TREE_TYPE (old_ics)); ! *ics = TREE_OPERAND (old_ics, 0); ! ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics); ! ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics); return type; } --- 5525,5539 ---- leave *ICS unchanged and return NULL_TREE. */ static tree ! maybe_handle_ref_bind (conversion **ics) { ! if ((*ics)->kind == ck_ref_bind) { ! conversion *old_ics = *ics; ! tree type = TREE_TYPE (old_ics->type); ! *ics = old_ics->u.next; ! (*ics)->user_conv_p = old_ics->user_conv_p; ! (*ics)->bad_p = old_ics->bad_p; return type; } *************** maybe_handle_ref_bind (tree *ics) *** 5281,5287 **** 0: ics1 and ics2 are indistinguishable */ static int ! compare_ics (tree ics1, tree ics2) { tree from_type1; tree from_type2; --- 5548,5554 ---- 0: ics1 and ics2 are indistinguishable */ static int ! compare_ics (conversion *ics1, conversion *ics2) { tree from_type1; tree from_type2; *************** compare_ics (tree ics1, tree ics2) *** 5291,5297 **** tree deref_from_type2 = NULL_TREE; tree deref_to_type1 = NULL_TREE; tree deref_to_type2 = NULL_TREE; ! int rank1, rank2; /* REF_BINDING is nonzero if the result of the conversion sequence is a reference type. In that case TARGET_TYPE is the --- 5558,5564 ---- tree deref_from_type2 = NULL_TREE; tree deref_to_type1 = NULL_TREE; tree deref_to_type2 = NULL_TREE; ! conversion_rank rank1, rank2; /* REF_BINDING is nonzero if the result of the conversion sequence is a reference type. In that case TARGET_TYPE is the *************** compare_ics (tree ics1, tree ics2) *** 5319,5348 **** --a user-defined conversion sequence (_over.ics.user_) is a better conversion sequence than an ellipsis conversion sequence (_over.ics.ellipsis_). */ ! rank1 = ICS_RANK (ics1); ! rank2 = ICS_RANK (ics2); if (rank1 > rank2) return -1; else if (rank1 < rank2) return 1; ! if (rank1 == BAD_RANK) { /* XXX Isn't this an extension? */ /* Both ICS are bad. We try to make a decision based on what would have happened if they'd been good. */ ! if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2) ! || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2)) return -1; ! else if (ICS_USER_FLAG (ics1) < ICS_USER_FLAG (ics2) ! || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) return 1; /* We couldn't make up our minds; try to figure it out below. */ } ! if (ICS_ELLIPSIS_FLAG (ics1)) /* Both conversions are ellipsis conversions. */ return 0; --- 5586,5615 ---- --a user-defined conversion sequence (_over.ics.user_) is a better conversion sequence than an ellipsis conversion sequence (_over.ics.ellipsis_). */ ! rank1 = CONVERSION_RANK (ics1); ! rank2 = CONVERSION_RANK (ics2); if (rank1 > rank2) return -1; else if (rank1 < rank2) return 1; ! if (rank1 == cr_bad) { /* XXX Isn't this an extension? */ /* Both ICS are bad. We try to make a decision based on what would have happened if they'd been good. */ ! if (ics1->user_conv_p > ics2->user_conv_p ! || ics1->rank > ics2->rank) return -1; ! else if (ics1->user_conv_p < ics2->user_conv_p ! || ics1->rank < ics2->rank) return 1; /* We couldn't make up our minds; try to figure it out below. */ } ! if (ics1->ellipsis_p) /* Both conversions are ellipsis conversions. */ return 0; *************** compare_ics (tree ics1, tree ics2) *** 5352,5378 **** ond standard conversion sequence of U1 is better than the second standard conversion sequence of U2. */ ! if (ICS_USER_FLAG (ics1)) { ! tree t1, t2; ! for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) ! if (TREE_CODE (t1) == AMBIG_CONV) return 0; ! for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) ! if (TREE_CODE (t2) == AMBIG_CONV) return 0; ! if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) return 0; /* We can just fall through here, after setting up FROM_TYPE1 and FROM_TYPE2. */ ! from_type1 = TREE_TYPE (t1); ! from_type2 = TREE_TYPE (t2); } else { /* We're dealing with two standard conversion sequences. [over.ics.rank] --- 5619,5649 ---- ond standard conversion sequence of U1 is better than the second standard conversion sequence of U2. */ ! if (ics1->user_conv_p) { ! conversion *t1; ! conversion *t2; ! for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next) ! if (t1->kind == ck_ambig) return 0; ! for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next) ! if (t2->kind == ck_ambig) return 0; ! if (t1->cand->fn != t2->cand->fn) return 0; /* We can just fall through here, after setting up FROM_TYPE1 and FROM_TYPE2. */ ! from_type1 = t1->type; ! from_type2 = t2->type; } else { + conversion *t1; + conversion *t2; + /* We're dealing with two standard conversion sequences. [over.ics.rank] *************** compare_ics (tree ics1, tree ics2) *** 5386,5400 **** conversion sequence is considered to be a subsequence of any non-identity conversion sequence */ ! from_type1 = ics1; ! while (TREE_CODE (from_type1) != IDENTITY_CONV) ! from_type1 = TREE_OPERAND (from_type1, 0); ! from_type1 = TREE_TYPE (from_type1); ! from_type2 = ics2; ! while (TREE_CODE (from_type2) != IDENTITY_CONV) ! from_type2 = TREE_OPERAND (from_type2, 0); ! from_type2 = TREE_TYPE (from_type2); } if (same_type_p (from_type1, from_type2)) --- 5657,5671 ---- conversion sequence is considered to be a subsequence of any non-identity conversion sequence */ ! t1 = ics1; ! while (t1->kind != ck_identity) ! t1 = t1->u.next; ! from_type1 = t1->type; ! t2 = ics2; ! while (t2->kind != ck_identity) ! t2 = t2->u.next; ! from_type2 = t2->type; } if (same_type_p (from_type1, from_type2)) *************** compare_ics (tree ics1, tree ics2) *** 5429,5441 **** The ICS_STD_RANK automatically handles the pointer-to-bool rule, so that we do not have to check it explicitly. */ ! if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) return 1; ! else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1)) return -1; ! to_type1 = TREE_TYPE (ics1); ! to_type2 = TREE_TYPE (ics2); if (TYPE_PTR_P (from_type1) && TYPE_PTR_P (from_type2) --- 5700,5712 ---- The ICS_STD_RANK automatically handles the pointer-to-bool rule, so that we do not have to check it explicitly. */ ! if (ics1->rank < ics2->rank) return 1; ! else if (ics2->rank < ics1->rank) return -1; ! to_type1 = ics1->type; ! to_type2 = ics2->type; if (TYPE_PTR_P (from_type1) && TYPE_PTR_P (from_type2) *************** compare_ics (tree ics1, tree ics2) *** 5568,5574 **** A& is better than binding an expression of type C to a reference of type A&, ! --onversion of B to A is better than conversion of C to A */ if (is_properly_derived_from (from_type1, to) && is_properly_derived_from (from_type2, to)) { --- 5839,5845 ---- A& is better than binding an expression of type C to a reference of type A&, ! --conversion of B to A is better than conversion of C to A */ if (is_properly_derived_from (from_type1, to) && is_properly_derived_from (from_type2, to)) { *************** compare_ics (tree ics1, tree ics2) *** 5585,5592 **** similar types T1 and T2 (_conv.qual_), respectively, and the cv- qualification signature of type T1 is a proper subset of the cv- qualification signature of type T2 */ ! if (TREE_CODE (ics1) == QUAL_CONV ! && TREE_CODE (ics2) == QUAL_CONV && same_type_p (from_type1, from_type2)) return comp_cv_qual_signature (to_type1, to_type2); --- 5856,5863 ---- similar types T1 and T2 (_conv.qual_), respectively, and the cv- qualification signature of type T1 is a proper subset of the cv- qualification signature of type T2 */ ! if (ics1->kind == ck_qual ! && ics2->kind == ck_qual && same_type_p (from_type1, from_type2)) return comp_cv_qual_signature (to_type1, to_type2); *************** compare_ics (tree ics1, tree ics2) *** 5609,5624 **** /* The source type for this standard conversion sequence. */ static tree ! source_type (tree t) { ! for (;; t = TREE_OPERAND (t, 0)) { ! if (TREE_CODE (t) == USER_CONV ! || TREE_CODE (t) == AMBIG_CONV ! || TREE_CODE (t) == IDENTITY_CONV) ! return TREE_TYPE (t); } ! abort (); } /* Note a warning about preferring WINNER to LOSER. We do this by storing --- 5880,5895 ---- /* The source type for this standard conversion sequence. */ static tree ! source_type (conversion *t) { ! for (;; t = t->u.next) { ! if (t->kind == ck_user ! || t->kind == ck_ambig ! || t->kind == ck_identity) ! return t->type; } ! gcc_unreachable (); } /* Note a warning about preferring WINNER to LOSER. We do this by storing *************** source_type (tree t) *** 5628,5636 **** static void add_warning (struct z_candidate *winner, struct z_candidate *loser) { ! winner->warnings = tree_cons (NULL_TREE, ! build_zc_wrapper (loser), ! winner->warnings); } /* Compare two candidates for overloading as described in --- 5899,5910 ---- static void add_warning (struct z_candidate *winner, struct z_candidate *loser) { ! candidate_warning *cw; ! ! cw = conversion_obstack_alloc (sizeof (candidate_warning)); ! cw->loser = loser; ! cw->next = winner->warnings; ! winner->warnings = cw; } /* Compare two candidates for overloading as described in *************** static int *** 5644,5650 **** joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn) { int winner = 0; ! int i, off1 = 0, off2 = 0, len; /* Candidates that involve bad conversions are always worse than those that don't. */ --- 5918,5926 ---- joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn) { int winner = 0; ! int off1 = 0, off2 = 0; ! size_t i; ! size_t len; /* Candidates that involve bad conversions are always worse than those that don't. */ *************** joust (struct z_candidate *cand1, struct *** 5656,5662 **** /* If we have two pseudo-candidates for conversions to the same type, or two candidates for the same function, arbitrarily pick one. */ if (cand1->fn == cand2->fn ! && (TYPE_P (cand1->fn) || DECL_P (cand1->fn))) return 1; /* a viable function F1 --- 5932,5938 ---- /* If we have two pseudo-candidates for conversions to the same type, or two candidates for the same function, arbitrarily pick one. */ if (cand1->fn == cand2->fn ! && (IS_TYPE_OR_DECL_P (cand1->fn))) return 1; /* a viable function F1 *************** joust (struct z_candidate *cand1, struct *** 5671,5727 **** the implicit object parameter of the non-static function. The standard says to pretend that the static function has an object parm, but that won't work with operator overloading. */ ! len = TREE_VEC_LENGTH (cand1->convs); ! if (len != TREE_VEC_LENGTH (cand2->convs)) { ! if (DECL_STATIC_FUNCTION_P (cand1->fn) ! && ! DECL_STATIC_FUNCTION_P (cand2->fn)) off2 = 1; ! else if (! DECL_STATIC_FUNCTION_P (cand1->fn) ! && DECL_STATIC_FUNCTION_P (cand2->fn)) { off1 = 1; --len; } - else - abort (); } for (i = 0; i < len; ++i) { ! tree t1 = TREE_VEC_ELT (cand1->convs, i+off1); ! tree t2 = TREE_VEC_ELT (cand2->convs, i+off2); int comp = compare_ics (t1, t2); if (comp != 0) { if (warn_sign_promo ! && ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK ! && TREE_CODE (t1) == STD_CONV ! && TREE_CODE (t2) == STD_CONV ! && TREE_CODE (TREE_TYPE (t1)) == INTEGER_TYPE ! && TREE_CODE (TREE_TYPE (t2)) == INTEGER_TYPE ! && (TYPE_PRECISION (TREE_TYPE (t1)) ! == TYPE_PRECISION (TREE_TYPE (t2))) ! && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t1, 0))) ! || (TREE_CODE (TREE_TYPE (TREE_OPERAND (t1, 0))) == ENUMERAL_TYPE))) { ! tree type = TREE_TYPE (TREE_OPERAND (t1, 0)); tree type1, type2; struct z_candidate *w, *l; if (comp > 0) ! type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2), w = cand1, l = cand2; else ! type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1), w = cand2, l = cand1; if (warn) { ! warning ("passing `%T' chooses `%T' over `%T'", type, type1, type2); ! warning (" in call to `%D'", w->fn); } else add_warning (w, l); --- 5947,6005 ---- the implicit object parameter of the non-static function. The standard says to pretend that the static function has an object parm, but that won't work with operator overloading. */ ! len = cand1->num_convs; ! if (len != cand2->num_convs) { ! int static_1 = DECL_STATIC_FUNCTION_P (cand1->fn); ! int static_2 = DECL_STATIC_FUNCTION_P (cand2->fn); ! ! gcc_assert (static_1 != static_2); ! ! if (static_1) off2 = 1; ! else { off1 = 1; --len; } } for (i = 0; i < len; ++i) { ! conversion *t1 = cand1->convs[i + off1]; ! conversion *t2 = cand2->convs[i + off2]; int comp = compare_ics (t1, t2); if (comp != 0) { if (warn_sign_promo ! && (CONVERSION_RANK (t1) + CONVERSION_RANK (t2) ! == cr_std + cr_promotion) ! && t1->kind == ck_std ! && t2->kind == ck_std ! && TREE_CODE (t1->type) == INTEGER_TYPE ! && TREE_CODE (t2->type) == INTEGER_TYPE ! && (TYPE_PRECISION (t1->type) ! == TYPE_PRECISION (t2->type)) ! && (TYPE_UNSIGNED (t1->u.next->type) ! || (TREE_CODE (t1->u.next->type) == ENUMERAL_TYPE))) { ! tree type = t1->u.next->type; tree type1, type2; struct z_candidate *w, *l; if (comp > 0) ! type1 = t1->type, type2 = t2->type, w = cand1, l = cand2; else ! type1 = t2->type, type2 = t1->type, w = cand2, l = cand1; if (warn) { ! warning ("passing %qT chooses %qT over %qT", type, type1, type2); ! warning (" in call to %qD", w->fn); } else add_warning (w, l); *************** joust (struct z_candidate *cand1, struct *** 5775,5786 **** /*NOP*/; else if (warn) { ! tree source = source_type (TREE_VEC_ELT (w->convs, 0)); if (! DECL_CONSTRUCTOR_P (w->fn)) source = TREE_TYPE (source); ! warning ("choosing `%D' over `%D'", w->fn, l->fn); ! warning (" for conversion from `%T' to `%T'", ! source, TREE_TYPE (w->second_conv)); warning (" because conversion sequence for the argument is better"); } else --- 6053,6064 ---- /*NOP*/; else if (warn) { ! tree source = source_type (w->convs[0]); if (! DECL_CONSTRUCTOR_P (w->fn)) source = TREE_TYPE (source); ! warning ("choosing %qD over %qD", w->fn, l->fn); ! warning (" for conversion from %qT to %qT", ! source, w->second_conv->type); warning (" because conversion sequence for the argument is better"); } else *************** joust (struct z_candidate *cand1, struct *** 5794,5802 **** F1 is a non-template function and F2 is a template function specialization. */ ! if (! cand1->template && cand2->template) return 1; ! else if (cand1->template && ! cand2->template) return -1; /* or, if not that, --- 6072,6080 ---- F1 is a non-template function and F2 is a template function specialization. */ ! if (!cand1->template_decl && cand2->template_decl) return 1; ! else if (cand1->template_decl && !cand2->template_decl) return -1; /* or, if not that, *************** joust (struct z_candidate *cand1, struct *** 5804,5813 **** more specialized than the template for F2 according to the partial ordering rules. */ ! if (cand1->template && cand2->template) { winner = more_specialized ! (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template), DEDUCE_ORDER, /* Tell the deduction code how many real function arguments we saw, not counting the implicit 'this' argument. But, --- 6082,6092 ---- more specialized than the template for F2 according to the partial ordering rules. */ ! if (cand1->template_decl && cand2->template_decl) { winner = more_specialized ! (TI_TEMPLATE (cand1->template_decl), ! TI_TEMPLATE (cand2->template_decl), DEDUCE_ORDER, /* Tell the deduction code how many real function arguments we saw, not counting the implicit 'this' argument. But, *************** joust (struct z_candidate *cand1, struct *** 5817,5823 **** [temp.func.order]: The presence of unused ellipsis and default arguments has no effect on the partial ordering of function templates. */ ! TREE_VEC_LENGTH (cand1->convs) - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn) - DECL_CONSTRUCTOR_P (cand1->fn))); if (winner) --- 6096,6102 ---- [temp.func.order]: The presence of unused ellipsis and default arguments has no effect on the partial ordering of function templates. */ ! cand1->num_convs - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn) - DECL_CONSTRUCTOR_P (cand1->fn))); if (winner) *************** joust (struct z_candidate *cand1, struct *** 5854,5863 **** || TREE_CODE (cand2->fn) == IDENTIFIER_NODE) { for (i = 0; i < len; ++i) ! if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)), ! TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)))) break; ! if (i == TREE_VEC_LENGTH (cand1->convs)) { if (cand1->fn == cand2->fn) /* Two built-in candidates; arbitrarily pick one. */ --- 6133,6142 ---- || TREE_CODE (cand2->fn) == IDENTIFIER_NODE) { for (i = 0; i < len; ++i) ! if (!same_type_p (cand1->convs[i]->type, ! cand2->convs[i]->type)) break; ! if (i == cand1->num_convs) { if (cand1->fn == cand2->fn) /* Two built-in candidates; arbitrarily pick one. */ *************** tweak: *** 5883,5897 **** worst conversion for the other, take the first. */ if (!pedantic) { ! int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK; struct z_candidate *w = 0, *l = 0; for (i = 0; i < len; ++i) { ! if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1) ! rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)); ! if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2) ! rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)); } if (rank1 < rank2) winner = 1, w = cand1, l = cand2; --- 6162,6176 ---- worst conversion for the other, take the first. */ if (!pedantic) { ! conversion_rank rank1 = cr_identity, rank2 = cr_identity; struct z_candidate *w = 0, *l = 0; for (i = 0; i < len; ++i) { ! if (CONVERSION_RANK (cand1->convs[i+off1]) > rank1) ! rank1 = CONVERSION_RANK (cand1->convs[i+off1]); ! if (CONVERSION_RANK (cand2->convs[i + off2]) > rank2) ! rank2 = CONVERSION_RANK (cand2->convs[i + off2]); } if (rank1 < rank2) winner = 1, w = cand1, l = cand2; *************** the worst conversion for the second:"); *** 5914,5920 **** } } ! my_friendly_assert (!winner, 20010121); return 0; } --- 6193,6199 ---- } } ! gcc_assert (!winner); return 0; } *************** can_convert (tree to, tree from) *** 5986,5993 **** bool can_convert_arg (tree to, tree from, tree arg) { ! tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); ! return (t && ! ICS_BAD_FLAG (t)); } /* Like can_convert_arg, but allows dubious conversions as well. */ --- 6265,6284 ---- bool can_convert_arg (tree to, tree from, tree arg) { ! conversion *t; ! void *p; ! bool ok_p; ! ! /* Get the high-water mark for the CONVERSION_OBSTACK. */ ! p = conversion_obstack_alloc (0); ! ! t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); ! ok_p = (t && !t->bad_p); ! ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return ok_p; } /* Like can_convert_arg, but allows dubious conversions as well. */ *************** can_convert_arg (tree to, tree from, tre *** 5995,6001 **** bool can_convert_arg_bad (tree to, tree from, tree arg) { ! return implicit_conversion (to, from, arg, LOOKUP_NORMAL) != 0; } /* Convert EXPR to TYPE. Return the converted expression. --- 6286,6302 ---- bool can_convert_arg_bad (tree to, tree from, tree arg) { ! conversion *t; ! void *p; ! ! /* Get the high-water mark for the CONVERSION_OBSTACK. */ ! p = conversion_obstack_alloc (0); ! /* Try to perform the conversion. */ ! t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return t != NULL; } /* Convert EXPR to TYPE. Return the converted expression. *************** can_convert_arg_bad (tree to, tree from, *** 6007,6037 **** tree perform_implicit_conversion (tree type, tree expr) { ! tree conv; ! if (error_operand_p (expr)) return error_mark_node; conv = implicit_conversion (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); if (!conv) { ! error ("could not convert `%E' to `%T'", expr, type); ! return error_mark_node; } ! 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, except in the case ! that TYPE is a class type; in that case, an error is issued. */ 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; /* [dcl.init] --- 6308,6354 ---- tree perform_implicit_conversion (tree type, tree expr) { ! conversion *conv; ! void *p; ! if (error_operand_p (expr)) return error_mark_node; + + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + conv = implicit_conversion (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); if (!conv) { ! error ("could not convert %qE to %qT", expr, type); ! expr = error_mark_node; } + else + expr = convert_like (conv, expr); ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return 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, except in the case ! that TYPE is a class type; in that case, an error is issued. If ! C_CAST_P is true, then this direction initialization is taking ! place as part of a static_cast being attempted as part of a C-style ! cast. */ tree ! perform_direct_initialization_if_possible (tree type, ! tree expr, ! bool c_cast_p) { ! conversion *conv; ! void *p; ! if (type == error_mark_node || error_operand_p (expr)) return error_mark_node; /* [dcl.init] *************** perform_direct_initialization_if_possibl *** 6046,6061 **** { expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! TYPE_BINFO (type), ! LOOKUP_NORMAL); return build_cplus_new (type, expr); } 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 --- 6363,6388 ---- { expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), ! type, LOOKUP_NORMAL); return build_cplus_new (type, expr); } + + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + conv = implicit_conversion (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); ! if (!conv || conv->bad_p) ! expr = NULL_TREE; ! else ! expr = convert_like_real (conv, expr, NULL_TREE, 0, 0, ! /*issue_conversion_warnings=*/false, ! c_cast_p); ! ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return expr; } /* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference *************** make_temporary_var_for_ref_to_temp (tree *** 6071,6076 **** --- 6398,6404 ---- /* Create the variable. */ var = build_decl (VAR_DECL, NULL_TREE, type); DECL_ARTIFICIAL (var) = 1; + DECL_IGNORED_P (var) = 1; TREE_USED (var) = 1; /* Register the variable. */ *************** make_temporary_var_for_ref_to_temp (tree *** 6101,6131 **** the VAR_DECL being initialized with the EXPR. (In that case, the type of DECL will be TYPE.) If DECL is non-NULL, then CLEANUP must also be non-NULL, and with *CLEANUP initialized to NULL. Upon ! return, if *CLEANUP is no longer NULL, it will be a CLEANUP_STMT ! that should be inserted after the returned expression is used to ! initialize DECL. Return the converted expression. */ tree initialize_reference (tree type, tree expr, tree decl, tree *cleanup) { ! 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)) { if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST) && !real_lvalue_p (expr)) error ("invalid initialization of non-const reference of " ! "type '%T' from a temporary of type '%T'", type, TREE_TYPE (expr)); else error ("invalid initialization of reference of type " ! "'%T' from expression of type '%T'", type, TREE_TYPE (expr)); return error_mark_node; } --- 6429,6463 ---- the VAR_DECL being initialized with the EXPR. (In that case, the type of DECL will be TYPE.) If DECL is non-NULL, then CLEANUP must also be non-NULL, and with *CLEANUP initialized to NULL. Upon ! return, if *CLEANUP is no longer NULL, it will be an expression ! that should be pushed as a cleanup after the returned expression ! is used to initialize DECL. Return the converted expression. */ tree initialize_reference (tree type, tree expr, tree decl, tree *cleanup) { ! conversion *conv; ! void *p; if (type == error_mark_node || error_operand_p (expr)) return error_mark_node; + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + p = conversion_obstack_alloc (0); + conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); ! if (!conv || conv->bad_p) { if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST) && !real_lvalue_p (expr)) error ("invalid initialization of non-const reference of " ! "type %qT from a temporary of type %qT", type, TREE_TYPE (expr)); else error ("invalid initialization of reference of type " ! "%qT from expression of type %qT", type, TREE_TYPE (expr)); return error_mark_node; } *************** initialize_reference (tree type, tree ex *** 6164,6185 **** 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)) { ! if (CHECK_COPY_CONSTRUCTOR_P (conv)) ! check_constructor_callable (TREE_TYPE (expr), expr); ! base_conv_type = TREE_TYPE (conv); ! conv = TREE_OPERAND (conv, 0); } else base_conv_type = NULL_TREE; --- 6496,6517 ---- we can extend the lifetime of the return value of the conversion operator. */ ! gcc_assert (conv->kind == ck_ref_bind); if (decl) { tree var; tree base_conv_type; /* Skip over the REF_BIND. */ ! conv = conv->u.next; /* If the next conversion is a BASE_CONV, skip that too -- but remember that the conversion was required. */ ! if (conv->kind == ck_base) { ! if (conv->check_copy_constructor_p) ! check_constructor_callable (TREE_TYPE (expr), expr); ! base_conv_type = conv->type; ! conv = conv->u.next; } else base_conv_type = NULL_TREE; *************** initialize_reference (tree type, tree ex *** 6187,6263 **** expr = convert_like_real (conv, expr, /*fn=*/NULL_TREE, /*argnum=*/0, /*inner=*/-1, ! /*issue_conversion_warnings=*/true); ! if (!real_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 the rvalue is the result of a function call it will be ! a TARGET_EXPR. If it is some other construct (such as a ! member access expression where the underlying object is ! itself the result of a function call), turn it into a ! TARGET_EXPR here. It is important that EXPR be a ! TARGET_EXPR below since otherwise the INIT_EXPR will ! attempt to make a bitwise copy of EXPR to intialize ! VAR. */ ! if (TREE_CODE (expr) != TARGET_EXPR) ! expr = get_target_expr (expr); ! /* Create the INIT_EXPR that will initialize the temporary ! variable. */ ! init = build (INIT_EXPR, type, var, expr); ! if (at_function_scope_p ()) { ! add_decl_stmt (var); ! *cleanup = cxx_maybe_build_cleanup (var); ! if (*cleanup) ! /* We must be careful to destroy the temporary only ! after its initialization has taken place. If the ! initialization throws an exception, then the ! destructor should not be run. We cannot simply ! transform INIT into something like: ! ! (INIT, ({ CLEANUP_STMT; })) ! because emit_local_var always treats the ! initializer as a full-expression. Thus, the ! destructor would run too early; it would run at the ! end of initializing the reference variable, rather ! than at the end of the block enclosing the ! reference variable. ! The solution is to pass back a CLEANUP_STMT which ! the caller is responsible for attaching to the ! statement tree. */ ! *cleanup = build_stmt (CLEANUP_STMT, 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); ! } ! /* 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" --- 6519,6610 ---- expr = convert_like_real (conv, expr, /*fn=*/NULL_TREE, /*argnum=*/0, /*inner=*/-1, ! /*issue_conversion_warnings=*/true, ! /*c_cast_p=*/false); ! if (error_operand_p (expr)) ! expr = error_mark_node; ! else { ! if (!real_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 the rvalue is the result of a function call it will be ! a TARGET_EXPR. If it is some other construct (such as a ! member access expression where the underlying object is ! itself the result of a function call), turn it into a ! TARGET_EXPR here. It is important that EXPR be a ! TARGET_EXPR below since otherwise the INIT_EXPR will ! attempt to make a bitwise copy of EXPR to initialize ! VAR. */ ! if (TREE_CODE (expr) != TARGET_EXPR) ! expr = get_target_expr (expr); ! /* Create the INIT_EXPR that will initialize the temporary ! variable. */ ! init = build2 (INIT_EXPR, type, var, expr); ! if (at_function_scope_p ()) ! { ! add_decl_expr (var); ! *cleanup = cxx_maybe_build_cleanup (var); ! /* We must be careful to destroy the temporary only ! after its initialization has taken place. If the ! initialization throws an exception, then the ! destructor should not be run. We cannot simply ! transform INIT into something like: ! ! (INIT, ({ CLEANUP_STMT; })) ! ! because emit_local_var always treats the ! initializer as a full-expression. Thus, the ! destructor would run too early; it would run at the ! end of initializing the reference variable, rather ! than at the end of the block enclosing the ! reference variable. ! ! The solution is to pass back a cleanup expression ! which the caller is responsible for attaching to ! the statement tree. */ ! } ! else ! { ! rest_of_decl_compilation (var, /*toplev=*/1, at_eof); ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! static_aggregates = tree_cons (NULL_TREE, var, ! static_aggregates); ! } ! /* Use its address to initialize the reference variable. */ ! expr = build_address (var); ! if (base_conv_type) ! expr = convert_to_base (expr, ! build_pointer_type (base_conv_type), ! /*check_access=*/true, ! /*nonnull=*/true); ! expr = build2 (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)); ! expr = build_nop (type, expr); } } + else + /* Perform the conversion. */ + expr = convert_like (conv, expr); ! /* Free all the conversions we allocated. */ ! obstack_free (&conversion_obstack, p); ! ! return expr; } #include "gt-cp-call.h" diff -Nrcpad gcc-3.4.3/gcc/cp/class.c gcc-4.0.0/gcc/cp/class.c *** gcc-3.4.3/gcc/cp/class.c Thu Aug 12 18:04:54 2004 --- gcc-4.0.0/gcc/cp/class.c Mon Mar 7 23:07:08 2005 *************** *** 1,6 **** /* Functions related to building classes and their related objects. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Functions related to building classes and their related objects. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 33,39 **** #include "rtl.h" #include "output.h" #include "toplev.h" - #include "lex.h" #include "target.h" #include "convert.h" --- 33,38 ---- *************** static void modify_vtable_entry (tree, t *** 117,153 **** static void finish_struct_bits (tree); static int alter_access (tree, tree, tree); static void handle_using_decl (tree, tree); - static void check_for_override (tree, tree); static tree dfs_modify_vtables (tree, void *); static tree modify_all_vtables (tree, tree); ! static void determine_primary_base (tree); static void finish_struct_methods (tree); static void maybe_warn_about_overly_private_class (tree); static int method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *); ! static void add_implicitly_declared_members (tree, int, int, int); static tree fixed_type_or_null (tree, int *, int *); static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t, bool, tree); static tree build_vtbl_ref_1 (tree, tree); static tree build_vtbl_initializer (tree, tree, tree, tree, int *); static int count_fields (tree); static int add_fields_to_record_type (tree, struct sorted_fields_type*, int); static void check_bitfield_decl (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 (tree); static void remove_zero_width_bit_fields (tree); ! static void check_bases (tree, int *, int *, int *); 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 (tree); static void fixup_inline_methods (tree); - static void set_primary_base (tree, tree); static void propagate_binfo_offsets (tree, tree); static void layout_virtual_bases (record_layout_info, splay_tree); static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *); --- 116,151 ---- static void finish_struct_bits (tree); static int alter_access (tree, tree, tree); static void handle_using_decl (tree, tree); static tree dfs_modify_vtables (tree, void *); static tree modify_all_vtables (tree, tree); ! static void determine_primary_bases (tree); static void finish_struct_methods (tree); static void maybe_warn_about_overly_private_class (tree); static int method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *); ! static void add_implicitly_declared_members (tree, int, int); static tree fixed_type_or_null (tree, int *, int *); static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t, bool, tree); + static tree build_simple_base_path (tree expr, tree binfo); static tree build_vtbl_ref_1 (tree, tree); static tree build_vtbl_initializer (tree, tree, tree, tree, int *); static int count_fields (tree); static int add_fields_to_record_type (tree, struct sorted_fields_type*, int); static void check_bitfield_decl (tree); ! static void check_field_decl (tree, tree, int *, int *, int *); ! static void check_field_decls (tree, tree *, 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 (tree); static void remove_zero_width_bit_fields (tree); ! static void check_bases (tree, int *, int *); 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 (tree); static void fixup_inline_methods (tree); static void propagate_binfo_offsets (tree, tree); static void layout_virtual_bases (record_layout_info, splay_tree); static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *); *************** static void add_vcall_offset_vtbl_entrie *** 156,164 **** static void build_vcall_offset_vtbl_entries (tree, vtbl_init_data *); static void add_vcall_offset (tree, tree, vtbl_init_data *); static void layout_vtable_decl (tree, int); ! static tree dfs_find_final_overrider (tree, void *); static tree dfs_find_final_overrider_post (tree, void *); - static tree dfs_find_final_overrider_q (tree, int, void *); static tree find_final_overrider (tree, tree, tree); static int make_new_vtable (tree, tree); static int maybe_indent_hierarchy (FILE *, int, int); --- 154,161 ---- static void build_vcall_offset_vtbl_entries (tree, vtbl_init_data *); static void add_vcall_offset (tree, tree, vtbl_init_data *); static void layout_vtable_decl (tree, int); ! static tree dfs_find_final_overrider_pre (tree, void *); static tree dfs_find_final_overrider_post (tree, void *); static tree find_final_overrider (tree, tree, tree); static int make_new_vtable (tree, tree); static int maybe_indent_hierarchy (FILE *, int, int); *************** static void dump_vtt (tree, tree); *** 171,207 **** static void dump_thunk (FILE *, int, tree); static tree build_vtable (tree, tree, tree); static void initialize_vtable (tree, tree); - static void initialize_array (tree, tree); static void layout_nonempty_base_or_field (record_layout_info, ! tree, tree, splay_tree); static tree end_of_class (tree, int); static bool layout_empty_base (tree, tree, splay_tree); static void accumulate_vtbl_inits (tree, tree, tree, tree, tree); static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree); static void build_rtti_vtbl_entries (tree, vtbl_init_data *); ! static void build_vcall_and_vbase_vtbl_entries (tree, ! vtbl_init_data *); ! static void mark_primary_bases (tree); static void clone_constructors_and_destructors (tree); static tree build_clone (tree, tree); static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned); - static tree copy_virtuals (tree); static void build_ctor_vtbl_group (tree, tree); static void build_vtt (tree); static tree binfo_ctor_vtable (tree); static tree *build_vtt_inits (tree, tree, tree *, tree *); static tree dfs_build_secondary_vptr_vtt_inits (tree, void *); - static tree dfs_ctor_vtable_bases_queue_p (tree, int, void *data); static tree dfs_fixup_binfo_vtbls (tree, void *); static int record_subobject_offset (tree, tree, splay_tree); static int check_subobject_offset (tree, tree, splay_tree); static int walk_subobject_offsets (tree, subobject_offset_fn, ! tree, splay_tree, tree, int); static void record_subobject_offsets (tree, tree, splay_tree, int); static int layout_conflict_p (tree, tree, splay_tree, int); static int splay_tree_compare_integer_csts (splay_tree_key k1, ! splay_tree_key k2); static void warn_about_ambiguous_bases (tree); static bool type_requires_array_cookie (tree); static bool contains_empty_class_p (tree); --- 168,199 ---- static void dump_thunk (FILE *, int, tree); static tree build_vtable (tree, tree, tree); static void initialize_vtable (tree, tree); static void layout_nonempty_base_or_field (record_layout_info, ! tree, tree, splay_tree); static tree end_of_class (tree, int); static bool layout_empty_base (tree, tree, splay_tree); static void accumulate_vtbl_inits (tree, tree, tree, tree, tree); static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree); static void build_rtti_vtbl_entries (tree, vtbl_init_data *); ! static void build_vcall_and_vbase_vtbl_entries (tree, vtbl_init_data *); static void clone_constructors_and_destructors (tree); static tree build_clone (tree, tree); static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned); static void build_ctor_vtbl_group (tree, tree); static void build_vtt (tree); static tree binfo_ctor_vtable (tree); static tree *build_vtt_inits (tree, tree, tree *, tree *); static tree dfs_build_secondary_vptr_vtt_inits (tree, void *); static tree dfs_fixup_binfo_vtbls (tree, void *); static int record_subobject_offset (tree, tree, splay_tree); static int check_subobject_offset (tree, tree, splay_tree); static int walk_subobject_offsets (tree, subobject_offset_fn, ! tree, splay_tree, tree, int); static void record_subobject_offsets (tree, tree, splay_tree, int); static int layout_conflict_p (tree, tree, splay_tree, int); static int splay_tree_compare_integer_csts (splay_tree_key k1, ! splay_tree_key k2); static void warn_about_ambiguous_bases (tree); static bool type_requires_array_cookie (tree); static bool contains_empty_class_p (tree); *************** static int empty_base_at_nonzero_offset_ *** 210,221 **** 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 - and dfs_fixup_binfo_vtbls. */ - #define VTT_TOP_LEVEL_P(NODE) TREE_UNSIGNED (NODE) - #define VTT_MARKED_BINFO_P(NODE) TREE_USED (NODE) - /* Variables shared between class.c and call.c. */ #ifdef GATHER_STATISTICS --- 202,207 ---- *************** build_base_path (enum tree_code code, *** 253,258 **** --- 239,246 ---- tree ptr_target_type; int fixed_type_p; int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE; + bool has_empty = false; + bool virtual_access; if (expr == error_mark_node || binfo == error_mark_node || !binfo) return error_mark_node; *************** build_base_path (enum tree_code code, *** 260,282 **** for (probe = binfo; probe; probe = BINFO_INHERITANCE_CHAIN (probe)) { d_binfo = probe; ! if (!v_binfo && TREE_VIA_VIRTUAL (probe)) v_binfo = probe; } probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); if (want_pointer) probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe)); ! my_friendly_assert (code == MINUS_EXPR ! ? same_type_p (BINFO_TYPE (binfo), probe) ! : code == PLUS_EXPR ! ? same_type_p (BINFO_TYPE (d_binfo), probe) ! : false, 20010723); ! if (code == MINUS_EXPR && v_binfo) { ! error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'", BINFO_TYPE (binfo), BINFO_TYPE (d_binfo), BINFO_TYPE (v_binfo)); return error_mark_node; } --- 248,275 ---- for (probe = binfo; probe; probe = BINFO_INHERITANCE_CHAIN (probe)) { d_binfo = probe; ! if (is_empty_class (BINFO_TYPE (probe))) ! has_empty = true; ! if (!v_binfo && BINFO_VIRTUAL_P (probe)) v_binfo = probe; } probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); if (want_pointer) probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe)); + + gcc_assert ((code == MINUS_EXPR + && SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), probe)) + || (code == PLUS_EXPR + && SAME_BINFO_TYPE_P (BINFO_TYPE (d_binfo), probe))); ! if (binfo == d_binfo) ! /* Nothing to do. */ ! return expr; ! if (code == MINUS_EXPR && v_binfo) { ! error ("cannot convert from base %qT to derived type %qT via virtual base %qT", BINFO_TYPE (binfo), BINFO_TYPE (d_binfo), BINFO_TYPE (v_binfo)); return error_mark_node; } *************** build_base_path (enum tree_code code, *** 285,300 **** /* 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 && !nonnull) ! null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node); ! ! offset = BINFO_OFFSET (binfo); ! ! if (v_binfo && fixed_type_p <= 0) { /* Going via virtual base V_BINFO. We need the static offset from V_BINFO to BINFO, and the dynamic offset from D_BINFO to --- 278,320 ---- /* This must happen before the call to save_expr. */ expr = build_unary_op (ADDR_EXPR, expr, 0); + offset = BINFO_OFFSET (binfo); fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); ! ! /* Do we need to look in the vtable for the real offset? */ ! virtual_access = (v_binfo && fixed_type_p <= 0); ! ! /* Do we need to check for a null pointer? */ ! if (want_pointer && !nonnull && (virtual_access || !integer_zerop (offset))) ! null_test = error_mark_node; ! ! /* Protect against multiple evaluation if necessary. */ ! if (TREE_SIDE_EFFECTS (expr) && (null_test || virtual_access)) expr = save_expr (expr); ! /* Now that we've saved expr, build the real null test. */ ! if (null_test) ! { ! tree zero = cp_convert (TREE_TYPE (expr), integer_zero_node); ! null_test = fold (build2 (NE_EXPR, boolean_type_node, ! expr, zero)); ! } ! ! /* If this is a simple base reference, express it as a COMPONENT_REF. */ ! if (code == PLUS_EXPR && !virtual_access ! /* We don't build base fields for empty bases, and they aren't very ! interesting to the optimizers anyway. */ ! && !has_empty) ! { ! expr = build_indirect_ref (expr, NULL); ! expr = build_simple_base_path (expr, binfo); ! if (want_pointer) ! expr = build_address (expr); ! target_type = TREE_TYPE (expr); ! goto out; ! } ! ! if (virtual_access) { /* Going via virtual base V_BINFO. We need the static offset from V_BINFO to BINFO, and the dynamic offset from D_BINFO to *************** build_base_path (enum tree_code code, *** 306,347 **** /* In a base member initializer, we cannot rely on the vtable being set up. We have to use the vtt_parm. */ tree derived = BINFO_INHERITANCE_CHAIN (v_binfo); ! ! 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_offset = build (PLUS_EXPR, TREE_TYPE (v_offset), ! v_offset, BINFO_VPTR_FIELD (v_binfo)); v_offset = build1 (NOP_EXPR, build_pointer_type (ptrdiff_type_node), v_offset); v_offset = build_indirect_ref (v_offset, NULL); offset = convert_to_integer (ptrdiff_type_node, size_diffop (offset, BINFO_OFFSET (v_binfo))); if (!integer_zerop (offset)) ! v_offset = build (code, ptrdiff_type_node, v_offset, offset); if (fixed_type_p < 0) /* Negative fixed_type_p means this is a constructor or destructor; virtual base layout is fixed in in-charge [cd]tors, but not in base [cd]tors. */ ! offset = build (COND_EXPR, ptrdiff_type_node, ! build (EQ_EXPR, boolean_type_node, ! current_in_charge_parm, integer_zero_node), ! v_offset, ! BINFO_OFFSET (binfo)); else offset = v_offset; } --- 326,369 ---- /* In a base member initializer, we cannot rely on the vtable being set up. We have to use the vtt_parm. */ tree derived = BINFO_INHERITANCE_CHAIN (v_binfo); ! tree t; ! ! t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))); ! t = build_pointer_type (t); ! v_offset = convert (t, current_vtt_parm); ! v_offset = build2 (PLUS_EXPR, t, v_offset, ! BINFO_VPTR_INDEX (derived)); ! v_offset = build_indirect_ref (v_offset, NULL); } else v_offset = build_vfield_ref (build_indirect_ref (expr, NULL), TREE_TYPE (TREE_TYPE (expr))); ! v_offset = build2 (PLUS_EXPR, TREE_TYPE (v_offset), ! v_offset, BINFO_VPTR_FIELD (v_binfo)); v_offset = build1 (NOP_EXPR, build_pointer_type (ptrdiff_type_node), v_offset); v_offset = build_indirect_ref (v_offset, NULL); + TREE_CONSTANT (v_offset) = 1; + TREE_INVARIANT (v_offset) = 1; offset = convert_to_integer (ptrdiff_type_node, size_diffop (offset, BINFO_OFFSET (v_binfo))); if (!integer_zerop (offset)) ! v_offset = build2 (code, ptrdiff_type_node, v_offset, offset); if (fixed_type_p < 0) /* Negative fixed_type_p means this is a constructor or destructor; virtual base layout is fixed in in-charge [cd]tors, but not in base [cd]tors. */ ! offset = build3 (COND_EXPR, ptrdiff_type_node, ! build2 (EQ_EXPR, boolean_type_node, ! current_in_charge_parm, integer_zero_node), ! v_offset, ! BINFO_OFFSET (binfo)); else offset = v_offset; } *************** build_base_path (enum tree_code code, *** 357,397 **** expr = build1 (NOP_EXPR, ptr_target_type, expr); if (!integer_zerop (offset)) ! expr = build (code, ptr_target_type, expr, offset); else null_test = NULL; if (!want_pointer) expr = build_indirect_ref (expr, NULL); if (null_test) ! expr = build (COND_EXPR, target_type, null_test, ! build1 (NOP_EXPR, target_type, integer_zero_node), ! expr); 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); } ! /* EXPR is an expression with class type. BASE is a base class (a ! BINFO) of that class type. Returns EXPR, converted to the BASE type. This function assumes that EXPR is the most derived class; therefore virtual bases can be found at their static offsets. */ --- 379,495 ---- expr = build1 (NOP_EXPR, ptr_target_type, expr); if (!integer_zerop (offset)) ! expr = build2 (code, ptr_target_type, expr, offset); else null_test = NULL; if (!want_pointer) expr = build_indirect_ref (expr, NULL); + out: if (null_test) ! expr = fold (build3 (COND_EXPR, target_type, null_test, expr, ! fold (build1 (NOP_EXPR, target_type, ! integer_zero_node)))); return expr; } ! /* Subroutine of build_base_path; EXPR and BINFO are as in that function. ! Perform a derived-to-base conversion by recursively building up a ! sequence of COMPONENT_REFs to the appropriate base fields. */ ! ! static tree ! build_simple_base_path (tree expr, tree binfo) ! { ! tree type = BINFO_TYPE (binfo); ! tree d_binfo = BINFO_INHERITANCE_CHAIN (binfo); ! tree field; ! ! if (d_binfo == NULL_TREE) ! { ! tree temp; ! ! gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type); ! ! /* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x' ! into `(*(a ? &b : &c)).x', and so on. A COND_EXPR is only ! an lvalue in the frontend; only _DECLs and _REFs are lvalues ! in the backend. */ ! temp = unary_complex_lvalue (ADDR_EXPR, expr); ! if (temp) ! expr = build_indirect_ref (temp, NULL); ! ! return expr; ! } ! ! /* Recurse. */ ! expr = build_simple_base_path (expr, d_binfo); ! ! for (field = TYPE_FIELDS (BINFO_TYPE (d_binfo)); ! field; field = TREE_CHAIN (field)) ! /* Is this the base field created by build_base_field? */ ! if (TREE_CODE (field) == FIELD_DECL ! && DECL_FIELD_IS_BASE (field) ! && TREE_TYPE (field) == type) ! { ! /* We don't use build_class_member_access_expr here, as that ! has unnecessary checks, and more importantly results in ! recursive calls to dfs_walk_once. */ ! int type_quals = cp_type_quals (TREE_TYPE (expr)); ! ! expr = build3 (COMPONENT_REF, ! cp_build_qualified_type (type, type_quals), ! expr, field, NULL_TREE); ! expr = fold_if_not_in_template (expr); ! ! /* 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 (expr) = 1; ! if (type_quals & TYPE_QUAL_VOLATILE) ! TREE_THIS_VOLATILE (expr) = 1; ! ! return expr; ! } ! ! /* Didn't find the base field?!? */ ! gcc_unreachable (); ! } ! ! /* Convert OBJECT to the base TYPE. OBJECT is an expression whose ! type is a class type or a pointer to a class type. In the former ! case, TYPE is also a class type; in the latter it is another ! pointer type. If CHECK_ACCESS is true, an error message is emitted ! if TYPE is inaccessible. If OBJECT has pointer type, the value is ! assumed to be non-NULL. */ tree ! convert_to_base (tree object, tree type, bool check_access, bool nonnull) { tree binfo; + tree object_type; ! if (TYPE_PTR_P (TREE_TYPE (object))) ! { ! object_type = TREE_TYPE (TREE_TYPE (object)); ! type = TREE_TYPE (type); ! } ! else ! object_type = TREE_TYPE (object); ! ! binfo = lookup_base (object_type, type, ! check_access ? ba_check : ba_unique, NULL); if (!binfo || binfo == error_mark_node) return error_mark_node; ! return build_base_path (PLUS_EXPR, object, binfo, nonnull); } ! /* EXPR is an expression with unqualified class type. BASE is a base ! binfo of that class type. Returns EXPR, converted to the BASE type. This function assumes that EXPR is the most derived class; therefore virtual bases can be found at their static offsets. */ *************** convert_to_base_statically (tree expr, t *** 401,415 **** tree expr_type; expr_type = TREE_TYPE (expr); ! if (!same_type_p (expr_type, BINFO_TYPE (base))) { tree pointer_type; pointer_type = build_pointer_type (expr_type); expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1); if (!integer_zerop (BINFO_OFFSET (base))) ! expr = build (PLUS_EXPR, pointer_type, expr, ! build_nop (pointer_type, BINFO_OFFSET (base))); expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr); expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr); } --- 499,513 ---- tree expr_type; expr_type = TREE_TYPE (expr); ! if (!SAME_BINFO_TYPE_P (BINFO_TYPE (base), expr_type)) { tree pointer_type; pointer_type = build_pointer_type (expr_type); expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1); if (!integer_zerop (BINFO_OFFSET (base))) ! expr = build2 (PLUS_EXPR, pointer_type, expr, ! build_nop (pointer_type, BINFO_OFFSET (base))); expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr); expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr); } *************** convert_to_base_statically (tree expr, t *** 418,423 **** --- 516,551 ---- } + tree + build_vfield_ref (tree datum, tree type) + { + tree vfield, vcontext; + + if (datum == error_mark_node) + return error_mark_node; + + /* First, convert to the requested type. */ + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type)) + datum = convert_to_base (datum, type, /*check_access=*/false, + /*nonnull=*/true); + + /* Second, the requested type may not be the owner of its own vptr. + If not, convert to the base class that owns it. We cannot use + convert_to_base here, because VCONTEXT may appear more than once + in the inheritance hierarchy of TYPE, and thus direct conversion + between the types may be ambiguous. Following the path back up + one step at a time via primary bases avoids the problem. */ + vfield = TYPE_VFIELD (type); + vcontext = DECL_CONTEXT (vfield); + while (!same_type_ignoring_top_level_qualifiers_p (vcontext, type)) + { + datum = build_simple_base_path (datum, CLASSTYPE_PRIMARY_BINFO (type)); + type = TREE_TYPE (datum); + } + + return build3 (COMPONENT_REF, TREE_TYPE (vfield), datum, vfield, NULL_TREE); + } + /* Given an object INSTANCE, return an expression which yields the vtable element corresponding to INDEX. There are many special cases for INSTANCE which we take care of here, mainly to avoid *************** build_vtbl_ref_1 (tree instance, tree id *** 440,448 **** if (fixed_type && !cdtorp) { tree binfo = lookup_base (fixed_type, basetype, ! ba_ignore|ba_quiet, NULL); if (binfo) ! vtbl = BINFO_VTABLE (binfo); } if (!vtbl) --- 568,576 ---- if (fixed_type && !cdtorp) { tree binfo = lookup_base (fixed_type, basetype, ! ba_unique | ba_quiet, NULL); if (binfo) ! vtbl = unshare_expr (BINFO_VTABLE (binfo)); } if (!vtbl) *************** build_vtbl_ref_1 (tree instance, tree id *** 451,456 **** --- 579,586 ---- assemble_external (vtbl); aref = build_array_ref (vtbl, idx); + TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx); + TREE_INVARIANT (aref) = TREE_CONSTANT (aref); return aref; } *************** build_vtbl_ref (tree instance, tree idx) *** 463,475 **** return aref; } ! /* Given an object INSTANCE, return an expression which yields a ! function pointer corresponding to vtable element INDEX. */ tree ! build_vfn_ref (tree instance, tree idx) { ! tree aref = build_vtbl_ref_1 (instance, idx); /* When using function descriptors, the address of the vtable entry is treated as a function pointer. */ --- 593,607 ---- return aref; } ! /* Given a stable object pointer INSTANCE_PTR, return an expression which ! yields a function pointer corresponding to vtable element INDEX. */ tree ! build_vfn_ref (tree instance_ptr, tree idx) { ! tree aref; ! ! aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx); /* When using function descriptors, the address of the vtable entry is treated as a function pointer. */ *************** build_vfn_ref (tree instance, tree idx) *** 477,482 **** --- 609,617 ---- aref = build1 (NOP_EXPR, TREE_TYPE (aref), build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1)); + /* Remember this as a method reference, for later devirtualization. */ + aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx); + return aref; } *************** get_vtt_name (tree type) *** 498,503 **** --- 633,664 ---- return mangle_vtt_for_type (type); } + /* DECL is an entity associated with TYPE, like a virtual table or an + implicitly generated constructor. Determine whether or not DECL + should have external or internal linkage at the object file + level. This routine does not deal with COMDAT linkage and other + similar complexities; it simply sets TREE_PUBLIC if it possible for + entities in other translation units to contain copies of DECL, in + the abstract. */ + + void + set_linkage_according_to_type (tree type, tree decl) + { + /* If TYPE involves a local class in a function with internal + linkage, then DECL should have internal linkage too. Other local + classes have no linkage -- but if their containing functions + have external linkage, it makes sense for DECL to have external + linkage too. That will allow template definitions to be merged, + for example. */ + if (no_linkage_check (type, /*relaxed_p=*/true)) + { + TREE_PUBLIC (decl) = 0; + DECL_INTERFACE_KNOWN (decl) = 1; + } + else + TREE_PUBLIC (decl) = 1; + } + /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE. (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.) Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */ *************** build_vtable (tree class_type, tree name *** 518,530 **** DECL_VIRTUAL_P (decl) = 1; DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN; DECL_VTABLE_OR_VTT_P (decl) = 1; - /* 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), DECL_ALIGN (decl)); ! import_export_vtable (decl, class_type, 0); return decl; } --- 679,714 ---- DECL_VIRTUAL_P (decl) = 1; DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN; DECL_VTABLE_OR_VTT_P (decl) = 1; /* 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), DECL_ALIGN (decl)); + set_linkage_according_to_type (class_type, decl); + /* The vtable has not been defined -- yet. */ + DECL_EXTERNAL (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; ! /* Mark the VAR_DECL node representing the vtable itself as a ! "gratuitous" one, thereby forcing dwarfout.c to ignore it. It ! is rather important that such things be ignored because any ! effort to actually generate DWARF for them will run into ! trouble when/if we encounter code like: ! ! #pragma interface ! struct S { virtual void member (); }; ! ! because the artificial declaration of the vtable itself (as ! manufactured by the g++ front end) will say that the vtable is ! a static member of `S' but only *after* the debug output for ! the definition of `S' has already been output. This causes ! grief because the DWARF entry for the definition of the vtable ! will try to refer back to an earlier *declaration* of the ! vtable as a static member of `S' and there won't be one. We ! might be able to arrange to have the "vtable static member" ! attached to the member list for `S' before the debug info for ! `S' get written (which would solve the problem) but that would ! require more intrusive changes to the g++ front end. */ ! DECL_IGNORED_P (decl) = 1; return decl; } *************** get_vtable_decl (tree type, int complete *** 555,576 **** return decl; } - /* Returns a copy of the BINFO_VIRTUALS list in BINFO. The - BV_VCALL_INDEX for each entry is cleared. */ - - static tree - copy_virtuals (tree binfo) - { - tree copies; - tree t; - - copies = copy_list (BINFO_VIRTUALS (binfo)); - for (t = copies; t; t = TREE_CHAIN (t)) - BV_VCALL_INDEX (t) = NULL_TREE; - - return copies; - } - /* 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 --- 739,744 ---- *************** build_primary_vtable (tree binfo, tree t *** 592,605 **** no need to do it again. */ return 0; ! virtuals = copy_virtuals (binfo); TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo)); DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl)); DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl)); } else { ! my_friendly_assert (TREE_TYPE (decl) == vtbl_type_node, 20000118); virtuals = NULL_TREE; } --- 760,773 ---- no need to do it again. */ return 0; ! virtuals = copy_list (BINFO_VIRTUALS (binfo)); TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo)); DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl)); DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl)); } else { ! gcc_assert (TREE_TYPE (decl) == vtbl_type_node); virtuals = NULL_TREE; } *************** build_primary_vtable (tree binfo, tree t *** 610,617 **** /* Initialize the association list for this type, based on our first approximation. */ ! TYPE_BINFO_VTABLE (type) = decl; ! TYPE_BINFO_VIRTUALS (type) = virtuals; SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type)); return 1; } --- 778,785 ---- /* Initialize the association list for this type, based on our first approximation. */ ! BINFO_VTABLE (TYPE_BINFO (type)) = decl; ! BINFO_VIRTUALS (TYPE_BINFO (type)) = virtuals; SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type)); return 1; } *************** build_secondary_vtable (tree binfo) *** 643,649 **** SET_BINFO_NEW_VTABLE_MARKED (binfo); /* Make fresh virtual list, so we can smash it later. */ ! BINFO_VIRTUALS (binfo) = copy_virtuals (binfo); /* Secondary vtables are laid out as part of the same structure as the primary vtable. */ --- 811,817 ---- SET_BINFO_NEW_VTABLE_MARKED (binfo); /* Make fresh virtual list, so we can smash it later. */ ! BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); /* Secondary vtables are laid out as part of the same structure as the primary vtable. */ *************** make_new_vtable (tree t, tree binfo) *** 661,670 **** /* In this case, it is *type*'s vtable we are modifying. We start with the approximation that its vtable is that of the immediate base class. */ ! /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo, ! since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */ ! return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), ! t); else /* This is our very own copy of `basetype' to play with. Later, we will fill in all the virtual functions that override the --- 829,835 ---- /* In this case, it is *type*'s vtable we are modifying. We start with the approximation that its vtable is that of the immediate base class. */ ! return build_primary_vtable (binfo, t); else /* This is our very own copy of `basetype' to play with. Later, we will fill in all the virtual functions that override the *************** modify_vtable_entry (tree t, *** 712,753 **** } ! /* 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 ! declaration for it was seen. (Even though that is erroneous, we ! add the method for improved error recovery.) */ void ! add_method (tree type, tree method, int error_p) { int using; ! int len; ! int slot; ! tree method_vec; ! int template_conv_p; if (method == error_mark_node) return; - - using = (DECL_CONTEXT (method) != type); - 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 ! allocate at least two (for constructors and destructors), and ! we're going to end up with an assignment operator at some point ! as well. ! ! We could use a TREE_LIST for now, and convert it to a TREE_VEC ! in finish_struct, but we would probably waste more memory ! making the links in the list than we would by over-allocating ! the size of the vector here. Furthermore, we would complicate ! all the code that expects this to be a vector. */ ! CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8); method_vec = CLASSTYPE_METHOD_VEC (type); ! len = TREE_VEC_LENGTH (method_vec); /* Constructors and destructors go in special slots. */ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method)) --- 877,920 ---- } ! /* Add method METHOD to class TYPE. */ void ! add_method (tree type, tree method) { int using; ! unsigned slot; ! tree overload; ! bool template_conv_p = false; ! bool conv_p; ! VEC(tree) *method_vec; ! bool complete_p; ! bool insert_p = false; ! tree current_fns; if (method == error_mark_node) return; ! complete_p = COMPLETE_TYPE_P (type); ! using = (DECL_CONTEXT (method) != type); ! conv_p = DECL_CONV_FN_P (method); ! if (conv_p) ! template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL ! && DECL_TEMPLATE_CONV_FN_P (method)); method_vec = CLASSTYPE_METHOD_VEC (type); ! if (!method_vec) ! { ! /* Make a new method vector. We start with 8 entries. We must ! allocate at least two (for constructors and destructors), and ! we're going to end up with an assignment operator at some ! point as well. */ ! method_vec = VEC_alloc (tree, 8); ! /* Create slots for constructors and destructors. */ ! VEC_quick_push (tree, method_vec, NULL_TREE); ! VEC_quick_push (tree, method_vec, NULL_TREE); ! CLASSTYPE_METHOD_VEC (type) = method_vec; ! } /* Constructors and destructors go in special slots. */ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method)) *************** add_method (tree type, tree method, int *** 755,869 **** else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method)) { slot = CLASSTYPE_DESTRUCTOR_SLOT; - TYPE_HAS_DESTRUCTOR (type) = 1; if (TYPE_FOR_JAVA (type)) ! error (DECL_ARTIFICIAL (method) ! ? "Java class '%T' cannot have an implicit non-trivial destructor" ! : "Java class '%T' cannot have a destructor", ! DECL_CONTEXT (method)); } 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) { - 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. */ ! int new_len; ! tree new_vec; ! ! /* In the non-error case, we are processing a class ! definition. Double the size of the vector to give room ! for new methods. */ ! if (!error_p) ! new_len = 2 * len; ! /* In the error case, the vector is already complete. We ! don't expect many errors, and the rest of the front-end ! will get confused if there are empty slots in the vector. */ ! else ! new_len = len + 1; ! ! new_vec = make_tree_vec (new_len); ! memcpy (&TREE_VEC_ELT (new_vec, 0), &TREE_VEC_ELT (method_vec, 0), ! len * sizeof (tree)); ! len = new_len; ! method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec; ! } ! ! if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot)) ! { ! /* Type conversion operators have to come before ordinary ! methods; add_conversions depends on this to speed up ! looking for conversion operators. So, if necessary, we ! slide some of the vector elements up. In theory, this ! makes this algorithm O(N^2) but we don't expect many ! conversion operators. */ ! 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 (!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. */ ! ; ! else { ! /* We know the last slot in the vector is empty ! because we know that at this point there's room ! for a new function. */ ! memmove (&TREE_VEC_ELT (method_vec, slot + 1), ! &TREE_VEC_ELT (method_vec, slot), ! (len - slot - 1) * sizeof (tree)); ! TREE_VEC_ELT (method_vec, slot) = NULL_TREE; } } } ! if (processing_template_decl) /* TYPE is a template class. Don't issue any errors now; wait until instantiation time to complain. */ --- 922,971 ---- else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method)) { slot = CLASSTYPE_DESTRUCTOR_SLOT; if (TYPE_FOR_JAVA (type)) ! { ! if (!DECL_ARTIFICIAL (method)) ! error ("Java class %qT cannot have a destructor", type); ! else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! error ("Java class %qT cannot have an implicit non-trivial " ! "destructor", ! type); ! } } else { ! tree m; ! ! insert_p = true; /* See if we already have an entry with this name. */ ! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; ! VEC_iterate (tree, method_vec, slot, m); ! ++slot) { m = OVL_CURRENT (m); if (template_conv_p) { ! if (TREE_CODE (m) == TEMPLATE_DECL ! && DECL_TEMPLATE_CONV_FN_P (m)) ! insert_p = false; break; } ! if (conv_p && !DECL_CONV_FN_P (m)) break; ! if (DECL_NAME (m) == DECL_NAME (method)) { ! insert_p = false; ! break; } + if (complete_p + && !DECL_CONV_FN_P (m) + && DECL_NAME (m) > DECL_NAME (method)) + break; } } ! current_fns = insert_p ? NULL_TREE : VEC_index (tree, method_vec, slot); ! if (processing_template_decl) /* TYPE is a template class. Don't issue any errors now; wait until instantiation time to complain. */ *************** add_method (tree type, tree method, int *** 873,881 **** tree fns; /* Check to see if we've already got this method. */ ! for (fns = TREE_VEC_ELT (method_vec, slot); ! fns; ! fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); tree parms1; --- 975,981 ---- tree fns; /* Check to see if we've already got this method. */ ! for (fns = current_fns; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); tree parms1; *************** add_method (tree type, tree method, int *** 928,934 **** return; else { ! cp_error_at ("`%#D' and `%#D' cannot be overloaded", method, fn); /* We don't call duplicate_decls here to merge --- 1028,1034 ---- return; else { ! cp_error_at ("%q#D and %q#D cannot be overloaded", method, fn); /* We don't call duplicate_decls here to merge *************** add_method (tree type, tree method, int *** 942,956 **** } } - /* Actually insert the new method. */ - TREE_VEC_ELT (method_vec, slot) - = build_overload (method, TREE_VEC_ELT (method_vec, slot)); - /* Add the new binding. */ ! if (!DECL_CONSTRUCTOR_P (method) ! && !DECL_DESTRUCTOR_P (method)) ! push_class_level_binding (DECL_NAME (method), ! TREE_VEC_ELT (method_vec, slot)); } /* Subroutines of finish_struct. */ --- 1042,1067 ---- } } /* Add the new binding. */ ! overload = build_overload (method, current_fns); ! ! if (!conv_p && slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p) ! push_class_level_binding (DECL_NAME (method), overload); ! ! if (insert_p) ! { ! /* We only expect to add few methods in the COMPLETE_P case, so ! just make room for one more method in that case. */ ! if (VEC_reserve (tree, method_vec, complete_p ? 1 : -1)) ! CLASSTYPE_METHOD_VEC (type) = method_vec; ! if (slot == VEC_length (tree, method_vec)) ! VEC_quick_push (tree, method_vec, overload); ! else ! VEC_quick_insert (tree, method_vec, slot, overload); ! } ! else ! /* Replace the current slot. */ ! VEC_replace (tree, method_vec, slot, overload); } /* Subroutines of finish_struct. */ *************** alter_access (tree t, tree fdecl, tree a *** 966,972 **** if (!DECL_LANG_SPECIFIC (fdecl)) retrofit_lang_decl (fdecl); ! my_friendly_assert (!DECL_DISCRIMINATOR_P (fdecl), 20030624); elem = purpose_member (t, DECL_ACCESS (fdecl)); if (elem) --- 1077,1083 ---- if (!DECL_LANG_SPECIFIC (fdecl)) retrofit_lang_decl (fdecl); ! gcc_assert (!DECL_DISCRIMINATOR_P (fdecl)); elem = purpose_member (t, DECL_ACCESS (fdecl)); if (elem) *************** alter_access (tree t, tree fdecl, tree a *** 974,983 **** if (TREE_VALUE (elem) != access) { if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) ! cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); else ! error ("conflicting access specifications for field `%s', ignored", ! IDENTIFIER_POINTER (DECL_NAME (fdecl))); } else { --- 1085,1095 ---- if (TREE_VALUE (elem) != access) { if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) ! cp_error_at ("conflicting access specifications for method" ! " %qD, ignored", TREE_TYPE (fdecl)); else ! error ("conflicting access specifications for field %qE, ignored", ! DECL_NAME (fdecl)); } else { *************** handle_using_decl (tree using_decl, tree *** 1026,1037 **** if (constructor_name_p (name, ctype)) { ! cp_error_at ("`%D' names constructor", using_decl); return; } if (constructor_name_p (name, t)) { ! cp_error_at ("`%D' invalid in `%T'", using_decl, t); return; } --- 1138,1149 ---- if (constructor_name_p (name, ctype)) { ! cp_error_at ("%qD names constructor", using_decl); return; } if (constructor_name_p (name, t)) { ! cp_error_at ("%qD invalid in %qT", using_decl, t); return; } *************** handle_using_decl (tree using_decl, tree *** 1039,1045 **** if (!fdecl) { ! cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype); return; } --- 1151,1157 ---- if (!fdecl) { ! cp_error_at ("no members matching %qD in %q#T", using_decl, ctype); return; } *************** handle_using_decl (tree using_decl, tree *** 1047,1053 **** /* Ignore base type this came from. */ fdecl = BASELINK_FUNCTIONS (fdecl); ! old_value = IDENTIFIER_CLASS_VALUE (name); if (old_value) { if (is_overloaded_fn (old_value)) --- 1159,1165 ---- /* Ignore base type this came from. */ fdecl = BASELINK_FUNCTIONS (fdecl); ! old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false); if (old_value) { if (is_overloaded_fn (old_value)) *************** handle_using_decl (tree using_decl, tree *** 1071,1086 **** the same name already present in the current class. */; else { ! cp_error_at ("`%D' invalid in `%#T'", using_decl, t); ! cp_error_at (" because of local method `%#D' with same name", OVL_CURRENT (old_value)); return; } } else if (!DECL_ARTIFICIAL (old_value)) { ! cp_error_at ("`%D' invalid in `%#T'", using_decl, t); ! cp_error_at (" because of local member `%#D' with same name", old_value); return; } --- 1183,1198 ---- the same name already present in the current class. */; else { ! cp_error_at ("%qD invalid in %q#T", using_decl, t); ! cp_error_at (" because of local method %q#D with same name", OVL_CURRENT (old_value)); return; } } else if (!DECL_ARTIFICIAL (old_value)) { ! cp_error_at ("%qD invalid in %q#T", using_decl, t); ! cp_error_at (" because of local member %q#D with same name", old_value); return; } *************** handle_using_decl (tree using_decl, tree *** 1088,1157 **** if (flist) for (; flist; flist = OVL_NEXT (flist)) { ! add_method (t, OVL_CURRENT (flist), /*error_p=*/0); alter_access (t, OVL_CURRENT (flist), access); } else alter_access (t, fdecl, access); } ! /* Run through the base clases of T, updating ! CANT_HAVE_DEFAULT_CTOR_P, CANT_HAVE_CONST_CTOR_P, and ! NO_CONST_ASN_REF_P. Also set flag bits in T based on properties of ! the bases. */ static void check_bases (tree t, - int* cant_have_default_ctor_p, int* cant_have_const_ctor_p, int* no_const_asn_ref_p) { - int n_baseclasses; int i; int seen_non_virtual_nearly_empty_base_p; ! tree binfos; - binfos = TYPE_BINFO_BASETYPES (t); - n_baseclasses = CLASSTYPE_N_BASECLASSES (t); seen_non_virtual_nearly_empty_base_p = 0; ! /* An aggregate cannot have baseclasses. */ ! CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0); ! ! for (i = 0; i < n_baseclasses; ++i) { ! tree base_binfo; ! tree basetype; ! ! /* Figure out what base we're looking at. */ ! base_binfo = TREE_VEC_ELT (binfos, i); ! basetype = TREE_TYPE (base_binfo); ! ! /* If the type of basetype is incomplete, then we already ! complained about that fact (and we should have fixed it up as ! well). */ ! if (!COMPLETE_TYPE_P (basetype)) ! { ! int j; ! /* The base type is of incomplete type. It is ! probably best to pretend that it does not ! exist. */ ! if (i == n_baseclasses-1) ! TREE_VEC_ELT (binfos, i) = NULL_TREE; ! TREE_VEC_LENGTH (binfos) -= 1; ! n_baseclasses -= 1; ! for (j = i; j+1 < n_baseclasses; j++) ! TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); ! continue; ! } /* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P here because the case of virtual functions but non-virtual dtor is handled in finish_struct_1. */ ! if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype) ! && TYPE_HAS_DESTRUCTOR (basetype)) ! warning ("base class `%#T' has a non-virtual destructor", ! basetype); /* If the base class doesn't have copy constructors or assignment operators that take const references, then the --- 1200,1240 ---- if (flist) for (; flist; flist = OVL_NEXT (flist)) { ! add_method (t, OVL_CURRENT (flist)); alter_access (t, OVL_CURRENT (flist), access); } else alter_access (t, fdecl, access); } ! /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P, ! and NO_CONST_ASN_REF_P. Also set flag bits in T based on ! properties of the bases. */ static void check_bases (tree t, int* cant_have_const_ctor_p, int* no_const_asn_ref_p) { int i; int seen_non_virtual_nearly_empty_base_p; ! tree base_binfo; ! tree binfo; seen_non_virtual_nearly_empty_base_p = 0; ! for (binfo = TYPE_BINFO (t), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { ! tree basetype = TREE_TYPE (base_binfo); + gcc_assert (COMPLETE_TYPE_P (basetype)); + /* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P here because the case of virtual functions but non-virtual dtor is handled in finish_struct_1. */ ! if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype)) ! warning ("base class %q#T has a non-virtual destructor", basetype); /* If the base class doesn't have copy constructors or assignment operators that take const references, then the *************** check_bases (tree t, *** 1162,1180 **** if (TYPE_HAS_ASSIGN_REF (basetype) && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) *no_const_asn_ref_p = 1; - /* Similarly, if the base class doesn't have a default - constructor, then the derived class won't have an - automatically generated default constructor. */ - if (TYPE_HAS_CONSTRUCTOR (basetype) - && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) - { - *cant_have_default_ctor_p = 1; - if (! TYPE_HAS_CONSTRUCTOR (t)) - pedwarn ("base `%T' with only non-default constructor in class without a constructor", - basetype); - } ! if (TREE_VIA_VIRTUAL (base_binfo)) /* A virtual base does not effect nearly emptiness. */ ; else if (CLASSTYPE_NEARLY_EMPTY_P (basetype)) --- 1245,1252 ---- if (TYPE_HAS_ASSIGN_REF (basetype) && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) *no_const_asn_ref_p = 1; ! if (BINFO_VIRTUAL_P (base_binfo)) /* A virtual base does not effect nearly emptiness. */ ; else if (CLASSTYPE_NEARLY_EMPTY_P (basetype)) *************** check_bases (tree t, *** 1206,1400 **** } } ! /* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy ! dominated by TYPE that are primary bases. */ static void ! mark_primary_bases (tree type) { ! tree binfo; ! ! /* Walk the bases in inheritance graph order. */ ! for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo)) { ! tree base_binfo = get_primary_binfo (binfo); ! if (!base_binfo) ! /* Not a dynamic base. */; ! else if (BINFO_PRIMARY_P (base_binfo)) ! BINFO_LOST_PRIMARY_P (binfo) = 1; ! else { ! BINFO_PRIMARY_BASE_OF (base_binfo) = binfo; ! /* A virtual binfo might have been copied from within ! another hierarchy. As we're about to use it as a primary ! base, make sure the offsets match. */ ! if (TREE_VIA_VIRTUAL (base_binfo)) ! { ! tree delta = size_diffop (convert (ssizetype, ! BINFO_OFFSET (binfo)), ! convert (ssizetype, ! BINFO_OFFSET (base_binfo))); ! propagate_binfo_offsets (base_binfo, delta); ! } } ! } ! } ! ! /* Make the BINFO the primary base of T. */ ! ! static void ! set_primary_base (tree t, tree binfo) ! { ! tree basetype; ! ! CLASSTYPE_PRIMARY_BINFO (t) = binfo; ! basetype = BINFO_TYPE (binfo); ! TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); ! TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); ! TYPE_VFIELD (t) = TYPE_VFIELD (basetype); ! } ! ! /* Determine the primary class for T. */ ! ! static void ! determine_primary_base (tree t) ! { ! int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); ! tree vbases; ! tree type_binfo; ! ! /* If there are no baseclasses, there is certainly no primary base. */ ! if (n_baseclasses == 0) ! return; ! ! type_binfo = TYPE_BINFO (t); ! ! for (i = 0; i < n_baseclasses; i++) ! { ! tree base_binfo = BINFO_BASETYPE (type_binfo, i); ! tree basetype = BINFO_TYPE (base_binfo); ! ! if (TYPE_CONTAINS_VPTR_P (basetype)) { ! /* We prefer a non-virtual base, although a virtual one will ! do. */ ! if (TREE_VIA_VIRTUAL (base_binfo)) ! continue; ! if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) ! { ! set_primary_base (t, base_binfo); ! CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype)); ! } else { ! tree vfields; ! ! /* Only add unique vfields, and flatten them out as we go. */ ! for (vfields = CLASSTYPE_VFIELDS (basetype); ! vfields; ! vfields = TREE_CHAIN (vfields)) ! if (VF_BINFO_VALUE (vfields) == NULL_TREE ! || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))) ! CLASSTYPE_VFIELDS (t) ! = tree_cons (base_binfo, ! VF_BASETYPE_VALUE (vfields), ! CLASSTYPE_VFIELDS (t)); } } } ! if (!TYPE_VFIELD (t)) ! CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE; ! ! /* Find the indirect primary bases - those virtual bases which are primary ! bases of something else in this hierarchy. */ ! for (vbases = CLASSTYPE_VBASECLASSES (t); ! vbases; ! vbases = TREE_CHAIN (vbases)) { ! tree vbase_binfo = TREE_VALUE (vbases); ! /* See if this virtual base is an indirect primary base. To be so, ! it must be a primary base within the hierarchy of one of our ! direct bases. */ ! for (i = 0; i < n_baseclasses; ++i) { ! tree basetype = TYPE_BINFO_BASETYPE (t, i); ! tree v; ! ! for (v = CLASSTYPE_VBASECLASSES (basetype); ! v; ! v = TREE_CHAIN (v)) ! { ! tree base_vbase = TREE_VALUE (v); ! ! if (BINFO_PRIMARY_P (base_vbase) ! && same_type_p (BINFO_TYPE (base_vbase), ! BINFO_TYPE (vbase_binfo))) ! { ! BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1; ! break; ! } ! } ! ! /* If we've discovered that this virtual base is an indirect ! primary base, then we can move on to the next virtual ! base. */ ! if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo)) ! break; } } /* A "nearly-empty" virtual base class can be the primary base ! class, if no non-virtual polymorphic base can be found. */ ! if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) ! { ! /* If not NULL, this is the best primary base candidate we have ! found so far. */ ! tree candidate = NULL_TREE; ! tree base_binfo; ! /* Loop over the baseclasses. */ ! for (base_binfo = TYPE_BINFO (t); ! base_binfo; ! base_binfo = TREE_CHAIN (base_binfo)) { ! tree basetype = BINFO_TYPE (base_binfo); ! ! if (TREE_VIA_VIRTUAL (base_binfo) ! && CLASSTYPE_NEARLY_EMPTY_P (basetype)) ! { ! /* If this is not an indirect primary base, then it's ! definitely our primary base. */ ! if (!BINFO_INDIRECT_PRIMARY_P (base_binfo)) ! { ! candidate = base_binfo; ! break; ! } ! /* If this is an indirect primary base, it still could be ! our primary base -- unless we later find there's another ! nearly-empty virtual base that isn't an indirect ! primary base. */ ! if (!candidate) ! candidate = base_binfo; ! } } ! ! /* If we've got a primary base, use it. */ ! if (candidate) ! { ! set_primary_base (t, candidate); ! CLASSTYPE_VFIELDS (t) ! = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate))); ! } } - - /* Mark the primary base classes at this point. */ - mark_primary_bases (t); } /* Set memoizing fields and bits of T (and its variants) for later --- 1278,1410 ---- } } ! /* Determine all the primary bases within T. Sets BINFO_PRIMARY_BASE_P for ! those that are primaries. Sets BINFO_LOST_PRIMARY_P for those ! that have had a nearly-empty virtual primary base stolen by some ! other base in the hierarchy. Determines CLASSTYPE_PRIMARY_BASE for ! T. */ static void ! determine_primary_bases (tree t) { ! unsigned i; ! tree primary = NULL_TREE; ! tree type_binfo = TYPE_BINFO (t); ! tree base_binfo; ! ! /* Determine the primary bases of our bases. */ ! for (base_binfo = TREE_CHAIN (type_binfo); base_binfo; ! base_binfo = TREE_CHAIN (base_binfo)) { ! tree primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (base_binfo)); ! /* See if we're the non-virtual primary of our inheritance ! chain. */ ! if (!BINFO_VIRTUAL_P (base_binfo)) { ! tree parent = BINFO_INHERITANCE_CHAIN (base_binfo); ! tree parent_primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (parent)); ! if (parent_primary ! && SAME_BINFO_TYPE_P (BINFO_TYPE (base_binfo), ! BINFO_TYPE (parent_primary))) ! /* We are the primary binfo. */ ! BINFO_PRIMARY_P (base_binfo) = 1; } ! /* Determine if we have a virtual primary base, and mark it so. ! */ ! if (primary && BINFO_VIRTUAL_P (primary)) { ! tree this_primary = copied_binfo (primary, base_binfo); ! if (BINFO_PRIMARY_P (this_primary)) ! /* Someone already claimed this base. */ ! BINFO_LOST_PRIMARY_P (base_binfo) = 1; else { ! tree delta; ! ! BINFO_PRIMARY_P (this_primary) = 1; ! BINFO_INHERITANCE_CHAIN (this_primary) = base_binfo; ! ! /* A virtual binfo might have been copied from within ! another hierarchy. As we're about to use it as a ! primary base, make sure the offsets match. */ ! delta = size_diffop (convert (ssizetype, ! BINFO_OFFSET (base_binfo)), ! convert (ssizetype, ! BINFO_OFFSET (this_primary))); ! ! propagate_binfo_offsets (this_primary, delta); } } } ! /* First look for a dynamic direct non-virtual base. */ ! for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, base_binfo); i++) { ! tree basetype = BINFO_TYPE (base_binfo); ! if (TYPE_CONTAINS_VPTR_P (basetype) && !BINFO_VIRTUAL_P (base_binfo)) { ! primary = base_binfo; ! goto found; } } /* A "nearly-empty" virtual base class can be the primary base ! class, if no non-virtual polymorphic base can be found. Look for ! a nearly-empty virtual dynamic base that is not already a primary ! base of something in the hierarchy. If there is no such base, ! just pick the first nearly-empty virtual base. */ ! for (base_binfo = TREE_CHAIN (type_binfo); base_binfo; ! base_binfo = TREE_CHAIN (base_binfo)) ! if (BINFO_VIRTUAL_P (base_binfo) ! && CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (base_binfo))) ! { ! if (!BINFO_PRIMARY_P (base_binfo)) ! { ! /* Found one that is not primary. */ ! primary = base_binfo; ! goto found; ! } ! else if (!primary) ! /* Remember the first candidate. */ ! primary = base_binfo; ! } ! ! found: ! /* If we've got a primary base, use it. */ ! if (primary) ! { ! tree basetype = BINFO_TYPE (primary); ! ! CLASSTYPE_PRIMARY_BINFO (t) = primary; ! if (BINFO_PRIMARY_P (primary)) ! /* We are stealing a primary base. */ ! BINFO_LOST_PRIMARY_P (BINFO_INHERITANCE_CHAIN (primary)) = 1; ! BINFO_PRIMARY_P (primary) = 1; ! if (BINFO_VIRTUAL_P (primary)) { ! tree delta; ! BINFO_INHERITANCE_CHAIN (primary) = type_binfo; ! /* A virtual binfo might have been copied from within ! another hierarchy. As we're about to use it as a primary ! base, make sure the offsets match. */ ! delta = size_diffop (ssize_int (0), ! convert (ssizetype, BINFO_OFFSET (primary))); ! ! propagate_binfo_offsets (primary, delta); } ! ! primary = TYPE_BINFO (basetype); ! ! TYPE_VFIELD (t) = TYPE_VFIELD (basetype); ! BINFO_VTABLE (type_binfo) = BINFO_VTABLE (primary); ! BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary); } } /* Set memoizing fields and bits of T (and its variants) for later *************** determine_primary_base (tree t) *** 1403,1465 **** static void finish_struct_bits (tree t) { ! int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); ! /* Fix up variants (if any). */ ! tree variants = TYPE_NEXT_VARIANT (t); ! while (variants) { /* These fields are in the _TYPE part of the node, not in the TYPE_LANG_SPECIFIC component, so they are not shared. */ TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t); - TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t); TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants) = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t); - TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants) - = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t); TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t); ! TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t); /* Copy whatever these are holding today. */ ! TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); ! TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); TYPE_FIELDS (variants) = TYPE_FIELDS (t); TYPE_SIZE (variants) = TYPE_SIZE (t); TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); - variants = TYPE_NEXT_VARIANT (variants); } ! if (n_baseclasses && TYPE_POLYMORPHIC_P (t)) ! /* For a class w/o baseclasses, `finish_struct' has set ! CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by ! definition). Similarly for a class whose base classes do not ! have vtables. When neither of these is true, we might have ! removed abstract virtuals (by providing a definition), added ! some (by declaring new ones), or redeclared ones from a base ! class. We need to recalculate what's really an abstract virtual ! at this point (by looking in the vtables). */ ! get_pure_virtuals (t); ! ! if (n_baseclasses) ! { ! /* Notice whether this class has type conversion functions defined. */ ! tree binfo = TYPE_BINFO (t); ! tree binfos = BINFO_BASETYPES (binfo); ! tree basetype; ! ! for (i = n_baseclasses-1; i >= 0; i--) ! { ! basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); ! ! TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype); ! } ! } ! ! /* If this type has a copy constructor or a destructor, force its mode to ! be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. This ! will cause it to be passed by invisible reference and prevent it from ! being returned in a register. */ if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) { tree variants; --- 1413,1459 ---- static void finish_struct_bits (tree t) { ! tree variants; ! /* Fix up variants (if any). */ ! for (variants = TYPE_NEXT_VARIANT (t); ! variants; ! variants = TYPE_NEXT_VARIANT (variants)) { /* These fields are in the _TYPE part of the node, not in the TYPE_LANG_SPECIFIC component, so they are not shared. */ TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t); TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t); TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants) = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t); TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t); ! ! TYPE_BINFO (variants) = TYPE_BINFO (t); ! /* Copy whatever these are holding today. */ ! TYPE_VFIELD (variants) = TYPE_VFIELD (t); ! TYPE_METHODS (variants) = TYPE_METHODS (t); TYPE_FIELDS (variants) = TYPE_FIELDS (t); TYPE_SIZE (variants) = TYPE_SIZE (t); TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); } ! if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t)) ! /* For a class w/o baseclasses, 'finish_struct' has set ! CLASSTYPE_PURE_VIRTUALS correctly (by definition). ! Similarly for a class whose base classes do not have vtables. ! When neither of these is true, we might have removed abstract ! virtuals (by providing a definition), added some (by declaring ! new ones), or redeclared ones from a base class. We need to ! recalculate what's really an abstract virtual at this point (by ! looking in the vtables). */ ! get_pure_virtuals (t); ! ! /* If this type has a copy constructor or a destructor, force its ! mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be ! nonzero. This will cause it to be passed by invisible reference ! and prevent it from being returned in a register. */ if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) { tree variants; *************** maybe_warn_about_overly_private_class (t *** 1543,1560 **** constructors/destructors we want to use the code below that issues error messages specifically referring to constructors/destructors.) */ ! int i; tree binfo = TYPE_BINFO (t); ! for (i = 0; i < BINFO_N_BASETYPES (binfo); i++) ! if (BINFO_BASEACCESS (binfo, i) != access_private_node) { has_nonprivate_method = 1; break; } if (!has_nonprivate_method) { ! warning ("all member functions in class `%T' are private", t); return; } } --- 1537,1554 ---- constructors/destructors we want to use the code below that issues error messages specifically referring to constructors/destructors.) */ ! unsigned i; tree binfo = TYPE_BINFO (t); ! for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++) ! if (BINFO_BASE_ACCESS (binfo, i) != access_private_node) { has_nonprivate_method = 1; break; } if (!has_nonprivate_method) { ! warning ("all member functions in class %qT are private", t); return; } } *************** maybe_warn_about_overly_private_class (t *** 1562,1571 **** /* Even if some of the member functions are non-private, the class won't be useful for much if all the constructors or destructors are private: such an object can never be created or destroyed. */ ! if (TYPE_HAS_DESTRUCTOR (t) ! && TREE_PRIVATE (CLASSTYPE_DESTRUCTORS (t))) { ! warning ("`%#T' only defines a private destructor and has no friends", t); return; } --- 1556,1565 ---- /* Even if some of the member functions are non-private, the class won't be useful for much if all the constructors or destructors are private: such an object can never be created or destroyed. */ ! fn = CLASSTYPE_DESTRUCTORS (t); ! if (fn && TREE_PRIVATE (fn)) { ! warning ("%q#T only defines a private destructor and has no friends", t); return; } *************** maybe_warn_about_overly_private_class (t *** 1587,1595 **** if (!TYPE_HAS_INIT_REF (t)) nonprivate_ctor = 1; else ! for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); ! fn; ! fn = OVL_NEXT (fn)) { tree ctor = OVL_CURRENT (fn); /* Ideally, we wouldn't count copy constructors (or, in --- 1581,1587 ---- if (!TYPE_HAS_INIT_REF (t)) nonprivate_ctor = 1; else ! for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn)) { tree ctor = OVL_CURRENT (fn); /* Ideally, we wouldn't count copy constructors (or, in *************** maybe_warn_about_overly_private_class (t *** 1607,1614 **** if (nonprivate_ctor == 0) { ! warning ("`%#T' only defines private constructors and has no friends", ! t); return; } } --- 1599,1606 ---- if (nonprivate_ctor == 0) { ! warning ("%q#T only defines private constructors and has no friends", ! t); return; } } *************** resort_type_method_vec (void* obj, *** 1671,1709 **** gt_pointer_operator new_value, void* cookie) { ! tree method_vec = obj; ! int len = TREE_VEC_LENGTH (method_vec); ! int slot; /* The type conversion ops have to live at the front of the vec, so we can't sort them. */ ! for (slot = 2; slot < len; ++slot) ! { ! tree fn = TREE_VEC_ELT (method_vec, slot); ! ! if (!DECL_CONV_FN_P (OVL_CURRENT (fn))) ! break; ! } if (len - slot > 1) { resort_data.new_value = new_value; resort_data.cookie = cookie; ! qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree), resort_method_name_cmp); } } ! /* Warn about duplicate methods in fn_fields. Also compact method ! lists so that lookup can be made faster. ! ! Data Structure: List of method lists. The outer list is a ! TREE_LIST, whose TREE_PURPOSE field is the field name and the ! TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN ! links the entire list of methods for TYPE_METHODS. Friends are ! chained in the same way as member functions (? TREE_CHAIN or ! DECL_CHAIN), but they live in the TREE_TYPE field of the outer ! list. That allows them to be quickly deleted, and requires no ! extra storage. Sort methods that are not special (i.e., constructors, destructors, and type conversion operators) so that we can find them faster in --- 1663,1691 ---- gt_pointer_operator new_value, void* cookie) { ! VEC(tree) *method_vec = (VEC(tree) *) obj; ! int len = VEC_length (tree, method_vec); ! size_t slot; ! tree fn; /* The type conversion ops have to live at the front of the vec, so we can't sort them. */ ! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; ! VEC_iterate (tree, method_vec, slot, fn); ! ++slot) ! if (!DECL_CONV_FN_P (OVL_CURRENT (fn))) ! break; ! if (len - slot > 1) { resort_data.new_value = new_value; resort_data.cookie = cookie; ! qsort (VEC_address (tree, method_vec) + slot, len - slot, sizeof (tree), resort_method_name_cmp); } } ! /* Warn about duplicate methods in fn_fields. Sort methods that are not special (i.e., constructors, destructors, and type conversion operators) so that we can find them faster in *************** static void *** 1713,1768 **** finish_struct_methods (tree t) { tree fn_fields; ! tree method_vec; int slot, len; - if (!TYPE_METHODS (t)) - { - /* Clear these for safety; perhaps some parsing error could set - these incorrectly. */ - TYPE_HAS_CONSTRUCTOR (t) = 0; - TYPE_HAS_DESTRUCTOR (t) = 0; - CLASSTYPE_METHOD_VEC (t) = NULL_TREE; - return; - } - method_vec = CLASSTYPE_METHOD_VEC (t); ! my_friendly_assert (method_vec != NULL_TREE, 19991215); ! len = TREE_VEC_LENGTH (method_vec); ! /* First fill in entry 0 with the constructors, entry 1 with destructors, ! and the next few with type conversion operators (if any). */ for (fn_fields = TYPE_METHODS (t); fn_fields; fn_fields = TREE_CHAIN (fn_fields)) - /* Clear out this flag. */ DECL_IN_AGGR_P (fn_fields) = 0; - if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t)) - /* We thought there was a destructor, but there wasn't. Some - parse errors cause this anomalous situation. */ - TYPE_HAS_DESTRUCTOR (t) = 0; - /* Issue warnings about private constructors and such. If there are no methods, then some public defaults are generated. */ maybe_warn_about_overly_private_class (t); - /* Now sort the methods. */ - while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE) - len--; - TREE_VEC_LENGTH (method_vec) = len; - /* The type conversion ops have to live at the front of the vec, so we can't sort them. */ ! for (slot = 2; slot < len; ++slot) ! { ! tree fn = TREE_VEC_ELT (method_vec, slot); ! ! if (!DECL_CONV_FN_P (OVL_CURRENT (fn))) ! break; ! } if (len - slot > 1) ! qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree), ! method_name_cmp); } /* Make BINFO's vtable have N entries, including RTTI entries, --- 1695,1728 ---- finish_struct_methods (tree t) { tree fn_fields; ! VEC(tree) *method_vec; int slot, len; method_vec = CLASSTYPE_METHOD_VEC (t); ! if (!method_vec) ! return; ! len = VEC_length (tree, method_vec); ! ! /* Clear DECL_IN_AGGR_P for all functions. */ for (fn_fields = TYPE_METHODS (t); fn_fields; fn_fields = TREE_CHAIN (fn_fields)) DECL_IN_AGGR_P (fn_fields) = 0; /* Issue warnings about private constructors and such. If there are no methods, then some public defaults are generated. */ maybe_warn_about_overly_private_class (t); /* The type conversion ops have to live at the front of the vec, so we can't sort them. */ ! for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; ! VEC_iterate (tree, method_vec, slot, fn_fields); ! ++slot) ! if (!DECL_CONV_FN_P (OVL_CURRENT (fn_fields))) ! break; if (len - slot > 1) ! qsort (VEC_address (tree, method_vec) + slot, ! len-slot, sizeof (tree), method_name_cmp); } /* Make BINFO's vtable have N entries, including RTTI entries, *************** base_derived_from (tree derived, tree ba *** 1836,1896 **** { if (probe == derived) return true; ! else if (TREE_VIA_VIRTUAL (probe)) /* If we meet a virtual base, we can't follow the inheritance any more. See if the complete type of DERIVED contains such a virtual base. */ ! return purpose_member (BINFO_TYPE (probe), ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (derived))) ! != NULL_TREE; } return false; } - typedef struct count_depth_data { - /* The depth of the current subobject, with "1" as the depth of the - most derived object in the hierarchy. */ - size_t depth; - /* The maximum depth found so far. */ - size_t max_depth; - } count_depth_data; - - /* Called from find_final_overrider via dfs_walk. */ - - static tree - dfs_depth_post (tree binfo ATTRIBUTE_UNUSED, void *data) - { - count_depth_data *cd = (count_depth_data *) data; - if (cd->depth > cd->max_depth) - cd->max_depth = cd->depth; - cd->depth--; - return NULL_TREE; - } - - /* Called from find_final_overrider via dfs_walk. */ - - static tree - dfs_depth_q (tree derived, int i, void *data) - { - count_depth_data *cd = (count_depth_data *) data; - cd->depth++; - return BINFO_BASETYPE (derived, i); - } - typedef struct find_final_overrider_data_s { /* The function for which we are trying to find a final overrider. */ tree fn; /* The base class in which the function was declared. */ tree declaring_base; - /* The most derived class in the hierarchy. */ - tree most_derived_type; /* The candidate overriders. */ tree candidates; ! /* Each entry in this array is the next-most-derived class for a ! virtual base class along the current path. */ ! tree *vpath_list; ! /* A pointer one past the top of the VPATH_LIST. */ ! tree *vpath; } find_final_overrider_data; /* Add the overrider along the current path to FFOD->CANDIDATES. --- 1796,1820 ---- { if (probe == derived) return true; ! else if (BINFO_VIRTUAL_P (probe)) /* If we meet a virtual base, we can't follow the inheritance any more. See if the complete type of DERIVED contains such a virtual base. */ ! return (binfo_for_vbase (BINFO_TYPE (probe), BINFO_TYPE (derived)) ! != NULL_TREE); } return false; } typedef struct find_final_overrider_data_s { /* The function for which we are trying to find a final overrider. */ tree fn; /* The base class in which the function was declared. */ tree declaring_base; /* The candidate overriders. */ tree candidates; ! /* Path to most derived. */ ! VEC (tree) *path; } find_final_overrider_data; /* Add the overrider along the current path to FFOD->CANDIDATES. *************** typedef struct find_final_overrider_data *** 1898,1919 **** static bool dfs_find_final_overrider_1 (tree binfo, ! tree *vpath, ! find_final_overrider_data *ffod) { tree method; ! /* If BINFO is not the most derived type, try a more derived class. A definition there will overrider a definition here. */ ! if (!same_type_p (BINFO_TYPE (binfo), ffod->most_derived_type)) { ! tree derived; ! ! if (TREE_VIA_VIRTUAL (binfo)) ! derived = *--vpath; ! else ! derived = BINFO_INHERITANCE_CHAIN (binfo); ! if (dfs_find_final_overrider_1 (derived, vpath, ffod)) return true; } --- 1822,1839 ---- static bool dfs_find_final_overrider_1 (tree binfo, ! find_final_overrider_data *ffod, ! unsigned depth) { tree method; ! /* If BINFO is not the most derived type, try a more derived class. A definition there will overrider a definition here. */ ! if (depth) { ! depth--; ! if (dfs_find_final_overrider_1 ! (VEC_index (tree, ffod->path, depth), ffod, depth)) return true; } *************** dfs_find_final_overrider_1 (tree binfo, *** 1947,1982 **** /* Called from find_final_overrider via dfs_walk. */ static tree ! dfs_find_final_overrider (tree binfo, void* data) { find_final_overrider_data *ffod = (find_final_overrider_data *) data; if (binfo == ffod->declaring_base) ! dfs_find_final_overrider_1 (binfo, ffod->vpath, ffod); return NULL_TREE; } static tree ! dfs_find_final_overrider_q (tree derived, int ix, void *data) ! { ! tree binfo = BINFO_BASETYPE (derived, ix); ! find_final_overrider_data *ffod = (find_final_overrider_data *) data; ! ! if (TREE_VIA_VIRTUAL (binfo)) ! *ffod->vpath++ = derived; ! ! return binfo; ! } ! ! static tree ! dfs_find_final_overrider_post (tree binfo, void *data) { find_final_overrider_data *ffod = (find_final_overrider_data *) data; - if (TREE_VIA_VIRTUAL (binfo)) - ffod->vpath--; - return NULL_TREE; } --- 1867,1889 ---- /* Called from find_final_overrider via dfs_walk. */ static tree ! dfs_find_final_overrider_pre (tree binfo, void *data) { find_final_overrider_data *ffod = (find_final_overrider_data *) data; if (binfo == ffod->declaring_base) ! dfs_find_final_overrider_1 (binfo, ffod, VEC_length (tree, ffod->path)); ! VEC_safe_push (tree, ffod->path, binfo); return NULL_TREE; } static tree ! dfs_find_final_overrider_post (tree binfo ATTRIBUTE_UNUSED, void *data) { find_final_overrider_data *ffod = (find_final_overrider_data *) data; + VEC_pop (tree, ffod->path); return NULL_TREE; } *************** static tree *** 1989,1995 **** find_final_overrider (tree derived, tree binfo, tree fn) { find_final_overrider_data ffod; - count_depth_data cd; /* Getting this right is a little tricky. This is valid: --- 1896,1901 ---- *************** find_final_overrider (tree derived, tree *** 2013,2041 **** fn = THUNK_TARGET (fn); /* Determine the depth of the hierarchy. */ - cd.depth = 0; - cd.max_depth = 0; - dfs_walk (derived, dfs_depth_post, dfs_depth_q, &cd); - ffod.fn = fn; ffod.declaring_base = binfo; - ffod.most_derived_type = BINFO_TYPE (derived); ffod.candidates = NULL_TREE; ! ffod.vpath_list = (tree *) xcalloc (cd.max_depth, sizeof (tree)); ! ffod.vpath = ffod.vpath_list; ! ! dfs_walk_real (derived, ! dfs_find_final_overrider, ! dfs_find_final_overrider_post, ! dfs_find_final_overrider_q, ! &ffod); ! free (ffod.vpath_list); /* If there was no winner, issue an error message. */ if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) { ! error ("no unique final overrider for `%D' in `%T'", fn, BINFO_TYPE (derived)); return error_mark_node; } --- 1919,1938 ---- fn = THUNK_TARGET (fn); /* Determine the depth of the hierarchy. */ ffod.fn = fn; ffod.declaring_base = binfo; ffod.candidates = NULL_TREE; ! ffod.path = VEC_alloc (tree, 30); ! dfs_walk_all (derived, dfs_find_final_overrider_pre, ! dfs_find_final_overrider_post, &ffod); + VEC_free (tree, ffod.path); + /* If there was no winner, issue an error message. */ if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) { ! error ("no unique final overrider for %qD in %qT", fn, BINFO_TYPE (derived)); return error_mark_node; } *************** find_final_overrider (tree derived, tree *** 2049,2065 **** static tree get_vcall_index (tree fn, tree type) { ! tree v; ! 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 --- 1946,1962 ---- static tree get_vcall_index (tree fn, tree type) { ! VEC (tree_pair_s) *indices = CLASSTYPE_VCALL_INDICES (type); ! tree_pair_p p; ! unsigned ix; ! for (ix = 0; VEC_iterate (tree_pair_s, indices, ix, p); ix++) ! if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (p->purpose)) ! || same_signature_p (fn, p->purpose)) ! return p->value; /* There should always be an appropriate index. */ ! gcc_unreachable (); } /* Update an entry in the vtable for BINFO, which is in the hierarchy *************** update_vtable_entry_for_fn (tree t, tree *** 2085,2091 **** calling FN through BINFO. */ for (b = binfo; ; b = get_primary_binfo (b)) { ! my_friendly_assert (b, 20021227); if (look_for_overrides_here (BINFO_TYPE (b), target_fn)) break; --- 1982,1988 ---- calling FN through BINFO. */ for (b = binfo; ; b = get_primary_binfo (b)) { ! gcc_assert (b); if (look_for_overrides_here (BINFO_TYPE (b), target_fn)) break; *************** update_vtable_entry_for_fn (tree t, tree *** 2115,2124 **** also be converting to the return type of FN, we have to combine the two conversions here. */ tree fixed_offset, virtual_offset; if (DECL_THUNK_P (fn)) { ! my_friendly_assert (DECL_RESULT_THUNK_P (fn), 20031211); fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn)); virtual_offset = THUNK_VIRTUAL_OFFSET (fn); } --- 2012,2024 ---- also be converting to the return type of FN, we have to combine the two conversions here. */ tree fixed_offset, virtual_offset; + + over_return = TREE_TYPE (over_return); + base_return = TREE_TYPE (base_return); if (DECL_THUNK_P (fn)) { ! gcc_assert (DECL_RESULT_THUNK_P (fn)); fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn)); virtual_offset = THUNK_VIRTUAL_OFFSET (fn); } *************** update_vtable_entry_for_fn (tree t, tree *** 2129,2163 **** /* Find the equivalent binfo within the return type of the overriding function. We will want the vbase offset from there. */ ! virtual_offset = ! TREE_VALUE (purpose_member ! (BINFO_TYPE (virtual_offset), ! CLASSTYPE_VBASECLASSES (TREE_TYPE (over_return)))); ! else if (!same_type_p (TREE_TYPE (over_return), ! TREE_TYPE (base_return))) { /* There was no existing virtual thunk (which takes ! precedence). */ ! tree thunk_binfo; ! base_kind kind; ! ! thunk_binfo = lookup_base (TREE_TYPE (over_return), ! TREE_TYPE (base_return), ! ba_check | ba_quiet, &kind); ! if (thunk_binfo && (kind == bk_via_virtual ! || !BINFO_OFFSET_ZEROP (thunk_binfo))) { tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo)); ! if (kind == bk_via_virtual) { ! /* We convert via virtual base. Find the virtual ! base and adjust the fixed offset to be from there. */ ! while (!TREE_VIA_VIRTUAL (thunk_binfo)) ! thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo); ! ! virtual_offset = thunk_binfo; offset = size_diffop (offset, convert (ssizetype, BINFO_OFFSET (virtual_offset))); --- 2029,2080 ---- /* Find the equivalent binfo within the return type of the overriding function. We will want the vbase offset from there. */ ! virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset), ! over_return); ! else if (!same_type_ignoring_top_level_qualifiers_p ! (over_return, base_return)) { /* There was no existing virtual thunk (which takes ! precedence). So find the binfo of the base function's ! return type within the overriding function's return type. ! We cannot call lookup base here, because we're inside a ! dfs_walk, and will therefore clobber the BINFO_MARKED ! flags. Fortunately we know the covariancy is valid (it ! has already been checked), so we can just iterate along ! the binfos, which have been chained in inheritance graph ! order. Of course it is lame that we have to repeat the ! search here anyway -- we should really be caching pieces ! of the vtable and avoiding this repeated work. */ ! tree thunk_binfo, base_binfo; ! /* Find the base binfo within the overriding function's ! return type. We will always find a thunk_binfo, except ! when the covariancy is invalid (which we will have ! already diagnosed). */ ! for (base_binfo = TYPE_BINFO (base_return), ! thunk_binfo = TYPE_BINFO (over_return); ! thunk_binfo; ! thunk_binfo = TREE_CHAIN (thunk_binfo)) ! if (SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo), ! BINFO_TYPE (base_binfo))) ! break; ! ! /* See if virtual inheritance is involved. */ ! for (virtual_offset = thunk_binfo; ! virtual_offset; ! virtual_offset = BINFO_INHERITANCE_CHAIN (virtual_offset)) ! if (BINFO_VIRTUAL_P (virtual_offset)) ! break; ! ! if (virtual_offset ! || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo))) { tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo)); ! if (virtual_offset) { ! /* We convert via virtual base. Adjust the fixed ! offset to be from there. */ offset = size_diffop (offset, convert (ssizetype, BINFO_OFFSET (virtual_offset))); *************** update_vtable_entry_for_fn (tree t, tree *** 2180,2186 **** fixed_offset, virtual_offset); } else ! my_friendly_assert (!DECL_THUNK_P (fn), 20021231); /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ --- 2097,2103 ---- fixed_offset, virtual_offset); } else ! gcc_assert (!DECL_THUNK_P (fn)); /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ *************** update_vtable_entry_for_fn (tree t, tree *** 2192,2205 **** { /* If we find the final overrider, then we can stop walking. */ ! if (same_type_p (BINFO_TYPE (b), ! BINFO_TYPE (TREE_VALUE (overrider)))) break; /* If we find a virtual base, and we haven't yet found the overrider, then there is a virtual base between the declaring base (first_defn) and the final overrider. */ ! if (TREE_VIA_VIRTUAL (b)) { virtual_base = b; break; --- 2109,2122 ---- { /* If we find the final overrider, then we can stop walking. */ ! if (SAME_BINFO_TYPE_P (BINFO_TYPE (b), ! BINFO_TYPE (TREE_VALUE (overrider)))) break; /* If we find a virtual base, and we haven't yet found the overrider, then there is a virtual base between the declaring base (first_defn) and the final overrider. */ ! if (BINFO_VIRTUAL_P (b)) { virtual_base = b; break; *************** update_vtable_entry_for_fn (tree t, tree *** 2226,2232 **** while ((probe = get_primary_binfo (probe)) && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix) ! if (TREE_VIA_VIRTUAL (probe)) virtual_base = probe; if (virtual_base) --- 2143,2149 ---- while ((probe = get_primary_binfo (probe)) && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix) ! if (BINFO_VIRTUAL_P (probe)) virtual_base = probe; if (virtual_base) *************** update_vtable_entry_for_fn (tree t, tree *** 2264,2269 **** --- 2181,2188 ---- if (virtual_base) BV_VCALL_INDEX (*virtuals) = get_vcall_index (overrider_target, BINFO_TYPE (virtual_base)); + else + BV_VCALL_INDEX (*virtuals) = NULL_TREE; } /* Called from modify_all_vtables via dfs_walk. */ *************** update_vtable_entry_for_fn (tree t, tree *** 2271,2306 **** static tree dfs_modify_vtables (tree binfo, void* data) { ! if (/* There's no need to modify the vtable for a non-virtual ! primary base; we're not going to use that vtable anyhow. ! We do still need to do this for virtual primary bases, as they ! could become non-primary in a construction vtable. */ ! (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) ! /* Similarly, a base without a vtable needs no modification. */ ! && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) ! { ! tree t = (tree) data; ! tree virtuals; ! tree old_virtuals; ! unsigned ix; ! ! make_new_vtable (t, binfo); ! ! /* Now, go through each of the virtual functions in the virtual ! function table for BINFO. Find the final overrider, and ! update the BINFO_VIRTUALS list appropriately. */ ! for (ix = 0, virtuals = BINFO_VIRTUALS (binfo), ! old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo))); ! virtuals; ! ix++, virtuals = TREE_CHAIN (virtuals), ! old_virtuals = TREE_CHAIN (old_virtuals)) ! update_vtable_entry_for_fn (t, ! binfo, ! BV_FN (old_virtuals), ! &virtuals, ix); ! } ! BINFO_MARKED (binfo) = 1; return NULL_TREE; } --- 2190,2231 ---- static tree dfs_modify_vtables (tree binfo, void* data) { ! tree t = (tree) data; ! tree virtuals; ! tree old_virtuals; ! unsigned ix; ! if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) ! /* A base without a vtable needs no modification, and its bases ! are uninteresting. */ ! return dfs_skip_bases; ! ! if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t) ! && !CLASSTYPE_HAS_PRIMARY_BASE_P (t)) ! /* Don't do the primary vtable, if it's new. */ ! return NULL_TREE; ! ! if (BINFO_PRIMARY_P (binfo) && !BINFO_VIRTUAL_P (binfo)) ! /* There's no need to modify the vtable for a non-virtual primary ! base; we're not going to use that vtable anyhow. We do still ! need to do this for virtual primary bases, as they could become ! non-primary in a construction vtable. */ ! return NULL_TREE; ! ! make_new_vtable (t, binfo); ! ! /* Now, go through each of the virtual functions in the virtual ! function table for BINFO. Find the final overrider, and update ! the BINFO_VIRTUALS list appropriately. */ ! for (ix = 0, virtuals = BINFO_VIRTUALS (binfo), ! old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo))); ! virtuals; ! ix++, virtuals = TREE_CHAIN (virtuals), ! old_virtuals = TREE_CHAIN (old_virtuals)) ! update_vtable_entry_for_fn (t, ! binfo, ! BV_FN (old_virtuals), ! &virtuals, ix); return NULL_TREE; } *************** modify_all_vtables (tree t, tree virtual *** 2321,2328 **** tree *fnsp; /* Update all of the vtables. */ ! dfs_walk (binfo, dfs_modify_vtables, unmarkedp, t); ! dfs_walk (binfo, dfs_unmark, markedp, t); /* Add virtual functions not already in our primary vtable. These will be both those introduced by this class, and those overridden --- 2246,2252 ---- tree *fnsp; /* Update all of the vtables. */ ! dfs_walk_once (binfo, dfs_modify_vtables, NULL, t); /* Add virtual functions not already in our primary vtable. These will be both those introduced by this class, and those overridden *************** get_basefndecls (tree name, tree t) *** 2359,2371 **** { tree methods; tree base_fndecls = NULL_TREE; ! int n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i; /* 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)) { --- 2283,2295 ---- { tree methods; tree base_fndecls = NULL_TREE; ! int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t)); int i; /* Find virtual functions in T with the indicated NAME. */ i = lookup_fnfields_1 (t, name); if (i != -1) ! for (methods = VEC_index (tree, CLASSTYPE_METHOD_VEC (t), i); methods; methods = OVL_NEXT (methods)) { *************** get_basefndecls (tree name, tree t) *** 2381,2387 **** for (i = 0; i < n_baseclasses; i++) { ! tree basetype = TYPE_BINFO_BASETYPE (t, i); base_fndecls = chainon (get_basefndecls (name, basetype), base_fndecls); } --- 2305,2311 ---- for (i = 0; i < n_baseclasses; i++) { ! tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i)); base_fndecls = chainon (get_basefndecls (name, basetype), base_fndecls); } *************** get_basefndecls (tree name, tree t) *** 2393,2399 **** a method declared virtual in the base class, then mark this field as being virtual as well. */ ! static void check_for_override (tree decl, tree ctype) { if (TREE_CODE (decl) == TEMPLATE_DECL) --- 2317,2323 ---- a method declared virtual in the base class, then mark this field as being virtual as well. */ ! void check_for_override (tree decl, tree ctype) { if (TREE_CODE (decl) == TEMPLATE_DECL) *************** check_for_override (tree decl, tree ctyp *** 2426,2454 **** void warn_hidden (tree t) { ! tree method_vec = CLASSTYPE_METHOD_VEC (t); ! int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; ! int i; /* We go through each separately named virtual function. */ ! for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i) { ! tree fns; tree name; tree fndecl; tree base_fndecls; int j; /* All functions in this slot in the CLASSTYPE_METHOD_VEC will have the same name. Figure out what name that is. */ ! name = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); /* There are no possibly hidden functions yet. */ base_fndecls = NULL_TREE; /* Iterate through all of the base classes looking for possibly hidden functions. */ ! for (j = 0; j < CLASSTYPE_N_BASECLASSES (t); j++) { ! tree basetype = TYPE_BINFO_BASETYPE (t, j); base_fndecls = chainon (get_basefndecls (name, basetype), base_fndecls); } --- 2350,2383 ---- void warn_hidden (tree t) { ! VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (t); ! tree fns; ! size_t i; /* We go through each separately named virtual function. */ ! for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; ! VEC_iterate (tree, method_vec, i, fns); ! ++i) { ! tree fn; tree name; tree fndecl; tree base_fndecls; + tree base_binfo; + tree binfo; int j; /* All functions in this slot in the CLASSTYPE_METHOD_VEC will have the same name. Figure out what name that is. */ ! name = DECL_NAME (OVL_CURRENT (fns)); /* There are no possibly hidden functions yet. */ base_fndecls = NULL_TREE; /* Iterate through all of the base classes looking for possibly hidden functions. */ ! for (binfo = TYPE_BINFO (t), j = 0; ! BINFO_BASE_ITERATE (binfo, j, base_binfo); j++) { ! tree basetype = BINFO_TYPE (base_binfo); base_fndecls = chainon (get_basefndecls (name, basetype), base_fndecls); } *************** warn_hidden (tree t) *** 2458,2466 **** continue; /* Remove any overridden functions. */ ! for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns)) { ! fndecl = OVL_CURRENT (fns); if (DECL_VINDEX (fndecl)) { tree *prev = &base_fndecls; --- 2387,2395 ---- continue; /* Remove any overridden functions. */ ! for (fn = fns; fn; fn = OVL_NEXT (fn)) { ! fndecl = OVL_CURRENT (fn); if (DECL_VINDEX (fndecl)) { tree *prev = &base_fndecls; *************** warn_hidden (tree t) *** 2481,2489 **** while (base_fndecls) { /* Here we know it is a hider, and no overrider exists. */ ! cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); ! cp_warning_at (" by `%D'", ! OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); base_fndecls = TREE_CHAIN (base_fndecls); } } --- 2410,2417 ---- while (base_fndecls) { /* Here we know it is a hider, and no overrider exists. */ ! cp_warning_at ("%qD was hidden", TREE_VALUE (base_fndecls)); ! cp_warning_at (" by %qD", fns); base_fndecls = TREE_CHAIN (base_fndecls); } } *************** finish_struct_anon (tree t) *** 2524,2539 **** if (TREE_CODE (elt) != FIELD_DECL) { ! cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members", elt); continue; } if (TREE_PRIVATE (elt)) ! cp_pedwarn_at ("private member `%#D' in anonymous union", elt); else if (TREE_PROTECTED (elt)) ! cp_pedwarn_at ("protected member `%#D' in anonymous union", elt); TREE_PRIVATE (elt) = TREE_PRIVATE (field); --- 2452,2468 ---- if (TREE_CODE (elt) != FIELD_DECL) { ! cp_pedwarn_at ("%q#D invalid; an anonymous union can " ! "only have non-static data members", elt); continue; } if (TREE_PRIVATE (elt)) ! cp_pedwarn_at ("private member %q#D in anonymous union", elt); else if (TREE_PROTECTED (elt)) ! cp_pedwarn_at ("protected member %q#D in anonymous union", elt); TREE_PRIVATE (elt) = TREE_PRIVATE (field); *************** maybe_add_class_template_decl_list (tree *** 2564,2666 **** } /* Create default constructors, assignment operators, and so forth for ! the type indicated by T, if they are needed. ! CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and ! CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the ! class cannot have a default constructor, copy constructor taking a ! const reference argument, or an assignment operator taking a const ! reference, respectively. If a virtual destructor is created, its ! DECL is returned; otherwise the return value is NULL_TREE. */ static void add_implicitly_declared_members (tree t, - int cant_have_default_ctor, int cant_have_const_cctor, int cant_have_const_assignment) { - tree default_fn; - tree implicit_fns = NULL_TREE; - tree virtual_dtor = NULL_TREE; - tree *f; - - ++adding_implicit_members; - /* Destructor. */ ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)) { ! default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0); ! check_for_override (default_fn, t); ! ! /* If we couldn't make it work, then pretend we didn't need it. */ ! if (default_fn == void_type_node) ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0; ! else { ! TREE_CHAIN (default_fn) = implicit_fns; ! implicit_fns = default_fn; ! if (DECL_VINDEX (default_fn)) ! virtual_dtor = default_fn; } } - else - /* Any non-implicit destructor is non-trivial. */ - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); /* Default constructor. */ ! if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor) { ! default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0); ! TREE_CHAIN (default_fn) = implicit_fns; ! implicit_fns = default_fn; } /* Copy constructor. */ if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t)) { ! /* ARM 12.18: You get either X(X&) or X(const X&), but ! not both. --Chip */ ! default_fn ! = implicitly_declare_fn (sfk_copy_constructor, t, ! /*const_p=*/!cant_have_const_cctor); ! TREE_CHAIN (default_fn) = implicit_fns; ! implicit_fns = default_fn; ! } ! ! /* Assignment operator. */ ! if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t)) ! { ! default_fn ! = implicitly_declare_fn (sfk_assignment_operator, t, ! /*const_p=*/!cant_have_const_assignment); ! TREE_CHAIN (default_fn) = implicit_fns; ! implicit_fns = default_fn; } ! /* Now, hook all of the new functions on to TYPE_METHODS, ! and add them to the CLASSTYPE_METHOD_VEC. */ ! for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f)) ! { ! add_method (t, *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; } /* Subroutine of finish_struct_1. Recursively count the number of fields --- 2493,2583 ---- } /* Create default constructors, assignment operators, and so forth for ! the type indicated by T, if they are needed. CANT_HAVE_CONST_CTOR, ! and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, ! the class cannot have a default constructor, copy constructor ! taking a const reference argument, or an assignment operator taking ! a const reference, respectively. */ static void add_implicitly_declared_members (tree t, int cant_have_const_cctor, int cant_have_const_assignment) { /* Destructor. */ ! if (!CLASSTYPE_DESTRUCTORS (t)) { ! /* In general, we create destructors lazily. */ ! CLASSTYPE_LAZY_DESTRUCTOR (t) = 1; ! /* However, if the implicit destructor is non-trivial ! destructor, we sometimes have to create it at this point. */ ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) { ! bool lazy_p = true; ! if (TYPE_FOR_JAVA (t)) ! /* If this a Java class, any non-trivial destructor is ! invalid, even if compiler-generated. Therefore, if the ! destructor is non-trivial we create it now. */ ! lazy_p = false; ! else ! { ! tree binfo; ! tree base_binfo; ! int ix; ! ! /* If the implicit destructor will be virtual, then we must ! generate it now because (unfortunately) we do not ! generate virtual tables lazily. */ ! binfo = TYPE_BINFO (t); ! for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++) ! { ! tree base_type; ! tree dtor; ! ! base_type = BINFO_TYPE (base_binfo); ! dtor = CLASSTYPE_DESTRUCTORS (base_type); ! if (dtor && DECL_VIRTUAL_P (dtor)) ! { ! lazy_p = false; ! break; ! } ! } ! } ! ! /* If we can't get away with being lazy, generate the destructor ! now. */ ! if (!lazy_p) ! lazily_declare_fn (sfk_destructor, t); } } /* Default constructor. */ ! if (! TYPE_HAS_CONSTRUCTOR (t)) { ! TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1; ! CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; } /* Copy constructor. */ if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t)) { ! TYPE_HAS_INIT_REF (t) = 1; ! TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor; ! CLASSTYPE_LAZY_COPY_CTOR (t) = 1; ! TYPE_HAS_CONSTRUCTOR (t) = 1; } ! /* If there is no assignment operator, one will be created if and ! when it is needed. For now, just record whether or not the type ! of the parameter to the assignment operator will be a const or ! non-const reference. */ ! if (!TYPE_HAS_ASSIGN_REF (t) && !TYPE_FOR_JAVA (t)) { ! TYPE_HAS_ASSIGN_REF (t) = 1; ! TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment; ! CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1; } } /* Subroutine of finish_struct_1. Recursively count the number of fields *************** check_bitfield_decl (tree field) *** 2712,2718 **** if (DECL_INITIAL (field) && ! INTEGRAL_TYPE_P (TREE_TYPE (field))) { ! cp_error_at ("bit-field `%#D' with non-integral type", field); w = error_mark_node; } --- 2629,2635 ---- if (DECL_INITIAL (field) && ! INTEGRAL_TYPE_P (TREE_TYPE (field))) { ! cp_error_at ("bit-field %q#D with non-integral type", field); w = error_mark_node; } *************** check_bitfield_decl (tree field) *** 2725,2764 **** STRIP_NOPS (w); /* detect invalid field size. */ ! if (TREE_CODE (w) == CONST_DECL) ! w = DECL_INITIAL (w); ! else ! w = decl_constant_value (w); if (TREE_CODE (w) != INTEGER_CST) { ! cp_error_at ("bit-field `%D' width not an integer constant", field); w = error_mark_node; } else if (tree_int_cst_sgn (w) < 0) { ! cp_error_at ("negative width in bit-field `%D'", field); w = error_mark_node; } else if (integer_zerop (w) && DECL_NAME (field) != 0) { ! cp_error_at ("zero width for bit-field `%D'", field); w = error_mark_node; } else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0 && TREE_CODE (type) != ENUMERAL_TYPE && TREE_CODE (type) != BOOLEAN_TYPE) ! cp_warning_at ("width of `%D' exceeds its type", field); else if (TREE_CODE (type) == ENUMERAL_TYPE && (0 > compare_tree_int (w, min_precision (TYPE_MIN_VALUE (type), ! TREE_UNSIGNED (type))) || 0 > compare_tree_int (w, min_precision (TYPE_MAX_VALUE (type), ! TREE_UNSIGNED (type))))) ! cp_warning_at ("`%D' is too small to hold all values of `%#T'", field, type); } --- 2642,2678 ---- STRIP_NOPS (w); /* detect invalid field size. */ ! w = integral_constant_value (w); if (TREE_CODE (w) != INTEGER_CST) { ! cp_error_at ("bit-field %qD width not an integer constant", field); w = error_mark_node; } else if (tree_int_cst_sgn (w) < 0) { ! cp_error_at ("negative width in bit-field %qD", field); w = error_mark_node; } else if (integer_zerop (w) && DECL_NAME (field) != 0) { ! cp_error_at ("zero width for bit-field %qD", field); w = error_mark_node; } else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0 && TREE_CODE (type) != ENUMERAL_TYPE && TREE_CODE (type) != BOOLEAN_TYPE) ! cp_warning_at ("width of %qD exceeds its type", field); else if (TREE_CODE (type) == ENUMERAL_TYPE && (0 > compare_tree_int (w, min_precision (TYPE_MIN_VALUE (type), ! TYPE_UNSIGNED (type))) || 0 > compare_tree_int (w, min_precision (TYPE_MAX_VALUE (type), ! TYPE_UNSIGNED (type))))) ! cp_warning_at ("%qD is too small to hold all values of %q#T", field, type); } *************** static void *** 2787,2793 **** check_field_decl (tree field, tree t, int* cant_have_const_ctor, - int* cant_have_default_ctor, int* no_const_asn_ref, int* any_default_members) { --- 2701,2706 ---- *************** check_field_decl (tree field, *** 2806,2813 **** for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field)) check_field_decl (fields, t, cant_have_const_ctor, ! cant_have_default_ctor, no_const_asn_ref, ! any_default_members); } /* Check members with class type for constructors, destructors, etc. */ --- 2719,2725 ---- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field)) check_field_decl (fields, t, cant_have_const_ctor, ! no_const_asn_ref, any_default_members); } /* Check members with class type for constructors, destructors, etc. */ *************** check_field_decl (tree field, *** 2820,2832 **** if (TREE_CODE (t) == UNION_TYPE) { if (TYPE_NEEDS_CONSTRUCTING (type)) ! cp_error_at ("member `%#D' with constructor not allowed in union", field); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! cp_error_at ("member `%#D' with destructor not allowed in union", field); if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) ! cp_error_at ("member `%#D' with copy assignment operator not allowed in union", field); } else --- 2732,2744 ---- if (TREE_CODE (t) == UNION_TYPE) { if (TYPE_NEEDS_CONSTRUCTING (type)) ! cp_error_at ("member %q#D with constructor not allowed in union", field); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! cp_error_at ("member %q#D with destructor not allowed in union", field); if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) ! cp_error_at ("member %q#D with copy assignment operator not allowed in union", field); } else *************** check_field_decl (tree field, *** 2843,2859 **** if (!TYPE_HAS_CONST_ASSIGN_REF (type)) *no_const_asn_ref = 1; - - if (TYPE_HAS_CONSTRUCTOR (type) - && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) - *cant_have_default_ctor = 1; } if (DECL_INITIAL (field) != NULL_TREE) { /* `build_class_init_list' does not recognize non-FIELD_DECLs. */ if (TREE_CODE (t) == UNION_TYPE && any_default_members != 0) ! error ("multiple fields in union `%T' initialized", t); *any_default_members = 1; } } --- 2755,2767 ---- if (!TYPE_HAS_CONST_ASSIGN_REF (type)) *no_const_asn_ref = 1; } if (DECL_INITIAL (field) != NULL_TREE) { /* `build_class_init_list' does not recognize non-FIELD_DECLs. */ if (TREE_CODE (t) == UNION_TYPE && any_default_members != 0) ! error ("multiple fields in union %qT initialized", t); *any_default_members = 1; } } *************** check_field_decl (tree field, *** 2869,2878 **** EMPTY_P The class is empty, i.e., contains no non-static data members. - CANT_HAVE_DEFAULT_CTOR_P - This class cannot have an implicitly generated default - constructor. - CANT_HAVE_CONST_CTOR_P This class cannot have an implicitly generated copy constructor taking a const reference. --- 2777,2782 ---- *************** check_field_decl (tree field, *** 2889,2907 **** static void 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; ! int has_pointers; int any_default_members; /* Assume there are no access declarations. */ *access_decls = NULL_TREE; /* Assume this class has no pointer members. */ ! has_pointers = 0; /* Assume none of the members of this class have default initializations. */ any_default_members = 0; --- 2793,2810 ---- static void check_field_decls (tree t, tree *access_decls, int *cant_have_const_ctor_p, int *no_const_asn_ref_p) { tree *field; tree *next; ! bool has_pointers; int any_default_members; /* Assume there are no access declarations. */ *access_decls = NULL_TREE; /* Assume this class has no pointer members. */ ! has_pointers = false; /* Assume none of the members of this class have default initializations. */ any_default_members = 0; *************** check_field_decls (tree t, tree *access_ *** 2919,2925 **** { if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x))) cp_warning_at ! ("ignoring packed attribute on unpacked non-POD field `%#D'", x); else DECL_PACKED (x) = 1; --- 2822,2828 ---- { if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x))) cp_warning_at ! ("ignoring packed attribute on unpacked non-POD field %q#D", x); else DECL_PACKED (x) = 1; *************** check_field_decls (tree t, tree *access_ *** 2976,2990 **** /* [class.union] If a union contains a static data member, or a member of ! reference type, the program is ill-formed. */ if (TREE_CODE (x) == VAR_DECL) { ! cp_error_at ("`%D' may not be static because it is a member of a union", x); continue; } if (TREE_CODE (type) == REFERENCE_TYPE) { ! cp_error_at ("`%D' may not have reference type `%T' because it is a member of a union", x, type); continue; } --- 2879,2894 ---- /* [class.union] If a union contains a static data member, or a member of ! reference type, the program is ill-formed. */ if (TREE_CODE (x) == VAR_DECL) { ! cp_error_at ("%qD may not be static because it is a member of a union", x); continue; } if (TREE_CODE (type) == REFERENCE_TYPE) { ! cp_error_at ("%qD may not have reference type %qT because" ! " it is a member of a union", x, type); continue; } *************** check_field_decls (tree t, tree *access_ *** 2992,3011 **** /* ``A local class cannot have static data members.'' ARM 9.4 */ if (current_function_decl && TREE_STATIC (x)) ! cp_error_at ("field `%D' in local class cannot be static", x); /* Perform error checking that did not get done in grokdeclarator. */ if (TREE_CODE (type) == FUNCTION_TYPE) { ! cp_error_at ("field `%D' invalidly declared function type", ! x); type = build_pointer_type (type); TREE_TYPE (x) = type; } else if (TREE_CODE (type) == METHOD_TYPE) { ! cp_error_at ("field `%D' invalidly declared method type", x); type = build_pointer_type (type); TREE_TYPE (x) = type; } --- 2896,2914 ---- /* ``A local class cannot have static data members.'' ARM 9.4 */ if (current_function_decl && TREE_STATIC (x)) ! cp_error_at ("field %qD in local class cannot be static", x); /* Perform error checking that did not get done in grokdeclarator. */ if (TREE_CODE (type) == FUNCTION_TYPE) { ! cp_error_at ("field %qD invalidly declared function type", x); type = build_pointer_type (type); TREE_TYPE (x) = type; } else if (TREE_CODE (type) == METHOD_TYPE) { ! cp_error_at ("field %qD invalidly declared method type", x); type = build_pointer_type (type); TREE_TYPE (x) = type; } *************** check_field_decls (tree t, tree *access_ *** 3033,3050 **** aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - *cant_have_default_ctor_p = 1; TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t) && extra_warnings) ! cp_warning_at ("non-static reference `%#D' in class without a constructor", x); } type = strip_array_types (type); ! ! if (TYPE_PTR_P (type)) ! has_pointers = 1; if (CLASS_TYPE_P (type)) { --- 2936,2957 ---- aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t) && extra_warnings) ! cp_warning_at ("non-static reference %q#D in class without a constructor", x); } type = strip_array_types (type); ! ! /* This is used by -Weffc++ (see below). Warn only for pointers ! to members which might hold dynamic memory. So do not warn ! for pointers to functions or pointers to members. */ ! if (TYPE_PTR_P (type) ! && !TYPE_PTRFN_P (type) ! && !TYPE_PTR_TO_MEMBER_P (type)) ! has_pointers = true; if (CLASS_TYPE_P (type)) { *************** check_field_decls (tree t, tree *access_ *** 3076,3087 **** aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - *cant_have_default_ctor_p = 1; TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; 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. */ else if (CLASS_TYPE_P (type)) --- 2983,2993 ---- aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t) && extra_warnings) ! cp_warning_at ("non-static const member %q#D in class without a constructor", x); } /* A field that is pseudo-const makes the structure likewise. */ else if (CLASS_TYPE_P (type)) *************** check_field_decls (tree t, tree *access_ *** 3096,3102 **** different name from the class iff the class has a user-defined constructor. */ if (constructor_name_p (DECL_NAME (x), t) && TYPE_HAS_CONSTRUCTOR (t)) ! cp_pedwarn_at ("field `%#D' with same name as class", x); /* We set DECL_C_BIT_FIELD in grokbitfield. If the type and width are valid, we'll also set DECL_BIT_FIELD. */ --- 3002,3008 ---- different name from the class iff the class has a user-defined constructor. */ if (constructor_name_p (DECL_NAME (x), t) && TYPE_HAS_CONSTRUCTOR (t)) ! cp_pedwarn_at ("field %q#D with same name as class", x); /* We set DECL_C_BIT_FIELD in grokbitfield. If the type and width are valid, we'll also set DECL_BIT_FIELD. */ *************** check_field_decls (tree t, tree *access_ *** 3105,3129 **** else check_field_decl (x, t, cant_have_const_ctor_p, - cant_have_default_ctor_p, no_const_asn_ref_p, &any_default_members); } ! /* Effective C++ rule 11. */ ! if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t) ! && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t))) { ! warning ("`%#T' has pointer data members", t); if (! TYPE_HAS_INIT_REF (t)) { ! warning (" but does not override `%T(const %T&)'", t, t); if (! TYPE_HAS_ASSIGN_REF (t)) ! warning (" or `operator=(const %T&)'", t); } else if (! TYPE_HAS_ASSIGN_REF (t)) ! warning (" but does not override `operator=(const %T&)'", t); } --- 3011,3050 ---- else check_field_decl (x, t, cant_have_const_ctor_p, no_const_asn_ref_p, &any_default_members); } ! /* Effective C++ rule 11: if a class has dynamic memory held by pointers, ! it should also define a copy constructor and an assignment operator to ! implement the correct copy semantic (deep vs shallow, etc.). As it is ! not feasible to check whether the constructors do allocate dynamic memory ! and store it within members, we approximate the warning like this: ! ! -- Warn only if there are members which are pointers ! -- Warn only if there is a non-trivial constructor (otherwise, ! there cannot be memory allocated). ! -- Warn only if there is a non-trivial destructor. We assume that the ! user at least implemented the cleanup correctly, and a destructor ! is needed to free dynamic memory. ! ! This seems enough for practical purposes. */ ! if (warn_ecpp ! && has_pointers ! && TYPE_HAS_CONSTRUCTOR (t) ! && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) ! && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t))) { ! warning ("%q#T has pointer data members", t); if (! TYPE_HAS_INIT_REF (t)) { ! warning (" but does not override %<%T(const %T&)%>", t, t); if (! TYPE_HAS_ASSIGN_REF (t)) ! warning (" or %", t); } else if (! TYPE_HAS_ASSIGN_REF (t)) ! warning (" but does not override %", t); } *************** walk_subobject_offsets (tree type, *** 3236,3253 **** /* Iterate through the direct base classes of TYPE. */ if (!type_binfo) type_binfo = TYPE_BINFO (type); ! for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++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; --- 3157,3172 ---- /* Iterate through the direct base classes of TYPE. */ if (!type_binfo) type_binfo = TYPE_BINFO (type); ! for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, binfo); i++) { tree binfo_offset; if (abi_version_at_least (2) ! && BINFO_VIRTUAL_P (binfo)) continue; if (!vbases_p ! && BINFO_VIRTUAL_P (binfo) && !BINFO_PRIMARY_P (binfo)) continue; *************** walk_subobject_offsets (tree type, *** 3261,3267 **** /* 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)); --- 3180,3186 ---- /* 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_BASE_BINFO (TYPE_BINFO (type), i); binfo_offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (orig_binfo)); *************** walk_subobject_offsets (tree type, *** 3278,3286 **** 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 --- 3197,3206 ---- return r; } ! if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type)) { ! unsigned ix; ! VEC (tree) *vbases; /* Iterate through the virtual base classes of TYPE. In G++ 3.2, we included virtual bases in the direct base class *************** walk_subobject_offsets (tree type, *** 3288,3298 **** 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, --- 3208,3216 ---- correct offsets for virtual bases are only known when working with the most derived type. */ if (vbases_p) ! for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0; ! VEC_iterate (tree, vbases, ix, binfo); ix++) { r = walk_subobject_offsets (binfo, f, size_binop (PLUS_EXPR, *************** walk_subobject_offsets (tree type, *** 3309,3317 **** /* 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) ! && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo) { r = (walk_subobject_offsets (vbase, f, offset, --- 3227,3237 ---- /* We still have to walk the primary base, if it is virtual. (If it is non-virtual, then it was walked above.) */ ! tree vbase = get_primary_binfo (type_binfo); ! ! if (vbase && BINFO_VIRTUAL_P (vbase) ! && BINFO_PRIMARY_P (vbase) ! && BINFO_INHERITANCE_CHAIN (vbase) == type_binfo) { r = (walk_subobject_offsets (vbase, f, offset, *************** layout_nonempty_base_or_field (record_la *** 3488,3494 **** break; /* 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)) --- 3408,3414 ---- break; /* G++ 3.2 did not check for overlaps when placing a non-empty virtual base. */ ! if (!abi_version_at_least (2) && binfo && BINFO_VIRTUAL_P (binfo)) break; if (layout_conflict_p (field_p ? type : binfo, offset, offsets, field_p)) *************** layout_empty_base (tree binfo, tree eoc, *** 3548,3554 **** 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 (!integer_zerop (BINFO_OFFSET (binfo))) --- 3468,3474 ---- bool atend = false; /* This routine should only be used for empty classes. */ ! gcc_assert (is_empty_class (basetype)); alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype)); if (!integer_zerop (BINFO_OFFSET (binfo))) *************** layout_empty_base (tree binfo, tree eoc, *** 3557,3563 **** propagate_binfo_offsets (binfo, size_diffop (size_zero_node, BINFO_OFFSET (binfo))); else if (warn_abi) ! warning ("offset of empty base `%T' may not be ABI-compliant and may" "change in a future version of GCC", BINFO_TYPE (binfo)); } --- 3477,3483 ---- propagate_binfo_offsets (binfo, size_diffop (size_zero_node, BINFO_OFFSET (binfo))); else if (warn_abi) ! warning ("offset of empty base %qT may not be ABI-compliant and may" "change in a future version of GCC", BINFO_TYPE (binfo)); } *************** layout_empty_base (tree binfo, tree eoc, *** 3589,3595 **** return atend; } ! /* 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 --- 3509,3515 ---- return atend; } ! /* Layout 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 *************** build_base_field (record_layout_info rli *** 3622,3633 **** /* 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 --- 3542,3555 ---- /* Create the FIELD_DECL. */ decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype)); DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (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_MODE (decl) = TYPE_MODE (basetype); ! DECL_FIELD_IS_BASE (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 *************** build_base_field (record_layout_info rli *** 3650,3656 **** atend = layout_empty_base (binfo, eoc, offsets); /* 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; --- 3572,3578 ---- atend = layout_empty_base (binfo, eoc, offsets); /* A nearly-empty class "has no proper base class that is empty, not morally virtual, and at an offset other than zero." */ ! if (!BINFO_VIRTUAL_P (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t)) { if (atend) CLASSTYPE_NEARLY_EMPTY_P (t) = 0; *************** build_base_field (record_layout_info rli *** 3667,3673 **** 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); } } --- 3589,3595 ---- if (abi_version_at_least (2)) CLASSTYPE_NEARLY_EMPTY_P (t) = 0; else if (warn_abi) ! warning ("class %qT will be considered nearly empty in a " "future version of GCC", t); } } *************** build_base_fields (record_layout_info rl *** 3706,3712 **** /* Chain to hold all the new FIELD_DECLs which stand in for base class subobjects. */ tree t = rli->t; ! int n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i; /* The primary base class is always allocated first. */ --- 3628,3634 ---- /* Chain to hold all the new FIELD_DECLs which stand in for base class subobjects. */ tree t = rli->t; ! int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t)); int i; /* The primary base class is always allocated first. */ *************** build_base_fields (record_layout_info rl *** 3719,3725 **** { tree base_binfo; ! 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. */ --- 3641,3647 ---- { tree base_binfo; ! base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (t), i); /* The primary base was already allocated above, so we don't need to allocate it again here. */ *************** build_base_fields (record_layout_info rl *** 3728,3734 **** /* Virtual bases are added at the end (a primary virtual base will have already been added). */ ! if (TREE_VIA_VIRTUAL (base_binfo)) continue; next_field = build_base_field (rli, base_binfo, --- 3650,3656 ---- /* Virtual bases are added at the end (a primary virtual base will have already been added). */ ! if (BINFO_VIRTUAL_P (base_binfo)) continue; next_field = build_base_field (rli, base_binfo, *************** check_methods (tree t) *** 3747,3770 **** for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) { - /* If this was an evil function, don't keep it in class. */ - if (DECL_ASSEMBLER_NAME_SET_P (x) - && IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) - continue; - check_for_override (x, t); if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x)) ! cp_error_at ("initializer specified for non-virtual method `%D'", x); ! /* The name of the field is the original field name Save this in auxiliary field for later overloading. */ if (DECL_VINDEX (x)) { TYPE_POLYMORPHIC_P (t) = 1; if (DECL_PURE_VIRTUAL_P (x)) ! CLASSTYPE_PURE_VIRTUALS (t) ! = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t)); } } } --- 3669,3688 ---- for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) { check_for_override (x, t); if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x)) ! cp_error_at ("initializer specified for non-virtual method %qD", x); /* The name of the field is the original field name Save this in auxiliary field for later overloading. */ if (DECL_VINDEX (x)) { TYPE_POLYMORPHIC_P (t) = 1; if (DECL_PURE_VIRTUAL_P (x)) ! VEC_safe_push (tree, CLASSTYPE_PURE_VIRTUALS (t), x); } + /* All user-declared destructors are non-trivial. */ + if (DECL_DESTRUCTOR_P (x)) + TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1; } } *************** build_clone (tree fn, tree name) *** 3867,3873 **** /* Create the RTL for this function. */ SET_DECL_RTL (clone, NULL_RTX); ! rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof); /* Make it easy to find the CLONE given the FN. */ TREE_CHAIN (clone) = TREE_CHAIN (fn); --- 3785,3791 ---- /* Create the RTL for this function. */ SET_DECL_RTL (clone, NULL_RTX); ! rest_of_decl_compilation (clone, /*top_level=*/1, at_eof); /* Make it easy to find the CLONE given the FN. */ TREE_CHAIN (clone) = TREE_CHAIN (fn); *************** build_clone (tree fn, tree name) *** 3884,3891 **** DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result)); DECL_TI_TEMPLATE (result) = clone; } ! else if (DECL_DEFERRED_FN (fn)) ! defer_fn (clone); return clone; } --- 3802,3809 ---- DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result)); DECL_TI_TEMPLATE (result) = clone; } ! else if (pch_file) ! note_decl_for_pch (clone); return clone; } *************** clone_function_decl (tree fn, int update *** 3910,3923 **** and a not-in-charge version. */ clone = build_clone (fn, complete_ctor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); clone = build_clone (fn, base_ctor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } else { ! my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411); /* For each destructor, we need three variants: an in-charge version, a not-in-charge version, and an in-charge deleting --- 3828,3841 ---- and a not-in-charge version. */ clone = build_clone (fn, complete_ctor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone); clone = build_clone (fn, base_ctor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone); } else { ! gcc_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)); /* For each destructor, we need three variants: an in-charge version, a not-in-charge version, and an in-charge deleting *************** clone_function_decl (tree fn, int update *** 3932,3945 **** { clone = build_clone (fn, deleting_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } clone = build_clone (fn, complete_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); clone = build_clone (fn, base_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } /* Note that this is an abstract function that is never emitted. */ --- 3850,3863 ---- { clone = build_clone (fn, deleting_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone); } clone = build_clone (fn, complete_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone); clone = build_clone (fn, base_dtor_identifier); if (update_method_vec_p) ! add_method (DECL_CONTEXT (clone), clone); } /* Note that this is an abstract function that is never emitted. */ *************** adjust_clone_args (tree decl) *** 3984,3991 **** decl_parms = TREE_CHAIN (decl_parms), clone_parms = TREE_CHAIN (clone_parms)) { ! my_friendly_assert (same_type_p (TREE_TYPE (decl_parms), ! TREE_TYPE (clone_parms)), 20010424); if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms)) { --- 3902,3909 ---- decl_parms = TREE_CHAIN (decl_parms), clone_parms = TREE_CHAIN (clone_parms)) { ! gcc_assert (same_type_p (TREE_TYPE (decl_parms), ! TREE_TYPE (clone_parms))); if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms)) { *************** adjust_clone_args (tree decl) *** 4015,4021 **** break; } } ! my_friendly_assert (!clone_parms, 20010424); } } --- 3933,3939 ---- break; } } ! gcc_assert (!clone_parms); } } *************** type_requires_array_cookie (tree type) *** 4066,4072 **** tree fns; bool has_two_argument_delete_p = false; ! my_friendly_assert (CLASS_TYPE_P (type), 20010712); /* If there's a non-trivial destructor, we need a cookie. In order to iterate through the array calling the destructor for each --- 3984,3990 ---- tree fns; bool has_two_argument_delete_p = false; ! gcc_assert (CLASS_TYPE_P (type)); /* If there's a non-trivial destructor, we need a cookie. In order to iterate through the array calling the destructor for each *************** type_requires_array_cookie (tree type) *** 4118,4153 **** static void check_bases_and_members (tree t) { - /* Nonzero if we are not allowed to generate a default constructor - for this case. */ - int cant_have_default_ctor; /* Nonzero if the implicitly generated copy constructor should take a non-const reference argument. */ int cant_have_const_ctor; ! /* Nonzero if the the implicitly generated assignment operator should take a non-const reference argument. */ int no_const_asn_ref; tree access_decls; /* By default, we use const reference arguments and generate default constructors. */ - cant_have_default_ctor = 0; cant_have_const_ctor = 0; no_const_asn_ref = 0; /* 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, - &cant_have_default_ctor, &cant_have_const_ctor, &no_const_asn_ref); - /* Check all the method declarations. */ - check_methods (t); - /* A nearly-empty class has to be vptr-containing; a nearly empty class contains just a vptr. */ if (!TYPE_CONTAINS_VPTR_P (t)) --- 4036,4069 ---- static void check_bases_and_members (tree t) { /* Nonzero if the implicitly generated copy constructor should take a non-const reference argument. */ int cant_have_const_ctor; ! /* Nonzero if the implicitly generated assignment operator should take a non-const reference argument. */ int no_const_asn_ref; tree access_decls; /* By default, we use const reference arguments and generate default constructors. */ cant_have_const_ctor = 0; no_const_asn_ref = 0; /* Check all the base-classes. */ ! check_bases (t, &cant_have_const_ctor, &no_const_asn_ref); ! /* Check all the method declarations. */ ! check_methods (t); ! ! /* Check all the data member declarations. We cannot call ! check_field_decls until we have called check_bases check_methods, ! as check_field_decls depends on TYPE_HAS_NONTRIVIAL_DESTRUCTOR ! being set appropriately. */ check_field_decls (t, &access_decls, &cant_have_const_ctor, &no_const_asn_ref); /* A nearly-empty class has to be vptr-containing; a nearly empty class contains just a vptr. */ if (!TYPE_CONTAINS_VPTR_P (t)) *************** check_bases_and_members (tree t) *** 4156,4180 **** /* Do some bookkeeping that will guide the generation of implicitly declared member functions. */ TYPE_HAS_COMPLEX_INIT_REF (t) ! |= (TYPE_HAS_INIT_REF (t) ! || TYPE_USES_VIRTUAL_BASECLASSES (t) ! || TYPE_POLYMORPHIC_P (t)); TYPE_NEEDS_CONSTRUCTING (t) ! |= (TYPE_HAS_CONSTRUCTOR (t) ! || TYPE_USES_VIRTUAL_BASECLASSES (t) ! || TYPE_POLYMORPHIC_P (t)); ! CLASSTYPE_NON_AGGREGATE (t) |= (TYPE_HAS_CONSTRUCTOR (t) ! || TYPE_POLYMORPHIC_P (t)); CLASSTYPE_NON_POD_P (t) ! |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) || TYPE_HAS_ASSIGN_REF (t)); - TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t); ! /* Synthesize any needed methods. Note that methods will be synthesized ! for anonymous unions; grok_x_components undoes that. */ ! add_implicitly_declared_members (t, cant_have_default_ctor, cant_have_const_ctor, no_const_asn_ref); --- 4072,4091 ---- /* Do some bookkeeping that will guide the generation of implicitly declared member functions. */ TYPE_HAS_COMPLEX_INIT_REF (t) ! |= (TYPE_HAS_INIT_REF (t) || TYPE_CONTAINS_VPTR_P (t)); TYPE_NEEDS_CONSTRUCTING (t) ! |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t)); ! CLASSTYPE_NON_AGGREGATE (t) ! |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t)); CLASSTYPE_NON_POD_P (t) ! |= (CLASSTYPE_NON_AGGREGATE (t) ! || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) || TYPE_HAS_ASSIGN_REF (t)); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t); ! /* Synthesize any needed methods. */ ! add_implicitly_declared_members (t, cant_have_const_ctor, no_const_asn_ref); *************** create_vtable_ptr (tree t, tree* virtual *** 4216,4221 **** --- 4127,4133 ---- BV_FN (new_virtual) = fn; BV_DELTA (new_virtual) = integer_zero_node; + BV_VCALL_INDEX (new_virtual) = NULL_TREE; TREE_CHAIN (new_virtual) = *virtuals_p; *virtuals_p = new_virtual; *************** create_vtable_ptr (tree t, tree* virtual *** 4229,4235 **** { /* We build this decl with vtbl_ptr_type_node, which is a `vtable_entry_type*'. It might seem more precise to use ! `vtable_entry_type (*)[N]' where N is the number of firtual functions. However, that would require the vtable pointer in base classes to have a different type than the vtable pointer in derived classes. We could make that happen, but that --- 4141,4147 ---- { /* We build this decl with vtbl_ptr_type_node, which is a `vtable_entry_type*'. It might seem more precise to use ! `vtable_entry_type (*)[N]' where N is the number of virtual functions. However, that would require the vtable pointer in base classes to have a different type than the vtable pointer in derived classes. We could make that happen, but that *************** create_vtable_ptr (tree t, tree* virtual *** 4260,4272 **** /* This class is non-empty. */ CLASSTYPE_EMPTY_P (t) = 0; - if (CLASSTYPE_N_BASECLASSES (t)) - /* If there were any baseclasses, they can't possibly be at - offset zero any more, because that's where the vtable - pointer is. So, converting to a base class is going to - take work. */ - TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1; - return field; } --- 4172,4177 ---- *************** static void *** 4297,4302 **** --- 4202,4209 ---- fixup_inline_methods (tree type) { tree method = TYPE_METHODS (type); + VEC (tree) *friends; + unsigned ix; if (method && TREE_CODE (method) == TREE_VEC) { *************** fixup_inline_methods (tree type) *** 4313,4323 **** fixup_pending_inline (method); /* Do friends. */ ! for (method = CLASSTYPE_INLINE_FRIENDS (type); ! method; ! method = TREE_CHAIN (method)) ! fixup_pending_inline (TREE_VALUE (method)); ! CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE; } /* Add OFFSET to all base types of BINFO which is a base in the --- 4220,4229 ---- fixup_pending_inline (method); /* Do friends. */ ! for (friends = CLASSTYPE_INLINE_FRIENDS (type), ix = 0; ! VEC_iterate (tree, friends, ix, method); ix++) ! fixup_pending_inline (method); ! CLASSTYPE_INLINE_FRIENDS (type) = NULL; } /* Add OFFSET to all base types of BINFO which is a base in the *************** propagate_binfo_offsets (tree binfo, tre *** 4330,4335 **** --- 4236,4242 ---- { int i; tree primary_binfo; + tree base_binfo; /* Update BINFO's offset. */ BINFO_OFFSET (binfo) *************** propagate_binfo_offsets (tree binfo, tre *** 4341,4373 **** /* Find the primary base class. */ primary_binfo = get_primary_binfo (binfo); /* Scan all of the bases, pushing the BINFO_OFFSET adjust downwards. */ ! for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i) { ! tree base_binfo; ! ! /* On the first time through the loop, do the primary base. ! Because the primary base need not be an immediate base, we ! must handle the primary base specially. */ ! if (i == -1) ! { ! if (!primary_binfo) ! continue; ! ! base_binfo = primary_binfo; ! } ! else ! { ! base_binfo = BINFO_BASETYPE (binfo, i); ! /* Don't do the primary base twice. */ ! if (base_binfo == primary_binfo) ! continue; ! } ! /* Skip virtual bases that aren't our canonical primary base. */ ! if (TREE_VIA_VIRTUAL (base_binfo) ! && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo) continue; propagate_binfo_offsets (base_binfo, offset); --- 4248,4265 ---- /* Find the primary base class. */ primary_binfo = get_primary_binfo (binfo); + if (primary_binfo && BINFO_INHERITANCE_CHAIN (primary_binfo) == binfo) + propagate_binfo_offsets (primary_binfo, offset); + /* Scan all of the bases, pushing the BINFO_OFFSET adjust downwards. */ ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { ! /* Don't do the primary base twice. */ ! if (base_binfo == primary_binfo) ! continue; ! if (BINFO_VIRTUAL_P (base_binfo)) continue; propagate_binfo_offsets (base_binfo, offset); *************** layout_virtual_bases (record_layout_info *** 4386,4392 **** bool first_vbase = true; tree *next_field; ! if (CLASSTYPE_N_BASECLASSES (t) == 0) return; if (!abi_version_at_least(2)) --- 4278,4284 ---- bool first_vbase = true; tree *next_field; ! if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) == 0) return; if (!abi_version_at_least(2)) *************** layout_virtual_bases (record_layout_info *** 4415,4421 **** allocated in inheritance graph order. */ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) { ! if (!TREE_VIA_VIRTUAL (vbase)) continue; if (!BINFO_PRIMARY_P (vbase)) --- 4307,4313 ---- allocated in inheritance graph order. */ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) { ! if (!BINFO_VIRTUAL_P (vbase)) continue; if (!BINFO_PRIMARY_P (vbase)) *************** layout_virtual_bases (record_layout_info *** 4442,4448 **** 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); first_vbase = false; --- 4334,4341 ---- CLASSTYPE_ALIGN (basetype)), bitsize_unit_node), BINFO_OFFSET (vbase)))) ! warning ("offset of virtual base %qT is not ABI-compliant and " ! "may change in a future version of GCC", basetype); first_vbase = false; *************** static tree *** 4477,4507 **** end_of_class (tree t, int include_virtuals_p) { tree result = size_zero_node; tree binfo; tree offset; int i; ! for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i) { - binfo = BINFO_BASETYPE (TYPE_BINFO (t), i); - if (!include_virtuals_p ! && TREE_VIA_VIRTUAL (binfo) ! && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t)) continue; ! 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; } --- 4370,4401 ---- end_of_class (tree t, int include_virtuals_p) { tree result = size_zero_node; + VEC (tree) *vbases; tree binfo; + tree base_binfo; tree offset; int i; ! for (binfo = TYPE_BINFO (t), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { if (!include_virtuals_p ! && BINFO_VIRTUAL_P (base_binfo) ! && (!BINFO_PRIMARY_P (base_binfo) ! || BINFO_INHERITANCE_CHAIN (base_binfo) != TYPE_BINFO (t))) continue; ! offset = end_of_base (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 (vbases = CLASSTYPE_VBASECLASSES (t), i = 0; ! VEC_iterate (tree, vbases, i, base_binfo); i++) { ! offset = end_of_base (base_binfo); if (INT_CST_LT_UNSIGNED (result, offset)) result = offset; } *************** static void *** 4523,4551 **** warn_about_ambiguous_bases (tree t) { int i; ! tree vbases; tree basetype; /* Check direct bases. */ ! for (i = 0; i < CLASSTYPE_N_BASECLASSES (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); } /* 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); } } --- 4417,4451 ---- warn_about_ambiguous_bases (tree t) { int i; ! VEC (tree) *vbases; tree basetype; + tree binfo; + tree base_binfo; + /* If there are no repeated bases, nothing can be ambiguous. */ + if (!CLASSTYPE_REPEATED_BASE_P (t)) + return; + /* Check direct bases. */ ! for (binfo = TYPE_BINFO (t), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { ! basetype = BINFO_TYPE (base_binfo); ! if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL)) ! warning ("direct base %qT inaccessible in %qT due to ambiguity", basetype, t); } /* Check for ambiguous virtual bases. */ if (extra_warnings) ! for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0; ! VEC_iterate (tree, vbases, i, binfo); i++) { ! basetype = BINFO_TYPE (binfo); ! if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL)) ! warning ("virtual base %qT inaccessible in %qT due to ambiguity", basetype, t); } } *************** include_empty_classes (record_layout_inf *** 4587,4596 **** rli->bitpos = round_down (rli->bitpos, BITS_PER_UNIT); else /* The size should have been rounded to a whole byte. */ ! my_friendly_assert (tree_int_cst_equal (rli->bitpos, ! round_down (rli->bitpos, ! BITS_PER_UNIT)), ! 20030903); rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, --- 4487,4494 ---- rli->bitpos = round_down (rli->bitpos, BITS_PER_UNIT); else /* The size should have been rounded to a whole byte. */ ! gcc_assert (tree_int_cst_equal ! (rli->bitpos, round_down (rli->bitpos, BITS_PER_UNIT))); rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, *************** layout_class_type (tree t, tree *virtual *** 4630,4638 **** /* Start laying out the record. */ rli = start_record_layout (t); ! /* If possible, we reuse the virtual function table pointer from one ! of our base classes. */ ! determine_primary_base (t); /* Create a pointer to our virtual function table. */ vptr = create_vtable_ptr (t, virtuals_p); --- 4528,4535 ---- /* Start laying out the record. */ rli = start_record_layout (t); ! /* Mark all the primary bases in the hierarchy. */ ! determine_primary_bases (t); /* Create a pointer to our virtual function table. */ vptr = create_vtable_ptr (t, virtuals_p); *************** layout_class_type (tree t, tree *virtual *** 4675,4681 **** At this point, finish_record_layout will be called, but S1 is still incomplete.) */ if (TREE_CODE (field) == VAR_DECL) ! maybe_register_incomplete_var (field); continue; } --- 4572,4584 ---- At this point, finish_record_layout will be called, but S1 is still incomplete.) */ if (TREE_CODE (field) == VAR_DECL) ! { ! maybe_register_incomplete_var (field); ! /* The visibility of static data members is determined ! at their point of declaration, not their point of ! definition. */ ! determine_visibility (field); ! } continue; } *************** layout_class_type (tree t, tree *virtual *** 4719,4725 **** 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); --- 4622,4628 ---- else { if (warn_abi && TREE_CODE (t) == UNION_TYPE) ! warning ("size assigned to %qT may not be " "ABI-compliant and may change in a future " "version of GCC", t); *************** layout_class_type (tree t, tree *virtual *** 4758,4764 **** && DECL_MODE (field) != TYPE_MODE (type)) /* Versions of G++ before G++ 3.4 did not reset the DECL_MODE. */ ! warning ("the offset of `%D' may not be ABI-compliant and may " "change in a future version of GCC", field); } else --- 4661,4667 ---- && DECL_MODE (field) != TYPE_MODE (type)) /* Versions of G++ before G++ 3.4 did not reset the DECL_MODE. */ ! warning ("the offset of %qD may not be ABI-compliant and may " "change in a future version of GCC", field); } else *************** layout_class_type (tree t, tree *virtual *** 4781,4787 **** && !integer_zerop (size_binop (TRUNC_MOD_EXPR, DECL_FIELD_BIT_OFFSET (field), bitsize_unit_node))) ! 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 --- 4684,4691 ---- && !integer_zerop (size_binop (TRUNC_MOD_EXPR, DECL_FIELD_BIT_OFFSET (field), bitsize_unit_node))) ! cp_warning_at ("offset of %qD 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 *************** layout_class_type (tree t, tree *virtual *** 4790,4796 **** && !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); --- 4694,4700 ---- && !tree_int_cst_equal (DECL_FIELD_OFFSET (field), byte_position (field)) && contains_empty_class_p (TREE_TYPE (field))) ! cp_warning_at ("%qD contains empty classes which may cause base " "classes to be placed at different locations in a " "future version of GCC", field); *************** layout_class_type (tree t, tree *virtual *** 4808,4813 **** --- 4712,4718 ---- DECL_SIZE (padding_field) = padding; DECL_CONTEXT (padding_field) = t; DECL_ARTIFICIAL (padding_field) = 1; + DECL_IGNORED_P (padding_field) = 1; layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, empty_base_offsets); *************** layout_class_type (tree t, tree *virtual *** 4849,4855 **** 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); } --- 4754,4760 ---- 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 %qT " "may change in a future version of GCC", t); } *************** layout_class_type (tree t, tree *virtual *** 4936,4950 **** /* 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); } ! /* 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; --- 4841,4860 ---- /* Warn about bases that can't be talked about due to ambiguity. */ warn_about_ambiguous_bases (t); + /* Now that we're done with layout, give the base fields the real types. */ + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + if (DECL_ARTIFICIAL (field) && IS_FAKE_BASE_TYPE (TREE_TYPE (field))) + TREE_TYPE (field) = TYPE_CONTEXT (TREE_TYPE (field)); + /* Clean up. */ splay_tree_delete (empty_base_offsets); } ! /* Determine the "key method" for the class type indicated by TYPE, ! and set CLASSTYPE_KEY_METHOD accordingly. */ ! void ! determine_key_method (tree type) { tree method; *************** key_method (tree type) *** 4952,4967 **** || processing_template_decl || 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)) ! return method; ! return NULL_TREE; } /* Perform processing required when the definition of T (a class type) --- 4862,4884 ---- || processing_template_decl || CLASSTYPE_TEMPLATE_INSTANTIATION (type) || CLASSTYPE_INTERFACE_KNOWN (type)) ! return; + /* The key method is the first non-pure virtual function that is not + inline at the point of class definition. On some targets the + key function may not be inline; those targets should not call + this function until the end of the translation unit. */ 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)) ! { ! CLASSTYPE_KEY_METHOD (type) = method; ! break; ! } ! return; } /* Perform processing required when the definition of T (a class type) *************** finish_struct_1 (tree t) *** 4974,4987 **** /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */ tree virtuals = NULL_TREE; int n_fields = 0; - tree vfield; if (COMPLETE_TYPE_P (t)) { ! if (IS_AGGR_TYPE (t)) ! error ("redefinition of `%#T'", t); ! else ! abort (); popclass (); return; } --- 4891,4901 ---- /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */ tree virtuals = NULL_TREE; int n_fields = 0; if (COMPLETE_TYPE_P (t)) { ! gcc_assert (IS_AGGR_TYPE (t)); ! error ("redefinition of %q#T", t); popclass (); return; } *************** finish_struct_1 (tree t) *** 5006,5012 **** /* 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. */ --- 4920,4935 ---- /* Find the key method. */ if (TYPE_CONTAINS_VPTR_P (t)) { ! /* The Itanium C++ ABI permits the key method to be chosen when ! the class is defined -- even though the key method so ! selected may later turn out to be an inline function. On ! some systems (such as ARM Symbian OS) the key method cannot ! be determined until the end of the translation unit. On such ! systems, we leave CLASSTYPE_KEY_METHOD set to NULL, which ! will cause the class to be added to KEYED_CLASSES. Then, in ! finish_file we will determine the key method. */ ! if (targetm.cxx.key_method_may_be_inline ()) ! determine_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. */ *************** finish_struct_1 (tree t) *** 5021,5056 **** needs a mode. */ compute_record_mode (CLASSTYPE_AS_BASE (t)); - /* Make sure that we get our own copy of the vfield FIELD_DECL. */ - vfield = TYPE_VFIELD (t); - if (vfield && CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - { - tree primary = CLASSTYPE_PRIMARY_BINFO (t); - - my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield), - BINFO_TYPE (primary)), - 20010726); - /* 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)), - 20010726); - - vfield = copy_decl (vfield); - DECL_FIELD_CONTEXT (vfield) = t; - TYPE_VFIELD (t) = vfield; - } - else - my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726); - virtuals = modify_all_vtables (t, nreverse (virtuals)); - /* If we created a new vtbl pointer for this class, add it to the - list. */ - if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - CLASSTYPE_VFIELDS (t) - = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t)); - /* If necessary, create the primary vtable for this class. */ if (virtuals || TYPE_CONTAINS_VPTR_P (t)) { --- 4944,4951 ---- *************** finish_struct_1 (tree t) *** 5068,5082 **** int vindex; tree fn; ! if (TYPE_BINFO_VTABLE (t)) ! my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)), ! 20000116); if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) ! my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE, ! 20000116); /* 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)); --- 4963,4976 ---- int vindex; tree fn; ! if (BINFO_VTABLE (TYPE_BINFO (t))) ! gcc_assert (DECL_VIRTUAL_P (BINFO_VTABLE (TYPE_BINFO (t)))); if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) ! gcc_assert (BINFO_VIRTUALS (TYPE_BINFO (t)) == NULL_TREE); /* Add entries for virtual functions introduced by this class. */ ! BINFO_VIRTUALS (TYPE_BINFO (t)) ! = chainon (BINFO_VIRTUALS (TYPE_BINFO (t)), virtuals); /* Set DECL_VINDEX for all functions declared in this class. */ for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t)); *************** finish_struct_1 (tree t) *** 5093,5099 **** thunk base function. */ DECL_VINDEX (fndecl) = NULL_TREE; else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) ! DECL_VINDEX (fndecl) = build_shared_int_cst (vindex); } } --- 4987,4993 ---- thunk base function. */ DECL_VINDEX (fndecl) = NULL_TREE; else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) ! DECL_VINDEX (fndecl) = build_int_cst (NULL_TREE, vindex); } } *************** finish_struct_1 (tree t) *** 5116,5123 **** n_fields = count_fields (TYPE_FIELDS (t)); if (n_fields > 7) { ! struct sorted_fields_type *field_vec = ggc_alloc (sizeof (struct sorted_fields_type) ! + n_fields * sizeof (tree)); field_vec->len = n_fields; add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0); qsort (field_vec->elts, n_fields, sizeof (tree), --- 5010,5018 ---- n_fields = count_fields (TYPE_FIELDS (t)); if (n_fields > 7) { ! struct sorted_fields_type *field_vec = GGC_NEWVAR ! (struct sorted_fields_type, ! sizeof (struct sorted_fields_type) + n_fields * sizeof (tree)); field_vec->len = n_fields; add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0); qsort (field_vec->elts, n_fields, sizeof (tree), *************** finish_struct_1 (tree t) *** 5127,5145 **** DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec; } - if (TYPE_HAS_CONSTRUCTOR (t)) - { - tree vfields = CLASSTYPE_VFIELDS (t); - - 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 the base types we marked. */ finish_vtbls (t); --- 5022,5027 ---- *************** finish_struct_1 (tree t) *** 5147,5155 **** /* Build the VTT for T. */ build_vtt (t); ! if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t) ! && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE) ! warning ("`%#T' has virtual functions but non-virtual destructor", t); complete_vars (t); --- 5029,5053 ---- /* Build the VTT for T. */ build_vtt (t); ! /* This warning does not make sense for Java classes, since they ! cannot have destructors. */ ! if (!TYPE_FOR_JAVA (t) && warn_nonvdtor && TYPE_POLYMORPHIC_P (t)) ! { ! tree dtor; ! ! dtor = CLASSTYPE_DESTRUCTORS (t); ! /* Warn only if the dtor is non-private or the class has ! friends. */ ! if (/* An implicitly declared destructor is always public. And, ! if it were virtual, we would have created it by now. */ ! !dtor ! || (!DECL_VINDEX (dtor) ! && (!TREE_PRIVATE (dtor) ! || CLASSTYPE_FRIEND_CLASSES (t) ! || DECL_FRIENDLIST (TYPE_MAIN_DECL (t))))) ! warning ("%q#T has virtual functions but non-virtual destructor", ! t); ! } complete_vars (t); *************** finish_struct (tree t, tree attributes) *** 5215,5222 **** --- 5113,5136 ---- if (processing_template_decl) { + tree x; + finish_struct_methods (t); TYPE_SIZE (t) = bitsize_zero_node; + TYPE_SIZE_UNIT (t) = size_zero_node; + + /* We need to emit an error message if this type was used as a parameter + and it is an abstract type, even if it is a template. We construct + a simple CLASSTYPE_PURE_VIRTUALS list without taking bases into + account and we call complete_vars with this type, which will check + the PARM_DECLS. Note that while the type is being defined, + CLASSTYPE_PURE_VIRTUALS contains the list of the inline friends + (see CLASSTYPE_INLINE_FRIENDS) so we need to clear it. */ + CLASSTYPE_PURE_VIRTUALS (t) = NULL; + for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) + if (DECL_PURE_VIRTUAL_P (x)) + VEC_safe_push (tree, CLASSTYPE_PURE_VIRTUALS (t), x); + complete_vars (t); } else finish_struct_1 (t); *************** fixed_type_or_null (tree instance, int* *** 5276,5284 **** } return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp); - case RTL_EXPR: - return NULL_TREE; - case PLUS_EXPR: case MINUS_EXPR: if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) --- 5190,5195 ---- *************** fixed_type_or_null (tree instance, int* *** 5293,5303 **** return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp); case ADDR_EXPR: if (nonnull) ! *nonnull = 1; ! return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp); case COMPONENT_REF: return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp); case VAR_DECL: --- 5204,5226 ---- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp); case ADDR_EXPR: + instance = TREE_OPERAND (instance, 0); if (nonnull) ! { ! /* Just because we see an ADDR_EXPR doesn't mean we're dealing ! with a real object -- given &p->f, p can still be null. */ ! tree t = get_base_address (instance); ! /* ??? Probably should check DECL_WEAK here. */ ! if (t && DECL_P (t)) ! *nonnull = 1; ! } ! return fixed_type_or_null (instance, nonnull, cdtorp); case COMPONENT_REF: + /* If this component is really a base class reference, then the field + itself isn't definitive. */ + if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1))) + return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp); return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp); case VAR_DECL: *************** init_class_processing (void) *** 5407,5412 **** --- 5330,5355 ---- ridpointers[(int) RID_PROTECTED] = access_protected_node; } + /* Restore the cached PREVIOUS_CLASS_LEVEL. */ + + static void + restore_class_cache (void) + { + tree type; + + /* We are re-entering the same class we just left, so we don't + have to search the whole inheritance matrix to find all the + decls to bind again. Instead, we install the cached + class_shadowed list and walk through it binding names. */ + push_binding_level (previous_class_level); + class_binding_level = previous_class_level; + /* Restore IDENTIFIER_TYPE_VALUE. */ + for (type = class_binding_level->type_shadowed; + type; + type = TREE_CHAIN (type)) + SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (type), TREE_TYPE (type)); + } + /* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE as appropriate for TYPE. *************** init_class_processing (void) *** 5414,5425 **** nodes of local TYPE_DECLs in the TREE_TYPE field of the name. For multiple inheritance, we perform a two-pass depth-first search ! of the type lattice. The first pass performs a pre-order search, ! marking types after the type has had its fields installed in ! the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely ! unmarks the marked types. If a field or member function name ! appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of ! that name becomes `error_mark_node'. */ void pushclass (tree type) --- 5357,5363 ---- nodes of local TYPE_DECLs in the TREE_TYPE field of the name. For multiple inheritance, we perform a two-pass depth-first search ! of the type lattice. */ void pushclass (tree type) *************** pushclass (tree type) *** 5455,5533 **** ? access_private_node : access_public_node); ! if (previous_class_type != NULL_TREE ! && (type != previous_class_type ! || !COMPLETE_TYPE_P (previous_class_type)) && current_class_depth == 1) { /* Forcibly remove any old class remnants. */ invalidate_class_lookup_cache (); } ! /* If we're about to enter a nested class, clear ! IDENTIFIER_CLASS_VALUE for the enclosing classes. */ ! if (current_class_depth > 1) ! clear_identifier_class_values (); ! ! pushlevel_class (); ! ! if (type != previous_class_type || current_class_depth > 1) ! { ! push_class_decls (type); ! if (CLASSTYPE_TEMPLATE_INFO (type) && !CLASSTYPE_USE_TEMPLATE (type)) ! { ! /* If we are entering the scope of a template declaration (not a ! specialization), we need to push all the using decls with ! dependent scope too. */ ! tree fields; ! ! for (fields = TYPE_FIELDS (type); ! fields; fields = TREE_CHAIN (fields)) ! if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields)) ! pushdecl_class_level (fields); ! } ! } else ! { ! tree item; ! ! /* We are re-entering the same class we just left, so we don't ! have to search the whole inheritance matrix to find all the ! decls to bind again. Instead, we install the cached ! class_shadowed list, and walk through it binding names and ! setting up IDENTIFIER_TYPE_VALUEs. */ ! set_class_shadows (previous_class_values); ! for (item = previous_class_values; item; item = TREE_CHAIN (item)) ! { ! tree id = TREE_PURPOSE (item); ! tree decl = TREE_TYPE (item); ! ! push_class_binding (id, decl); ! if (TREE_CODE (decl) == TYPE_DECL) ! set_identifier_type_value (id, decl); ! } ! unuse_fields (type); ! } ! ! cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type)); } ! /* When we exit a toplevel class scope, we save the ! IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we ! reenter the class. Here, we've entered some other class, so we ! must invalidate our cache. */ void invalidate_class_lookup_cache (void) { ! tree t; ! ! /* The IDENTIFIER_CLASS_VALUEs are no longer valid. */ ! for (t = previous_class_values; t; t = TREE_CHAIN (t)) ! IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE; ! ! previous_class_values = NULL_TREE; ! previous_class_type = NULL_TREE; } /* Get out of the current class scope. If we were in a class scope --- 5393,5422 ---- ? access_private_node : access_public_node); ! if (previous_class_level ! && type != previous_class_level->this_entity && current_class_depth == 1) { /* Forcibly remove any old class remnants. */ invalidate_class_lookup_cache (); } ! if (!previous_class_level ! || type != previous_class_level->this_entity ! || current_class_depth > 1) ! pushlevel_class (); else ! restore_class_cache (); } ! /* When we exit a toplevel class scope, we save its binding level so ! that we can restore it quickly. Here, we've entered some other ! class, so we must invalidate our cache. */ void invalidate_class_lookup_cache (void) { ! previous_class_level = NULL; } /* Get out of the current class scope. If we were in a class scope *************** void *** 5537,5543 **** popclass (void) { poplevel_class (); - pop_class_decls (); current_class_depth--; current_class_name = current_class_stack[current_class_depth].name; --- 5426,5431 ---- *************** push_lang_context (tree name) *** 5670,5676 **** current_lang_name = name; } else ! error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name)); } /* Get out of the current language scope. */ --- 5558,5564 ---- current_lang_name = name; } else ! error ("language string %<\"%E\"%> not recognized", name); } /* Get out of the current language scope. */ *************** resolve_address_of_overloaded_function ( *** 5736,5746 **** /* By the time we get here, we should be seeing only real pointer-to-member types, not the internal POINTER_TYPE to METHOD_TYPE representation. */ ! my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE ! && (TREE_CODE (TREE_TYPE (target_type)) ! == METHOD_TYPE)), 0); ! my_friendly_assert (is_overloaded_fn (overload), 20030910); /* Check that the TARGET_TYPE is reasonable. */ if (TYPE_PTRFN_P (target_type)) --- 5624,5633 ---- /* By the time we get here, we should be seeing only real pointer-to-member types, not the internal POINTER_TYPE to METHOD_TYPE representation. */ ! gcc_assert (TREE_CODE (target_type) != POINTER_TYPE ! || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE); ! gcc_assert (is_overloaded_fn (overload)); /* Check that the TARGET_TYPE is reasonable. */ if (TYPE_PTRFN_P (target_type)) *************** resolve_address_of_overloaded_function ( *** 5758,5766 **** else { if (flags & tf_error) ! error ("\ ! cannot resolve overloaded function `%D' based on conversion to type `%T'", ! DECL_NAME (OVL_FUNCTION (overload)), target_type); return error_mark_node; } --- 5645,5653 ---- else { if (flags & tf_error) ! error ("cannot resolve overloaded function %qD based on" ! " conversion to type %qT", ! DECL_NAME (OVL_FUNCTION (overload)), target_type); return error_mark_node; } *************** cannot resolve overloaded function `%D' *** 5883,5891 **** /* There were *no* matches. */ if (flags & tf_error) { ! error ("no matches converting function `%D' to type `%#T'", ! DECL_NAME (OVL_FUNCTION (overload)), ! target_type); /* print_candidates expects a chain with the functions in TREE_VALUE slots, so we cons one up here (we're losing anyway, --- 5770,5778 ---- /* There were *no* matches. */ if (flags & tf_error) { ! error ("no matches converting function %qD to type %q#T", ! DECL_NAME (OVL_FUNCTION (overload)), ! target_type); /* print_candidates expects a chain with the functions in TREE_VALUE slots, so we cons one up here (we're losing anyway, *************** cannot resolve overloaded function `%D' *** 5906,5912 **** { tree match; ! error ("converting overloaded function `%D' to type `%#T' is ambiguous", DECL_NAME (OVL_FUNCTION (overload)), target_type); --- 5793,5799 ---- { tree match; ! error ("converting overloaded function %qD to type %q#T is ambiguous", DECL_NAME (OVL_FUNCTION (overload)), target_type); *************** cannot resolve overloaded function `%D' *** 5932,5941 **** if (!(flags & tf_error)) return error_mark_node; ! pedwarn ("assuming pointer to member `%D'", fn); if (!explained) { ! pedwarn ("(a pointer to member can only be formed with `&%E')", fn); explained = 1; } } --- 5819,5828 ---- if (!(flags & tf_error)) return error_mark_node; ! pedwarn ("assuming pointer to member %qD", fn); if (!explained) { ! pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn); explained = 1; } } *************** instantiate_type (tree lhstype, tree rhs *** 5997,6003 **** else { if (flags & tf_error) ! error ("argument of type `%T' does not match `%T'", TREE_TYPE (rhs), lhstype); return error_mark_node; } --- 5884,5890 ---- else { if (flags & tf_error) ! error ("argument of type %qT does not match %qT", TREE_TYPE (rhs), lhstype); return error_mark_node; } *************** instantiate_type (tree lhstype, tree rhs *** 6006,6011 **** --- 5893,5907 ---- if (TREE_CODE (rhs) == BASELINK) rhs = BASELINK_FUNCTIONS (rhs); + /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot + deduce any type information. */ + if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR) + { + if (flags & tf_error) + error ("not enough type information"); + return error_mark_node; + } + /* We don't overwrite rhs if it is an overloaded function. Copying it would destroy the tree link. */ if (TREE_CODE (rhs) != OVERLOAD) *************** instantiate_type (tree lhstype, tree rhs *** 6022,6030 **** case CONVERT_EXPR: case SAVE_EXPR: case CONSTRUCTOR: ! case BUFFER_REF: ! abort (); ! return error_mark_node; case INDIRECT_REF: case ARRAY_REF: --- 5918,5924 ---- case CONVERT_EXPR: case SAVE_EXPR: case CONSTRUCTOR: ! gcc_unreachable (); case INDIRECT_REF: case ARRAY_REF: *************** instantiate_type (tree lhstype, tree rhs *** 6048,6061 **** case COMPONENT_REF: { ! tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); ! if (addr != error_mark_node && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0))) /* Do not lose object's side effects. */ ! addr = build (COMPOUND_EXPR, TREE_TYPE (addr), ! TREE_OPERAND (rhs, 0), addr); ! return addr; } case OFFSET_REF: --- 5942,5956 ---- case COMPONENT_REF: { ! tree member = TREE_OPERAND (rhs, 1); ! member = instantiate_type (lhstype, member, flags); ! if (member != error_mark_node && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0))) /* Do not lose object's side effects. */ ! return build2 (COMPOUND_EXPR, TREE_TYPE (member), ! TREE_OPERAND (rhs, 0), member); ! return member; } case OFFSET_REF: *************** instantiate_type (tree lhstype, tree rhs *** 6065,6071 **** /* This can happen if we are forming a pointer-to-member for a member template. */ ! my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0); /* Fall through. */ --- 5960,5966 ---- /* This can happen if we are forming a pointer-to-member for a member template. */ ! gcc_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR); /* Fall through. */ *************** instantiate_type (tree lhstype, tree rhs *** 6087,6102 **** /*template_only=*/false, /*explicit_targs=*/NULL_TREE); - case TREE_LIST: - /* Now we should have a baselink. */ - my_friendly_assert (BASELINK_P (rhs), 990412); - - return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags); - case CALL_EXPR: /* This is too hard for now. */ ! abort (); ! return error_mark_node; case PLUS_EXPR: case MINUS_EXPR: --- 5982,5990 ---- /*template_only=*/false, /*explicit_targs=*/NULL_TREE); case CALL_EXPR: /* This is too hard for now. */ ! gcc_unreachable (); case PLUS_EXPR: case MINUS_EXPR: *************** instantiate_type (tree lhstype, tree rhs *** 6200,6216 **** return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); } - case ENTRY_VALUE_EXPR: - abort (); - return error_mark_node; case ERROR_MARK: return error_mark_node; default: ! abort (); ! return error_mark_node; } } /* Return the name of the virtual function pointer field --- 6088,6101 ---- return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); } case ERROR_MARK: return error_mark_node; default: ! gcc_unreachable (); } + return error_mark_node; } /* Return the name of the virtual function pointer field *************** instantiate_type (tree lhstype, tree rhs *** 6222,6235 **** static tree get_vfield_name (tree type) { ! tree binfo = TYPE_BINFO (type); char *buf; ! while (BINFO_BASETYPES (binfo) ! && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0))) ! && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0))) ! binfo = BINFO_BASETYPE (binfo, 0); type = BINFO_TYPE (binfo); buf = alloca (sizeof (VFIELD_NAME_FORMAT) + TYPE_NAME_LENGTH (type) + 2); sprintf (buf, VFIELD_NAME_FORMAT, --- 6107,6126 ---- static tree get_vfield_name (tree type) { ! tree binfo, base_binfo; char *buf; ! for (binfo = TYPE_BINFO (type); ! BINFO_N_BASE_BINFOS (binfo); ! binfo = base_binfo) ! { ! base_binfo = BINFO_BASE_BINFO (binfo, 0); + if (BINFO_VIRTUAL_P (base_binfo) + || !TYPE_CONTAINS_VPTR_P (BINFO_TYPE (base_binfo))) + break; + } + type = BINFO_TYPE (binfo); buf = alloca (sizeof (VFIELD_NAME_FORMAT) + TYPE_NAME_LENGTH (type) + 2); sprintf (buf, VFIELD_NAME_FORMAT, *************** contains_empty_class_p (tree type) *** 6309,6318 **** 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 --- 6200,6212 ---- if (CLASS_TYPE_P (type)) { tree field; + tree binfo; + tree base_binfo; int i; ! for (binfo = TYPE_BINFO (type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) ! if (contains_empty_class_p (BINFO_TYPE (base_binfo))) return true; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL *************** contains_empty_class_p (tree type) *** 6325,6359 **** return false; } - /* Find the enclosing class of the given NODE. NODE can be a *_DECL or - a *_TYPE node. NODE can also be a local class. */ - - tree - get_enclosing_class (tree type) - { - tree node = type; - - while (node && TREE_CODE (node) != NAMESPACE_DECL) - { - switch (TREE_CODE_CLASS (TREE_CODE (node))) - { - case 'd': - node = DECL_CONTEXT (node); - break; - - case 't': - if (node != type) - return node; - node = TYPE_CONTEXT (node); - break; - - default: - abort (); - } - } - return NULL_TREE; - } - /* Note that NAME was looked up while the current class was being defined and that the result of that lookup was DECL. */ --- 6219,6224 ---- *************** maybe_note_name_used_in_class (tree name *** 6363,6374 **** splay_tree names_used; /* If we're not defining a class, there's nothing to do. */ ! if (innermost_scope_kind() != sk_class) return; /* If there's already a binding for this NAME, then we don't have anything to worry about. */ ! if (IDENTIFIER_CLASS_VALUE (name)) return; if (!current_class_stack[current_class_depth - 1].names_used) --- 6228,6241 ---- splay_tree names_used; /* If we're not defining a class, there's nothing to do. */ ! if (!(innermost_scope_kind() == sk_class ! && TYPE_BEING_DEFINED (current_class_type))) return; /* If there's already a binding for this NAME, then we don't have anything to worry about. */ ! if (lookup_member (current_class_type, name, ! /*protect=*/0, /*want_type=*/false)) return; if (!current_class_stack[current_class_depth - 1].names_used) *************** note_name_declared_in_class (tree name, *** 6404,6411 **** A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. */ ! error ("declaration of `%#D'", decl); ! cp_error_at ("changes meaning of `%D' from `%+#D'", DECL_NAME (OVL_CURRENT (decl)), (tree) n->value); } --- 6271,6278 ---- A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. */ ! error ("declaration of %q#D", decl); ! cp_error_at ("changes meaning of %qD from %q+#D", DECL_NAME (OVL_CURRENT (decl)), (tree) n->value); } *************** get_vtbl_decl_for_binfo (tree binfo) *** 6423,6434 **** decl = BINFO_VTABLE (binfo); if (decl && TREE_CODE (decl) == PLUS_EXPR) { ! my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR, ! 2000403); decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0); } if (decl) ! my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403); return decl; } --- 6290,6300 ---- decl = BINFO_VTABLE (binfo); if (decl && TREE_CODE (decl) == PLUS_EXPR) { ! gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR); decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0); } if (decl) ! gcc_assert (TREE_CODE (decl) == VAR_DECL); return decl; } *************** dump_class_hierarchy_r (FILE *stream, *** 6476,6486 **** int indent) { int indented = 0; ! tree base_binfos; indented = maybe_indent_hierarchy (stream, indent, 0); fprintf (stream, "%s (0x%lx) ", ! type_as_string (binfo, TFF_PLAIN_IDENTIFIER), (unsigned long) binfo); if (binfo != igo) { --- 6342,6353 ---- int indent) { int indented = 0; ! tree base_binfo; ! int i; indented = maybe_indent_hierarchy (stream, indent, 0); fprintf (stream, "%s (0x%lx) ", ! type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER), (unsigned long) binfo); if (binfo != igo) { *************** dump_class_hierarchy_r (FILE *stream, *** 6495,6512 **** fprintf (stream, " empty"); else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo))) fprintf (stream, " nearly-empty"); ! if (TREE_VIA_VIRTUAL (binfo)) fprintf (stream, " virtual"); fprintf (stream, "\n"); indented = 0; ! if (BINFO_PRIMARY_BASE_OF (binfo)) { indented = maybe_indent_hierarchy (stream, indent + 3, indented); fprintf (stream, " primary-for %s (0x%lx)", ! type_as_string (BINFO_PRIMARY_BASE_OF (binfo), TFF_PLAIN_IDENTIFIER), ! (unsigned long)BINFO_PRIMARY_BASE_OF (binfo)); } if (BINFO_LOST_PRIMARY_P (binfo)) { --- 6362,6379 ---- fprintf (stream, " empty"); else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo))) fprintf (stream, " nearly-empty"); ! if (BINFO_VIRTUAL_P (binfo)) fprintf (stream, " virtual"); fprintf (stream, "\n"); indented = 0; ! if (BINFO_PRIMARY_P (binfo)) { indented = maybe_indent_hierarchy (stream, indent + 3, indented); fprintf (stream, " primary-for %s (0x%lx)", ! type_as_string (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)), TFF_PLAIN_IDENTIFIER), ! (unsigned long)BINFO_INHERITANCE_CHAIN (binfo)); } if (BINFO_LOST_PRIMARY_P (binfo)) { *************** dump_class_hierarchy_r (FILE *stream, *** 6552,6572 **** if (indented) fprintf (stream, "\n"); } - - base_binfos = BINFO_BASETYPES (binfo); - if (base_binfos) - { - int ix, n; - - n = TREE_VEC_LENGTH (base_binfos); - for (ix = 0; ix != n; ix++) - { - tree base_binfo = TREE_VEC_ELT (base_binfos, ix); ! igo = dump_class_hierarchy_r (stream, flags, base_binfo, ! igo, indent + 2); ! } ! } return igo; } --- 6419,6427 ---- if (indented) fprintf (stream, "\n"); } ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) ! igo = dump_class_hierarchy_r (stream, flags, base_binfo, igo, indent + 2); return igo; } *************** dump_vtable (tree t, tree binfo, tree vt *** 6647,6656 **** fprintf (stream, "%s for %s", ctor_vtbl_p ? "Construction vtable" : "Vtable", ! type_as_string (binfo, TFF_PLAIN_IDENTIFIER)); if (ctor_vtbl_p) { ! if (!TREE_VIA_VIRTUAL (binfo)) fprintf (stream, " (0x%lx instance)", (unsigned long)binfo); fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER)); } --- 6502,6511 ---- fprintf (stream, "%s for %s", ctor_vtbl_p ? "Construction vtable" : "Vtable", ! type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER)); if (ctor_vtbl_p) { ! if (!BINFO_VIRTUAL_P (binfo)) fprintf (stream, " (0x%lx instance)", (unsigned long)binfo); fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER)); } *************** finish_vtbls (tree t) *** 6740,6758 **** /* We lay out the primary and secondary vtables in one contiguous vtable. The primary vtable is first, followed by the non-virtual secondary vtables in inheritance graph order. */ ! list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE); accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t), TYPE_BINFO (t), t, list); /* Then come the virtual bases, also in inheritance graph order. */ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) { ! if (!TREE_VIA_VIRTUAL (vbase)) continue; accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list); } ! if (TYPE_BINFO_VTABLE (t)) initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list)); } --- 6595,6613 ---- /* We lay out the primary and secondary vtables in one contiguous vtable. The primary vtable is first, followed by the non-virtual secondary vtables in inheritance graph order. */ ! list = build_tree_list (BINFO_VTABLE (TYPE_BINFO (t)), NULL_TREE); accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t), TYPE_BINFO (t), t, list); /* Then come the virtual bases, also in inheritance graph order. */ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) { ! if (!BINFO_VIRTUAL_P (vbase)) continue; accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list); } ! if (BINFO_VTABLE (TYPE_BINFO (t))) initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list)); } *************** initialize_vtable (tree binfo, tree init *** 6765,6790 **** layout_vtable_decl (binfo, list_length (inits)); decl = get_vtbl_decl_for_binfo (binfo); ! initialize_array (decl, inits); dump_vtable (BINFO_TYPE (binfo), binfo, decl); } - /* Initialize DECL (a declaration for a namespace-scope array) with - the INITS. */ - - static void - initialize_array (tree decl, tree inits) - { - tree context; - - context = DECL_CONTEXT (decl); - DECL_CONTEXT (decl) = NULL_TREE; - DECL_INITIAL (decl) = build_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; - } - /* Build the VTT (virtual table table) for T. A class requires a VTT if it has virtual bases. --- 6620,6629 ---- layout_vtable_decl (binfo, list_length (inits)); decl = get_vtbl_decl_for_binfo (binfo); ! initialize_artificial_var (decl, inits); dump_vtable (BINFO_TYPE (binfo), binfo, decl); } /* Build the VTT (virtual table table) for T. A class requires a VTT if it has virtual bases. *************** build_vtt (tree t) *** 6821,6827 **** /* Now, build the VTT object itself. */ vtt = build_vtable (t, get_vtt_name (t), type); ! 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; --- 6660,6666 ---- /* Now, build the VTT object itself. */ vtt = build_vtable (t, get_vtt_name (t), type); ! initialize_artificial_var (vtt, inits); /* Add the VTT to the vtables list. */ TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t)); TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt; *************** binfo_ctor_vtable (tree binfo) *** 6844,6850 **** vt = BINFO_VTABLE (binfo); if (TREE_CODE (vt) == TREE_LIST) vt = TREE_VALUE (vt); ! if (TREE_CODE (vt) == TREE_VEC) binfo = vt; else break; --- 6683,6689 ---- vt = BINFO_VTABLE (binfo); if (TREE_CODE (vt) == TREE_LIST) vt = TREE_VALUE (vt); ! if (TREE_CODE (vt) == TREE_BINFO) binfo = vt; else break; *************** binfo_ctor_vtable (tree binfo) *** 6853,6858 **** --- 6692,6713 ---- return vt; } + /* Data for secondary VTT initialization. */ + typedef struct secondary_vptr_vtt_init_data_s + { + /* Is this the primary VTT? */ + bool top_level_p; + + /* Current index into the VTT. */ + tree index; + + /* TREE_LIST of initializers built up. */ + tree inits; + + /* The type being constructed by this secondary VTT. */ + tree type_being_constructed; + } secondary_vptr_vtt_init_data; + /* Recursively build the VTT-initializer for BINFO (which is in the hierarchy dominated by T). INITS points to the end of the initializer list to date. INDEX is the VTT index where the next element will be *************** binfo_ctor_vtable (tree binfo) *** 6862,6877 **** vtables for the BINFO-in-T variant. */ static tree * ! build_vtt_inits (tree binfo, tree t, tree* inits, tree* index) { int i; tree b; tree init; tree secondary_vptrs; ! int top_level_p = same_type_p (TREE_TYPE (binfo), t); /* We only need VTTs for subobjects with virtual bases. */ ! if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) return inits; /* We need to use a construction vtable if this is not the primary --- 6717,6733 ---- vtables for the BINFO-in-T variant. */ static tree * ! build_vtt_inits (tree binfo, tree t, tree *inits, tree *index) { int i; tree b; tree init; tree secondary_vptrs; ! secondary_vptr_vtt_init_data data; ! int top_level_p = SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t); /* We only need VTTs for subobjects with virtual bases. */ ! if (!CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo))) return inits; /* We need to use a construction vtable if this is not the primary *************** build_vtt_inits (tree binfo, tree t, tre *** 6890,7065 **** inits = &TREE_CHAIN (*inits); if (top_level_p) { ! my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129); BINFO_VPTR_INDEX (binfo) = *index; } *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node)); /* Recursively add the secondary VTTs for non-virtual bases. */ ! for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) ! { ! b = BINFO_BASETYPE (binfo, i); ! if (!TREE_VIA_VIRTUAL (b)) ! inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, ! inits, index); ! } /* Add secondary virtual pointers for all subobjects of BINFO with either virtual bases or reachable along a virtual path, except subobjects that are non-virtual primary bases. */ ! secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo)); ! TREE_TYPE (secondary_vptrs) = *index; ! VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p; ! VTT_MARKED_BINFO_P (secondary_vptrs) = 0; ! dfs_walk_real (binfo, ! dfs_build_secondary_vptr_vtt_inits, ! NULL, ! dfs_ctor_vtable_bases_queue_p, ! secondary_vptrs); ! VTT_MARKED_BINFO_P (secondary_vptrs) = 1; ! dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p, ! secondary_vptrs); ! *index = TREE_TYPE (secondary_vptrs); /* The secondary vptrs come back in reverse order. After we reverse them, and add the INITS, the last init will be the first element of the chain. */ ! secondary_vptrs = TREE_VALUE (secondary_vptrs); if (secondary_vptrs) { *inits = nreverse (secondary_vptrs); inits = &TREE_CHAIN (secondary_vptrs); ! my_friendly_assert (*inits == NULL_TREE, 20000517); } - /* Add the secondary VTTs for virtual bases. */ if (top_level_p) for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b)) { ! if (!TREE_VIA_VIRTUAL (b)) continue; inits = build_vtt_inits (b, t, inits, index); } ! ! if (!top_level_p) ! { ! tree data = tree_cons (t, binfo, NULL_TREE); ! VTT_TOP_LEVEL_P (data) = 0; ! VTT_MARKED_BINFO_P (data) = 0; ! ! dfs_walk (binfo, dfs_fixup_binfo_vtbls, ! dfs_ctor_vtable_bases_queue_p, ! data); ! } return inits; } ! /* Called from build_vtt_inits via dfs_walk. BINFO is the binfo ! for the base in most derived. DATA is a TREE_LIST who's ! TREE_CHAIN is the type of the base being ! constructed whilst this secondary vptr is live. The TREE_UNSIGNED ! flag of DATA indicates that this is a constructor vtable. The ! TREE_TOP_LEVEL flag indicates that this is the primary VTT. */ static tree ! dfs_build_secondary_vptr_vtt_inits (tree binfo, void* data) { ! tree l; ! tree t; ! tree init; ! tree index; ! int top_level_p; ! ! l = (tree) data; ! t = TREE_CHAIN (l); ! top_level_p = VTT_TOP_LEVEL_P (l); ! ! BINFO_MARKED (binfo) = 1; /* We don't care about bases that don't have vtables. */ if (!TYPE_VFIELD (BINFO_TYPE (binfo))) ! return NULL_TREE; ! /* We're only interested in proper subobjects of T. */ ! if (same_type_p (BINFO_TYPE (binfo), t)) return NULL_TREE; /* We're not interested in non-virtual primary bases. */ ! if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo)) ! return NULL_TREE; ! ! /* If BINFO has virtual bases or is reachable via a virtual path ! from T, it'll have a secondary vptr. */ ! if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)) ! && !binfo_via_virtual (binfo, t)) return NULL_TREE; ! /* Record the index where this secondary vptr can be found. */ ! index = TREE_TYPE (l); ! if (top_level_p) { ! my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129); ! BINFO_VPTR_INDEX (binfo) = index; ! } ! TREE_TYPE (l) = size_binop (PLUS_EXPR, index, ! TYPE_SIZE_UNIT (ptr_type_node)); ! /* Add the initializer for the secondary vptr itself. */ ! if (top_level_p && TREE_VIA_VIRTUAL (binfo)) ! { ! /* 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. */ ! while (BINFO_PRIMARY_BASE_OF (binfo)) ! binfo = BINFO_PRIMARY_BASE_OF (binfo); } ! init = binfo_ctor_vtable (binfo); ! TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l)); ! ! return NULL_TREE; ! } ! /* dfs_walk_real predicate for building vtables. DATA is a TREE_LIST, ! VTT_MARKED_BINFO_P indicates whether marked or unmarked bases ! should be walked. TREE_PURPOSE is the TREE_TYPE that dominates the ! hierarchy. */ ! static tree ! dfs_ctor_vtable_bases_queue_p (tree derived, int ix, ! void* data) ! { ! tree binfo = BINFO_BASETYPE (derived, ix); ! ! if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data)) ! return NULL_TREE; ! return binfo; } ! /* Called from build_vtt_inits via dfs_walk. After building constructor ! vtables and generating the sub-vtt from them, we need to restore the ! BINFO_VTABLES that were scribbled on. DATA is a TREE_LIST whose ! TREE_VALUE is the TREE_TYPE of the base whose sub vtt was generated. */ static tree dfs_fixup_binfo_vtbls (tree binfo, void* data) { ! BINFO_MARKED (binfo) = 0; ! /* We don't care about bases that don't have vtables. */ ! if (!TYPE_VFIELD (BINFO_TYPE (binfo))) return NULL_TREE; ! /* If we scribbled the construction vtable vptr into BINFO, clear it out now. */ ! if (BINFO_VTABLE (binfo) ! && TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST ! && (TREE_PURPOSE (BINFO_VTABLE (binfo)) ! == TREE_VALUE ((tree) data))) ! BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo)); return NULL_TREE; } --- 6746,6879 ---- inits = &TREE_CHAIN (*inits); if (top_level_p) { ! gcc_assert (!BINFO_VPTR_INDEX (binfo)); BINFO_VPTR_INDEX (binfo) = *index; } *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node)); /* Recursively add the secondary VTTs for non-virtual bases. */ ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, b); ++i) ! if (!BINFO_VIRTUAL_P (b)) ! inits = build_vtt_inits (b, t, inits, index); /* Add secondary virtual pointers for all subobjects of BINFO with either virtual bases or reachable along a virtual path, except subobjects that are non-virtual primary bases. */ ! data.top_level_p = top_level_p; ! data.index = *index; ! data.inits = NULL; ! data.type_being_constructed = BINFO_TYPE (binfo); ! dfs_walk_once (binfo, dfs_build_secondary_vptr_vtt_inits, NULL, &data); ! *index = data.index; /* The secondary vptrs come back in reverse order. After we reverse them, and add the INITS, the last init will be the first element of the chain. */ ! secondary_vptrs = data.inits; if (secondary_vptrs) { *inits = nreverse (secondary_vptrs); inits = &TREE_CHAIN (secondary_vptrs); ! gcc_assert (*inits == NULL_TREE); } if (top_level_p) + /* Add the secondary VTTs for virtual bases in inheritance graph + order. */ for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b)) { ! if (!BINFO_VIRTUAL_P (b)) continue; inits = build_vtt_inits (b, t, inits, index); } ! else ! /* Remove the ctor vtables we created. */ ! dfs_walk_all (binfo, dfs_fixup_binfo_vtbls, NULL, binfo); return inits; } ! /* Called from build_vtt_inits via dfs_walk. BINFO is the binfo for the base ! in most derived. DATA is a SECONDARY_VPTR_VTT_INIT_DATA structure. */ static tree ! dfs_build_secondary_vptr_vtt_inits (tree binfo, void *data_) { ! secondary_vptr_vtt_init_data *data = (secondary_vptr_vtt_init_data *)data_; /* We don't care about bases that don't have vtables. */ if (!TYPE_VFIELD (BINFO_TYPE (binfo))) ! return dfs_skip_bases; ! /* We're only interested in proper subobjects of the type being ! constructed. */ ! if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), data->type_being_constructed)) return NULL_TREE; + /* We're only interested in bases with virtual bases or reachable + via a virtual path from the type being constructed. */ + if (!(CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo)) + || binfo_via_virtual (binfo, data->type_being_constructed))) + return dfs_skip_bases; + /* We're not interested in non-virtual primary bases. */ ! if (!BINFO_VIRTUAL_P (binfo) && BINFO_PRIMARY_P (binfo)) return NULL_TREE; ! /* Record the index where this secondary vptr can be found. */ ! if (data->top_level_p) { ! gcc_assert (!BINFO_VPTR_INDEX (binfo)); ! BINFO_VPTR_INDEX (binfo) = data->index; ! if (BINFO_VIRTUAL_P (binfo)) ! { ! /* It's a primary virtual base, and this is not a ! construction vtable. Find the base this is primary of in ! the inheritance graph, and use that base's vtable ! now. */ ! while (BINFO_PRIMARY_P (binfo)) ! binfo = BINFO_INHERITANCE_CHAIN (binfo); ! } } ! ! /* Add the initializer for the secondary vptr itself. */ ! data->inits = tree_cons (NULL_TREE, binfo_ctor_vtable (binfo), data->inits); ! /* Advance the vtt index. */ ! data->index = size_binop (PLUS_EXPR, data->index, ! TYPE_SIZE_UNIT (ptr_type_node)); ! return NULL_TREE; } ! /* Called from build_vtt_inits via dfs_walk. After building ! constructor vtables and generating the sub-vtt from them, we need ! to restore the BINFO_VTABLES that were scribbled on. DATA is the ! binfo of the base whose sub vtt was generated. */ static tree dfs_fixup_binfo_vtbls (tree binfo, void* data) { ! tree vtable = BINFO_VTABLE (binfo); ! if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) ! /* If this class has no vtable, none of its bases do. */ ! return dfs_skip_bases; ! ! if (!vtable) ! /* This might be a primary base, so have no vtable in this ! hierarchy. */ return NULL_TREE; ! /* If we scribbled the construction vtable vptr into BINFO, clear it out now. */ ! if (TREE_CODE (vtable) == TREE_LIST ! && (TREE_PURPOSE (vtable) == (tree) data)) ! BINFO_VTABLE (binfo) = TREE_CHAIN (vtable); return NULL_TREE; } *************** build_ctor_vtbl_group (tree binfo, tree *** 7082,7092 **** if (IDENTIFIER_GLOBAL_VALUE (id)) return; ! my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124); /* Build a version of VTBL (with the wrong type) for use in constructing the addresses of secondary vtables in the construction vtable group. */ vtbl = build_vtable (t, id, ptr_type_node); list = build_tree_list (vtbl, NULL_TREE); accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)), binfo, t, list); --- 6896,6907 ---- if (IDENTIFIER_GLOBAL_VALUE (id)) return; ! gcc_assert (!SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t)); /* Build a version of VTBL (with the wrong type) for use in constructing the addresses of secondary vtables in the construction vtable group. */ vtbl = build_vtable (t, id, ptr_type_node); + DECL_CONSTRUCTION_VTABLE_P (vtbl) = 1; list = build_tree_list (vtbl, NULL_TREE); accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)), binfo, t, list); *************** build_ctor_vtbl_group (tree binfo, tree *** 7099,7105 **** { tree b; ! if (!TREE_VIA_VIRTUAL (vbase)) continue; b = copied_binfo (vbase, binfo); --- 6914,6920 ---- { tree b; ! if (!BINFO_VIRTUAL_P (vbase)) continue; b = copied_binfo (vbase, binfo); *************** build_ctor_vtbl_group (tree binfo, tree *** 7114,7120 **** /* Initialize the construction vtable. */ CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl); ! initialize_array (vtbl, inits); dump_vtable (t, binfo, vtbl); } --- 6929,6935 ---- /* Initialize the construction vtable. */ CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl); ! initialize_artificial_var (vtbl, inits); dump_vtable (t, binfo, vtbl); } *************** accumulate_vtbl_inits (tree binfo, *** 7136,7146 **** tree inits) { int i; ! int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); ! my_friendly_assert (same_type_p (BINFO_TYPE (binfo), ! BINFO_TYPE (orig_binfo)), ! 20000517); /* If it doesn't have a vptr, we don't do anything. */ if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) --- 6951,6960 ---- tree inits) { int i; ! tree base_binfo; ! int ctor_vtbl_p = !SAME_BINFO_TYPE_P (BINFO_TYPE (rtti_binfo), t); ! gcc_assert (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), BINFO_TYPE (orig_binfo))); /* If it doesn't have a vptr, we don't do anything. */ if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) *************** accumulate_vtbl_inits (tree binfo, *** 7149,7155 **** /* If we're building a construction vtable, we're not interested in subobjects that don't require construction vtables. */ if (ctor_vtbl_p ! && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)) && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo))) return; --- 6963,6969 ---- /* If we're building a construction vtable, we're not interested in subobjects that don't require construction vtables. */ if (ctor_vtbl_p ! && !CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo)) && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo))) return; *************** accumulate_vtbl_inits (tree binfo, *** 7164,7178 **** secondary vtable lies from the primary vtable. We can't use dfs_walk here because we need to iterate through bases of BINFO and RTTI_BINFO simultaneously. */ ! for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) { - tree base_binfo = BINFO_BASETYPE (binfo, i); - /* Skip virtual bases. */ ! if (TREE_VIA_VIRTUAL (base_binfo)) continue; accumulate_vtbl_inits (base_binfo, ! BINFO_BASETYPE (orig_binfo, i), rtti_binfo, t, inits); } --- 6978,6990 ---- secondary vtable lies from the primary vtable. We can't use dfs_walk here because we need to iterate through bases of BINFO and RTTI_BINFO simultaneously. */ ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { /* Skip virtual bases. */ ! if (BINFO_VIRTUAL_P (base_binfo)) continue; accumulate_vtbl_inits (base_binfo, ! BINFO_BASE_BINFO (orig_binfo, i), rtti_binfo, t, inits); } *************** dfs_accumulate_vtbl_inits (tree binfo, *** 7190,7199 **** { tree inits = NULL_TREE; tree vtbl = NULL_TREE; ! int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); if (ctor_vtbl_p ! && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo)) { /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary virtual base. If it is not the same primary in --- 7002,7011 ---- { tree inits = NULL_TREE; tree vtbl = NULL_TREE; ! int ctor_vtbl_p = !SAME_BINFO_TYPE_P (BINFO_TYPE (rtti_binfo), t); if (ctor_vtbl_p ! && BINFO_VIRTUAL_P (orig_binfo) && BINFO_PRIMARY_P (orig_binfo)) { /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary virtual base. If it is not the same primary in *************** dfs_accumulate_vtbl_inits (tree binfo, *** 7210,7240 **** RTTI_BINFO. 3) We are primary to something not a base of RTTI_BINFO. */ ! tree b = BINFO_PRIMARY_BASE_OF (binfo); tree last = NULL_TREE; /* First, look through the bases we are primary to for RTTI_BINFO or a virtual base. */ ! for (; b; b = BINFO_PRIMARY_BASE_OF (b)) { last = b; ! if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo) ! break; } /* If we run out of primary links, keep looking down our inheritance chain; we might be an indirect primary. */ ! if (b == NULL_TREE) ! for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b)) ! if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo) ! break; ! /* If we found RTTI_BINFO, this is case 1. If we found a virtual base B and it is a base of RTTI_BINFO, this is case 2. In either case, we share our vtable with LAST, i.e. the derived-most base within B of which we are a primary. */ if (b == rtti_binfo ! || (b && purpose_member (BINFO_TYPE (b), ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo))))) /* Just set our BINFO_VTABLE to point to LAST, as we may not have set LAST's BINFO_VTABLE yet. We'll extract the actual vptr in binfo_ctor_vtable after everything's been set up. */ --- 7022,7053 ---- RTTI_BINFO. 3) We are primary to something not a base of RTTI_BINFO. */ ! tree b; tree last = NULL_TREE; /* First, look through the bases we are primary to for RTTI_BINFO or a virtual base. */ ! b = binfo; ! while (BINFO_PRIMARY_P (b)) { + b = BINFO_INHERITANCE_CHAIN (b); last = b; ! if (BINFO_VIRTUAL_P (b) || b == rtti_binfo) ! goto found; } /* If we run out of primary links, keep looking down our inheritance chain; we might be an indirect primary. */ ! for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b)) ! if (BINFO_VIRTUAL_P (b) || b == rtti_binfo) ! break; ! found: ! /* If we found RTTI_BINFO, this is case 1. If we found a virtual base B and it is a base of RTTI_BINFO, this is case 2. In either case, we share our vtable with LAST, i.e. the derived-most base within B of which we are a primary. */ if (b == rtti_binfo ! || (b && binfo_for_vbase (BINFO_TYPE (b), BINFO_TYPE (rtti_binfo)))) /* Just set our BINFO_VTABLE to point to LAST, as we may not have set LAST's BINFO_VTABLE yet. We'll extract the actual vptr in binfo_ctor_vtable after everything's been set up. */ *************** dfs_accumulate_vtbl_inits (tree binfo, *** 7256,7273 **** /* Figure out the position to which the VPTR should point. */ vtbl = TREE_PURPOSE (l); ! vtbl = build1 (ADDR_EXPR, ! vtbl_ptr_type_node, ! vtbl); ! TREE_CONSTANT (vtbl) = 1; index = size_binop (PLUS_EXPR, size_int (non_fn_entries), size_int (list_length (TREE_VALUE (l)))); index = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type), index); ! vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index); ! TREE_CONSTANT (vtbl) = 1; } if (ctor_vtbl_p) --- 7069,7082 ---- /* Figure out the position to which the VPTR should point. */ vtbl = TREE_PURPOSE (l); ! vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl); index = size_binop (PLUS_EXPR, size_int (non_fn_entries), size_int (list_length (TREE_VALUE (l)))); index = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type), index); ! vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index); } if (ctor_vtbl_p) *************** dfs_accumulate_vtbl_inits (tree binfo, *** 7275,7281 **** So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will straighten this out. */ BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo)); ! else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo)) inits = NULL_TREE; else /* For an ordinary vtable, set BINFO_VTABLE. */ --- 7084,7090 ---- So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will straighten this out. */ BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo)); ! else if (BINFO_PRIMARY_P (binfo) && BINFO_VIRTUAL_P (binfo)) inits = NULL_TREE; else /* For an ordinary vtable, set BINFO_VTABLE. */ *************** dfs_accumulate_vtbl_inits (tree binfo, *** 7284,7289 **** --- 7093,7100 ---- return inits; } + static GTY(()) tree abort_fndecl_addr; + /* Construct the initializer for BINFO's virtual function table. BINFO is part of the hierarchy dominated by T. If we're building a construction vtable, the ORIG_BINFO is the binfo we should use to *************** build_vtbl_initializer (tree binfo, *** 7316,7335 **** { tree v, b; tree vfun_inits; - tree vbase; vtbl_init_data vid; ! /* Initialize VID. */ memset (&vid, 0, sizeof (vid)); vid.binfo = binfo; vid.derived = t; vid.rtti_binfo = rtti_binfo; 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 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); /* Add entries to the vtable for RTTI. */ build_rtti_vtbl_entries (binfo, &vid); --- 7127,7148 ---- { tree v, b; tree vfun_inits; vtbl_init_data vid; ! unsigned ix; ! tree vbinfo; ! VEC (tree) *vbases; ! /* Initialize VID. */ memset (&vid, 0, sizeof (vid)); vid.binfo = binfo; vid.derived = t; vid.rtti_binfo = rtti_binfo; vid.last_init = &vid.inits; ! vid.primary_vtbl_p = SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t); ! vid.ctor_vtbl_p = !SAME_BINFO_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 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); /* Add entries to the vtable for RTTI. */ build_rtti_vtbl_entries (binfo, &vid); *************** build_vtbl_initializer (tree binfo, *** 7340,7351 **** VARRAY_TREE_INIT (vid.fns, 32, "fns"); /* Add the vcall and vbase offset entries. */ build_vcall_and_vbase_vtbl_entries (binfo, &vid); /* Clear BINFO_VTABLE_PATH_MARKED; it's set by build_vbase_offset_vtbl_entries. */ ! for (vbase = CLASSTYPE_VBASECLASSES (t); ! vbase; ! vbase = TREE_CHAIN (vbase)) ! BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)) = 0; /* If the target requires padding between data entries, add that now. */ if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1) --- 7153,7164 ---- VARRAY_TREE_INIT (vid.fns, 32, "fns"); /* Add the vcall and vbase offset entries. */ build_vcall_and_vbase_vtbl_entries (binfo, &vid); + /* Clear BINFO_VTABLE_PATH_MARKED; it's set by build_vbase_offset_vtbl_entries. */ ! for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0; ! VEC_iterate (tree, vbases, ix, vbinfo); ix++) ! BINFO_VTABLE_PATH_MARKED (vbinfo) = 0; /* If the target requires padding between data entries, add that now. */ if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1) *************** build_vtbl_initializer (tree binfo, *** 7425,7448 **** delta = BV_DELTA (v); vcall_index = BV_VCALL_INDEX (v); ! my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727); ! my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727); /* You can't call an abstract virtual function; it's abstract. So, we replace these functions with __pure_virtual. */ if (DECL_PURE_VIRTUAL_P (fn_original)) - fn = abort_fndecl; - else if (!integer_zerop (delta) || vcall_index) { ! fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index); ! if (!DECL_NAME (fn)) ! finish_thunk (fn); } - /* Take the address of the function, considering it to be of an - appropriate generic type. */ - init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn); - /* The address of a function can't change. */ - TREE_CONSTANT (init) = 1; } /* And add it to the chain of initializers. */ --- 7238,7267 ---- delta = BV_DELTA (v); vcall_index = BV_VCALL_INDEX (v); ! gcc_assert (TREE_CODE (delta) == INTEGER_CST); ! gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); /* You can't call an abstract virtual function; it's abstract. So, we replace these functions with __pure_virtual. */ if (DECL_PURE_VIRTUAL_P (fn_original)) { ! fn = abort_fndecl; ! if (abort_fndecl_addr == NULL) ! abort_fndecl_addr = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn); ! init = abort_fndecl_addr; ! } ! else ! { ! if (!integer_zerop (delta) || vcall_index) ! { ! fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index); ! if (!DECL_NAME (fn)) ! finish_thunk (fn); ! } ! /* Take the address of the function, considering it to be of an ! appropriate generic type. */ ! init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn); } } /* And add it to the chain of initializers. */ *************** build_vtbl_initializer (tree binfo, *** 7455,7464 **** else for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i) { ! tree fdesc = build (FDESC_EXPR, vfunc_ptr_type_node, ! TREE_OPERAND (init, 0), ! build_int_2 (i, 0)); TREE_CONSTANT (fdesc) = 1; vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits); } --- 7274,7284 ---- else for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i) { ! tree fdesc = build2 (FDESC_EXPR, vfunc_ptr_type_node, ! TREE_OPERAND (init, 0), ! build_int_cst (NULL_TREE, i)); TREE_CONSTANT (fdesc) = 1; + TREE_INVARIANT (fdesc) = 1; vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits); } *************** build_vbase_offset_vtbl_entries (tree bi *** 7512,7518 **** /* If there are no virtual baseclasses, then there is nothing to do. */ ! if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) return; t = vid->derived; --- 7332,7338 ---- /* If there are no virtual baseclasses, then there is nothing to do. */ ! if (!CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo))) return; t = vid->derived; *************** build_vbase_offset_vtbl_entries (tree bi *** 7529,7535 **** 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)) { non_primary_binfo = vid->binfo; break; --- 7349,7355 ---- 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 (BINFO_VIRTUAL_P (non_primary_binfo)) { non_primary_binfo = vid->binfo; break; *************** build_vbase_offset_vtbl_entries (tree bi *** 7549,7555 **** tree b; tree delta; ! if (!TREE_VIA_VIRTUAL (vbase)) continue; /* Find the instance of this virtual base in the complete --- 7369,7375 ---- tree b; tree delta; ! if (!BINFO_VIRTUAL_P (vbase)) continue; /* Find the instance of this virtual base in the complete *************** build_vbase_offset_vtbl_entries (tree bi *** 7571,7582 **** BINFO_VPTR_FIELD (b) = delta; if (binfo != TYPE_BINFO (t)) ! { ! /* The vbase offset had better be the same. */ ! my_friendly_assert (tree_int_cst_equal (delta, ! BINFO_VPTR_FIELD (vbase)), ! 20030202); ! } /* The next vbase will come at a more negative offset. */ vid->index = size_binop (MINUS_EXPR, vid->index, --- 7391,7398 ---- BINFO_VPTR_FIELD (b) = delta; if (binfo != TYPE_BINFO (t)) ! /* The vbase offset had better be the same. */ ! gcc_assert (tree_int_cst_equal (delta, BINFO_VPTR_FIELD (vbase))); /* The next vbase will come at a more negative offset. */ vid->index = size_binop (MINUS_EXPR, vid->index, *************** build_vcall_offset_vtbl_entries (tree bi *** 7607,7613 **** /* 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: --- 7423,7429 ---- /* 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 (BINFO_VIRTUAL_P (binfo) || binfo == TYPE_BINFO (vid->derived)) { /* We need a vcall offset for each of the virtual functions in this vtable. For example: *************** build_vcall_offset_vtbl_entries (tree bi *** 7630,7636 **** 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); --- 7446,7452 ---- vid->vbase = binfo; /* If we are just computing the vcall indices -- but do not need the actual entries -- not that. */ ! if (!BINFO_VIRTUAL_P (binfo)) vid->generate_vcall_entries = false; /* Now, walk through the non-virtual bases, adding vcall offsets. */ add_vcall_offset_vtbl_entries_r (binfo, vid); *************** add_vcall_offset_vtbl_entries_r (tree bi *** 7644,7655 **** { int i; tree primary_binfo; /* Don't walk into virtual bases -- except, of course, for the virtual base for which we are building vcall offsets. Any primary virtual base will have already had its offsets generated through the recursion in build_vcall_and_vbase_vtbl_entries. */ ! if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo) return; /* If BINFO has a primary base, process it first. */ --- 7460,7472 ---- { int i; tree primary_binfo; + tree base_binfo; /* Don't walk into virtual bases -- except, of course, for the virtual base for which we are building vcall offsets. Any primary virtual base will have already had its offsets generated through the recursion in build_vcall_and_vbase_vtbl_entries. */ ! if (BINFO_VIRTUAL_P (binfo) && vid->vbase != binfo) return; /* If BINFO has a primary base, process it first. */ *************** add_vcall_offset_vtbl_entries_r (tree bi *** 7661,7674 **** add_vcall_offset_vtbl_entries_1 (binfo, vid); /* Scan the non-primary bases of BINFO. */ ! for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) ! { ! tree base_binfo; ! ! base_binfo = BINFO_BASETYPE (binfo, i); ! if (base_binfo != primary_binfo) ! add_vcall_offset_vtbl_entries_r (base_binfo, vid); ! } } /* Called from build_vcall_offset_vtbl_entries_r. */ --- 7478,7486 ---- add_vcall_offset_vtbl_entries_1 (binfo, vid); /* Scan the non-primary bases of BINFO. */ ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) ! if (base_binfo != primary_binfo) ! add_vcall_offset_vtbl_entries_r (base_binfo, vid); } /* Called from build_vcall_offset_vtbl_entries_r. */ *************** add_vcall_offset_vtbl_entries_1 (tree bi *** 7712,7721 **** 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; } --- 7524,7532 ---- 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 (BINFO_VIRTUAL_P (non_primary_binfo)) { ! gcc_assert (non_primary_binfo == vid->vbase); non_primary_binfo = vid->binfo; break; } *************** add_vcall_offset_vtbl_entries_1 (tree bi *** 7749,7755 **** /* 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); --- 7560,7566 ---- /* 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_BINFO_TYPE_P (BINFO_TYPE (binfo), DECL_CONTEXT (orig_fn))) continue; add_vcall_offset (orig_fn, binfo, vid); *************** add_vcall_offset (tree orig_fn, tree bin *** 7786,7795 **** 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)); ! /* The next vcall offset will be found at a more negative offset. */ vid->index = size_binop (MINUS_EXPR, vid->index, --- 7597,7610 ---- the vtable for the most derived class, remember the vcall offset. */ if (vid->binfo == TYPE_BINFO (vid->derived)) ! { ! tree_pair_p elt = VEC_safe_push (tree_pair_s, ! CLASSTYPE_VCALL_INDICES (vid->derived), ! NULL); ! elt->purpose = orig_fn; ! elt->value = vid->index; ! } ! /* The next vcall offset will be found at a more negative offset. */ vid->index = size_binop (MINUS_EXPR, vid->index, *************** build_rtti_vtbl_entries (tree binfo, vtb *** 7853,7859 **** tree primary_base; primary_base = get_primary_binfo (b); ! my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127); b = primary_base; } offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b)); --- 7668,7675 ---- tree primary_base; primary_base = get_primary_binfo (b); ! gcc_assert (BINFO_PRIMARY_P (primary_base) ! && BINFO_INHERITANCE_CHAIN (primary_base) == b); b = primary_base; } offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b)); *************** build_rtti_vtbl_entries (tree binfo, vtb *** 7870,7879 **** *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 = build_nop (vfunc_ptr_type_node, offset); *vid->last_init = build_tree_list (NULL_TREE, init); vid->last_init = &TREE_CHAIN (*vid->last_init); } --- 7686,7725 ---- *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 than ! the typeinfo entry. Convert the offset to look like a function pointer, so that we can put it in the vtable. */ 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); } + + /* Fold a OBJ_TYPE_REF expression to the address of a function. + KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). */ + + tree + cp_fold_obj_type_ref (tree ref, tree known_type) + { + HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1); + HOST_WIDE_INT i = 0; + tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type)); + tree fndecl; + + while (i != index) + { + i += (TARGET_VTABLE_USES_DESCRIPTORS + ? TARGET_VTABLE_USES_DESCRIPTORS : 1); + v = TREE_CHAIN (v); + } + + fndecl = BV_FN (v); + + #ifdef ENABLE_CHECKING + gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), + DECL_VINDEX (fndecl))); + #endif + + return build_address (fndecl); + } + + #include "gt-cp-class.h" diff -Nrcpad gcc-3.4.3/gcc/cp/config-lang.in gcc-4.0.0/gcc/cp/config-lang.in *** gcc-3.4.3/gcc/cp/config-lang.in Mon Jun 23 20:52:12 2003 --- gcc-4.0.0/gcc/cp/config-lang.in Tue Jan 25 19:21:30 2005 *************** stagestuff="g++\$(exeext) g++-cross\$(ex *** 34,37 **** target_libs="target-libstdc++-v3 target-gperf" ! gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.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/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c" --- 34,37 ---- target_libs="target-libstdc++-v3 target-gperf" ! gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c \$(srcdir)/cp/class.c" diff -Nrcpad gcc-3.4.3/gcc/cp/cp-gimplify.c gcc-4.0.0/gcc/cp/cp-gimplify.c *** gcc-3.4.3/gcc/cp/cp-gimplify.c Thu Jan 1 00:00:00 1970 --- gcc-4.0.0/gcc/cp/cp-gimplify.c Wed Dec 22 18:00:38 2004 *************** *** 0 **** --- 1,373 ---- + /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. + + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Contributed by Jason Merrill + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + #include "config.h" + #include "system.h" + #include "coretypes.h" + #include "tm.h" + #include "tree.h" + #include "cp-tree.h" + #include "c-common.h" + #include "toplev.h" + #include "tree-gimple.h" + #include "hashtab.h" + #include "pointer-set.h" + + /* Genericize a TRY_BLOCK. */ + + static void + genericize_try_block (tree *stmt_p) + { + tree body = TRY_STMTS (*stmt_p); + tree cleanup = TRY_HANDLERS (*stmt_p); + + gimplify_stmt (&body); + + if (CLEANUP_P (*stmt_p)) + /* A cleanup is an expression, so it doesn't need to be genericized. */; + else + gimplify_stmt (&cleanup); + + *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); + } + + /* Genericize a HANDLER by converting to a CATCH_EXPR. */ + + static void + genericize_catch_block (tree *stmt_p) + { + tree type = HANDLER_TYPE (*stmt_p); + tree body = HANDLER_BODY (*stmt_p); + + gimplify_stmt (&body); + + /* FIXME should the caught type go in TREE_TYPE? */ + *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); + } + + /* Genericize an EH_SPEC_BLOCK by converting it to a + TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ + + static void + genericize_eh_spec_block (tree *stmt_p) + { + tree body = EH_SPEC_STMTS (*stmt_p); + tree allowed = EH_SPEC_RAISES (*stmt_p); + tree failure = build_call (call_unexpected_node, + tree_cons (NULL_TREE, build_exc_ptr (), + NULL_TREE)); + gimplify_stmt (&body); + + *stmt_p = gimple_build_eh_filter (body, allowed, failure); + } + + /* Genericize an IF_STMT by turning it into a COND_EXPR. */ + + static void + gimplify_if_stmt (tree *stmt_p) + { + tree stmt, cond, then_, else_; + + stmt = *stmt_p; + cond = IF_COND (stmt); + then_ = THEN_CLAUSE (stmt); + else_ = ELSE_CLAUSE (stmt); + + if (!then_) + then_ = build_empty_stmt (); + if (!else_) + else_ = build_empty_stmt (); + + if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) + stmt = then_; + else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) + stmt = else_; + else + stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); + *stmt_p = stmt; + } + + /* Gimplify initialization from an AGGR_INIT_EXPR. */ + + static void + cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) + { + tree from = TREE_OPERAND (*expr_p, 1); + tree to = TREE_OPERAND (*expr_p, 0); + tree sub; + + /* If we are initializing something from a TARGET_EXPR, strip the + TARGET_EXPR and initialize it directly. */ + /* What about code that pulls out the temp and uses it elsewhere? I + think that such code never uses the TARGET_EXPR as an initializer. If + I'm wrong, we'll abort because the temp won't have any RTL. In that + case, I guess we'll need to replace references somehow. */ + if (TREE_CODE (from) == TARGET_EXPR) + from = TARGET_EXPR_INITIAL (from); + if (TREE_CODE (from) == CLEANUP_POINT_EXPR) + from = TREE_OPERAND (from, 0); + + /* Look through any COMPOUND_EXPRs. */ + sub = expr_last (from); + + /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and + replace the slot operand with our target. + + Should we add a target parm to gimplify_expr instead? No, as in this + case we want to replace the INIT_EXPR. */ + if (TREE_CODE (sub) == AGGR_INIT_EXPR) + { + gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); + TREE_OPERAND (sub, 2) = to; + *expr_p = from; + + /* The initialization is now a side-effect, so the container can + become void. */ + if (from != sub) + TREE_TYPE (from) = void_type_node; + } + } + + /* Gimplify a MUST_NOT_THROW_EXPR. */ + + static void + gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) + { + tree stmt = *expr_p; + tree temp = voidify_wrapper_expr (stmt, NULL); + tree body = TREE_OPERAND (stmt, 0); + + gimplify_stmt (&body); + + stmt = gimple_build_eh_filter (body, NULL_TREE, + build_call (terminate_node, NULL_TREE)); + + if (temp) + { + append_to_statement_list (stmt, pre_p); + *expr_p = temp; + } + else + *expr_p = stmt; + } + + /* Do C++-specific gimplification. Args are as for gimplify_expr. */ + + int + cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) + { + int saved_stmts_are_full_exprs_p = 0; + enum tree_code code = TREE_CODE (*expr_p); + enum gimplify_status ret; + + if (STATEMENT_CODE_P (code)) + { + saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); + current_stmt_tree ()->stmts_are_full_exprs_p + = STMT_IS_FULL_EXPR_P (*expr_p); + } + + switch (code) + { + case PTRMEM_CST: + *expr_p = cplus_expand_constant (*expr_p); + ret = GS_OK; + break; + + case AGGR_INIT_EXPR: + simplify_aggr_init_expr (expr_p); + ret = GS_OK; + break; + + case THROW_EXPR: + /* FIXME communicate throw type to backend, probably by moving + THROW_EXPR into ../tree.def. */ + *expr_p = TREE_OPERAND (*expr_p, 0); + ret = GS_OK; + break; + + case MUST_NOT_THROW_EXPR: + gimplify_must_not_throw_expr (expr_p, pre_p); + ret = GS_OK; + break; + + case INIT_EXPR: + case MODIFY_EXPR: + cp_gimplify_init_expr (expr_p, pre_p, post_p); + ret = GS_OK; + break; + + case EMPTY_CLASS_EXPR: + /* We create an INTEGER_CST with RECORD_TYPE and value zero. */ + *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0); + ret = GS_OK; + break; + + case BASELINK: + *expr_p = BASELINK_FUNCTIONS (*expr_p); + ret = GS_OK; + break; + + case TRY_BLOCK: + genericize_try_block (expr_p); + ret = GS_OK; + break; + + case HANDLER: + genericize_catch_block (expr_p); + ret = GS_OK; + break; + + case EH_SPEC_BLOCK: + genericize_eh_spec_block (expr_p); + ret = GS_OK; + break; + + case USING_STMT: + /* Just ignore for now. Eventually we will want to pass this on to + the debugger. */ + *expr_p = build_empty_stmt (); + ret = GS_ALL_DONE; + break; + + case IF_STMT: + gimplify_if_stmt (expr_p); + ret = GS_OK; + break; + + default: + ret = c_gimplify_expr (expr_p, pre_p, post_p); + break; + } + + /* Restore saved state. */ + if (STATEMENT_CODE_P (code)) + current_stmt_tree ()->stmts_are_full_exprs_p + = saved_stmts_are_full_exprs_p; + + return ret; + } + + static inline bool + is_invisiref_parm (tree t) + { + return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) + && DECL_BY_REFERENCE (t)); + } + + /* Perform any pre-gimplification lowering of C++ front end trees to + GENERIC. */ + + static tree + cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) + { + tree stmt = *stmt_p; + struct pointer_set_t *p_set = (struct pointer_set_t*) data; + + if (is_invisiref_parm (stmt)) + { + *stmt_p = convert_from_reference (stmt); + *walk_subtrees = 0; + return NULL; + } + + /* Other than invisiref parms, don't walk the same tree twice. */ + if (pointer_set_contains (p_set, stmt)) + { + *walk_subtrees = 0; + return NULL_TREE; + } + + if (TREE_CODE (stmt) == ADDR_EXPR + && is_invisiref_parm (TREE_OPERAND (stmt, 0))) + { + *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); + *walk_subtrees = 0; + } + else if (TREE_CODE (stmt) == RETURN_EXPR + && TREE_OPERAND (stmt, 0) + && is_invisiref_parm (TREE_OPERAND (stmt, 0))) + /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ + *walk_subtrees = 0; + else if (IS_TYPE_OR_DECL_P (stmt)) + *walk_subtrees = 0; + + /* Due to the way voidify_wrapper_expr is written, we don't get a chance + to lower this construct before scanning it, so we need to lower these + before doing anything else. */ + else if (TREE_CODE (stmt) == CLEANUP_STMT) + *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR + : TRY_FINALLY_EXPR, + void_type_node, + CLEANUP_BODY (stmt), + CLEANUP_EXPR (stmt)); + + pointer_set_insert (p_set, *stmt_p); + + return NULL; + } + + void + cp_genericize (tree fndecl) + { + tree t; + struct pointer_set_t *p_set; + + /* Fix up the types of parms passed by invisible reference. */ + for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) + if (TREE_ADDRESSABLE (TREE_TYPE (t))) + { + /* If a function's arguments are copied to create a thunk, + then DECL_BY_REFERENCE will be set -- but the type of the + argument will be a pointer type, so we will never get + here. */ + gcc_assert (!DECL_BY_REFERENCE (t)); + gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); + TREE_TYPE (t) = DECL_ARG_TYPE (t); + DECL_BY_REFERENCE (t) = 1; + TREE_ADDRESSABLE (t) = 0; + relayout_decl (t); + } + + /* Do the same for the return value. */ + if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) + { + t = DECL_RESULT (fndecl); + TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); + DECL_BY_REFERENCE (t) = 1; + TREE_ADDRESSABLE (t) = 0; + relayout_decl (t); + } + + /* If we're a clone, the body is already GIMPLE. */ + if (DECL_CLONED_FUNCTION_P (fndecl)) + return; + + /* We do want to see every occurrence of the parms, so we can't just use + walk_tree's hash functionality. */ + p_set = pointer_set_create (); + walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); + pointer_set_destroy (p_set); + + /* Do everything else. */ + c_genericize (fndecl); + } diff -Nrcpad gcc-3.4.3/gcc/cp/cp-lang.c gcc-4.0.0/gcc/cp/cp-lang.c *** gcc-3.4.3/gcc/cp/cp-lang.c Tue Dec 23 16:53:47 2003 --- gcc-4.0.0/gcc/cp/cp-lang.c Tue Nov 2 20:29:21 2004 *************** *** 1,5 **** /* Language-dependent hooks for C++. ! Copyright 2001, 2002 Free Software Foundation, Inc. Contributed by Alexandre Oliva This file is part of GCC. --- 1,5 ---- /* Language-dependent hooks for C++. ! Copyright 2001, 2002, 2004 Free Software Foundation, Inc. Contributed by Alexandre Oliva This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 31,206 **** #include "langhooks-def.h" #include "diagnostic.h" #include "cxx-pretty-print.h" enum c_language_kind c_language = clk_cxx; ! static HOST_WIDE_INT cxx_get_alias_set (tree); ! static bool ok_to_generate_alias_set_for_type (tree); ! static bool cxx_warn_unused_global_decl (tree); ! static tree cp_expr_size (tree); ! static size_t cp_tree_size (enum tree_code); ! static bool cp_var_mod_type_p (tree); ! static void cxx_initialize_diagnostics (diagnostic_context *); #undef LANG_HOOKS_NAME #define LANG_HOOKS_NAME "GNU C++" - #undef LANG_HOOKS_TREE_SIZE - #define LANG_HOOKS_TREE_SIZE cp_tree_size #undef LANG_HOOKS_INIT #define LANG_HOOKS_INIT cxx_init - #undef LANG_HOOKS_FINISH - #define LANG_HOOKS_FINISH cxx_finish - #undef LANG_HOOKS_CLEAR_BINDING_STACK - #define LANG_HOOKS_CLEAR_BINDING_STACK pop_everything - #undef LANG_HOOKS_INIT_OPTIONS - #define LANG_HOOKS_INIT_OPTIONS c_common_init_options - #undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS - #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS cxx_initialize_diagnostics - #undef LANG_HOOKS_HANDLE_OPTION - #define LANG_HOOKS_HANDLE_OPTION c_common_handle_option - #undef LANG_HOOKS_HANDLE_FILENAME - #define LANG_HOOKS_HANDLE_FILENAME c_common_handle_filename - #undef LANG_HOOKS_MISSING_ARGUMENT - #define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument - #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_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 - #define LANG_HOOKS_PRINT_XNODE cxx_print_xnode - #undef LANG_HOOKS_PRINT_DECL - #define LANG_HOOKS_PRINT_DECL cxx_print_decl - #undef LANG_HOOKS_PRINT_TYPE - #define LANG_HOOKS_PRINT_TYPE cxx_print_type - #undef LANG_HOOKS_PRINT_IDENTIFIER - #define LANG_HOOKS_PRINT_IDENTIFIER cxx_print_identifier #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_BUILTIN_TYPE_DECLS ! #define LANG_HOOKS_BUILTIN_TYPE_DECLS cxx_builtin_type_decls ! #undef LANG_HOOKS_PUSHLEVEL ! #define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i ! #undef LANG_HOOKS_POPLEVEL ! #define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree ! #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_DECL_UNINIT ! #define LANG_HOOKS_DECL_UNINIT c_decl_uninit ! ! ! #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 ! ! #undef LANG_HOOKS_RTL_EXPAND_START ! #define LANG_HOOKS_RTL_EXPAND_START cxx_expand_function_start ! #undef LANG_HOOKS_RTL_EXPAND_STMT ! #define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt ! ! /* 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 \ ! cp_walk_subtrees ! #undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN ! #define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \ ! cp_cannot_inline_tree_fn ! #undef LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS ! #define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \ ! cp_add_pending_fn_decls ! #undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P ! #define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \ ! cp_is_overload_p ! #undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P ! #define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \ ! cp_auto_var_in_fn_p ! #undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING ! #define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \ ! cp_copy_res_decl_for_inlining ! #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P ! #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p ! #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P ! #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p ! #undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS ! #define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS c_estimate_num_insns ! #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN ! #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree ! #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN ! #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals ! #undef LANG_HOOKS_EXPR_SIZE ! #define LANG_HOOKS_EXPR_SIZE cp_expr_size ! ! #undef LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR ! #define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR cxx_callgraph_analyze_expr ! #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION ! #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION expand_body ! ! #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 ! #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE ! #define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type ! /* 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 --- 31,65 ---- #include "langhooks-def.h" #include "diagnostic.h" #include "cxx-pretty-print.h" + #include "debug.h" + #include "cp-objcp-common.h" enum c_language_kind c_language = clk_cxx; ! /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h; ! consequently, there should be very few hooks below. */ #undef LANG_HOOKS_NAME #define LANG_HOOKS_NAME "GNU C++" #undef LANG_HOOKS_INIT #define LANG_HOOKS_INIT cxx_init #undef LANG_HOOKS_DECL_PRINTABLE_NAME #define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name ! #undef LANG_HOOKS_FOLD_OBJ_TYPE_REF ! #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref ! /* Each front end provides its own lang hook initializer. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; /* Tree code classes. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, ! const enum tree_code_class tree_code_type[] = { #include "tree.def" ! tcc_exceptional, #include "c-common.def" ! tcc_exceptional, #include "cp-tree.def" }; #undef DEFTREECODE *************** const char *const tree_code_name[] = { *** 233,414 **** }; #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 (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 (tree t) ! { ! if (TREE_CODE (t) == RECORD_TYPE ! && TYPE_CONTEXT (t) && CLASS_TYPE_P (TYPE_CONTEXT (t)) ! && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t) ! /* The base variant of a type must be in the same alias set as the ! complete type. */ ! return get_alias_set (TYPE_CONTEXT (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 (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. */ ! ! static tree ! cp_expr_size (tree exp) ! { ! if (CLASS_TYPE_P (TREE_TYPE (exp))) ! { ! /* 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 (is_empty_class (TREE_TYPE (exp)) ! ? size_zero_node ! : CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp))); ! } ! else ! /* Use the default code. */ ! return lhd_expr_size (exp); ! } ! ! /* Langhook for tree_size: determine size of our 'x' and 'c' nodes. */ ! static size_t ! cp_tree_size (enum tree_code code) ! { ! switch (code) ! { ! case PTRMEM_CST: return sizeof (struct ptrmem_cst); ! case BASELINK: return sizeof (struct tree_baselink); ! case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index); ! case DEFAULT_ARG: return sizeof (struct tree_default_arg); ! case OVERLOAD: return sizeof (struct tree_overload); ! case WRAPPER: return sizeof (struct tree_wrapper); ! default: ! abort (); ! } ! /* NOTREACHED */ ! } ! /* Returns true if T is a variably modified type, in the sense of C99. ! This routine needs only check cases that cannot be handled by the ! language-independent logic in tree-inline.c. */ ! static bool ! cp_var_mod_type_p (tree type) { ! /* If TYPE is a pointer-to-member, it is variably modified if either ! the class or the member are variably modified. */ ! if (TYPE_PTR_TO_MEMBER_P (type)) ! return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type)) ! || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))); ! ! /* All other types are not variably modified. */ ! return false; } - /* Stub routine to tell people that this doesn't work yet. */ void ! c_reset_state (void) { ! sorry ("inter-module optimisations not implemented yet"); } ! /* Construct a C++-aware pretty-printer for CONTEXT. It is assumed ! that CONTEXT->printer is an already constructed basic pretty_printer. */ ! static void ! cxx_initialize_diagnostics (diagnostic_context *context) ! { ! pretty_printer *base = context->printer; ! cxx_pretty_printer *pp = xmalloc (sizeof (cxx_pretty_printer)); ! memcpy (pp_base (pp), base, sizeof (pretty_printer)); ! pp_cxx_pretty_printer_init (pp); ! context->printer = (pretty_printer *) pp; ! ! /* It is safe to free this object because it was previously malloc()'d. */ ! free (base); ! } --- 92,116 ---- }; #undef DEFTREECODE ! /* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c; ! there should be very few routines below. */ ! /* The following function does something real, but only in Objective-C++. */ ! tree ! objcp_tsubst_copy_and_build (tree t ATTRIBUTE_UNUSED, ! tree args ATTRIBUTE_UNUSED, ! tsubst_flags_t complain ATTRIBUTE_UNUSED, ! tree in_decl ATTRIBUTE_UNUSED, ! bool function_p ATTRIBUTE_UNUSED) { ! return NULL_TREE; } void ! finish_file (void) { ! cp_finish_file (); } ! #include "gtype-cp.h" diff -Nrcpad gcc-3.4.3/gcc/cp/cp-objcp-common.c gcc-4.0.0/gcc/cp/cp-objcp-common.c *** gcc-3.4.3/gcc/cp/cp-objcp-common.c Thu Jan 1 00:00:00 1970 --- gcc-4.0.0/gcc/cp/cp-objcp-common.c Tue Dec 14 19:38:25 2004 *************** *** 0 **** --- 1,204 ---- + /* Some code common to C++ and ObjC++ front ends. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Ziemowit Laski + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + #include "config.h" + #include "system.h" + #include "coretypes.h" + #include "tm.h" + #include "tree.h" + #include "cp-tree.h" + #include "c-common.h" + #include "toplev.h" + #include "langhooks.h" + #include "langhooks-def.h" + #include "diagnostic.h" + #include "debug.h" + #include "cxx-pretty-print.h" + #include "cp-objcp-common.h" + + /* Special routine to get the alias set for C++. */ + + HOST_WIDE_INT + cxx_get_alias_set (tree t) + { + if (IS_FAKE_BASE_TYPE (t)) + /* The base variant of a type must be in the same alias set as the + complete type. */ + return get_alias_set (TYPE_CONTEXT (t)); + + /* Punt on PMFs until we canonicalize functions properly. */ + if (TYPE_PTRMEMFUNC_P (t)) + return 0; + + return c_common_get_alias_set (t); + } + + /* Called from check_global_declarations. */ + + bool + cxx_warn_unused_global_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. */ + + tree + cp_expr_size (tree exp) + { + tree type = TREE_TYPE (exp); + + if (CLASS_TYPE_P (type)) + { + /* 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. */ + gcc_assert (!TYPE_HAS_COMPLEX_INIT_REF (type) + || !TYPE_HAS_COMPLEX_ASSIGN_REF (type) + /* But storing a CONSTRUCTOR isn't a copy. */ + || TREE_CODE (exp) == CONSTRUCTOR + /* And, the gimplifier will sometimes make a copy of + an aggregate. In particular, for a case like: + + struct S { S(); }; + struct X { int a; S s; }; + X x = { 0 }; + + the gimplifier will create a temporary with + static storage duration, perform static + initialization of the temporary, and then copy + the result. Since the "s" subobject is never + constructed, this is a valid transformation. */ + || CP_AGGREGATE_TYPE_P (type)); + + /* This would be wrong for a type with virtual bases, but they are + caught by the assert above. */ + return (is_empty_class (type) + ? size_zero_node + : CLASSTYPE_SIZE_UNIT (type)); + } + else + /* Use the default code. */ + return lhd_expr_size (exp); + } + + /* Langhook for tree_size: determine size of our 'x' and 'c' nodes. */ + size_t + cp_tree_size (enum tree_code code) + { + switch (code) + { + case TINST_LEVEL: return sizeof (struct tinst_level_s); + case PTRMEM_CST: return sizeof (struct ptrmem_cst); + case BASELINK: return sizeof (struct tree_baselink); + case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index); + case DEFAULT_ARG: return sizeof (struct tree_default_arg); + case OVERLOAD: return sizeof (struct tree_overload); + default: + gcc_unreachable (); + } + /* NOTREACHED */ + } + + /* Returns true if T is a variably modified type, in the sense of C99. + FN is as passed to variably_modified_p. + This routine needs only check cases that cannot be handled by the + language-independent logic in tree.c. */ + + bool + cp_var_mod_type_p (tree type, tree fn) + { + /* If TYPE is a pointer-to-member, it is variably modified if either + the class or the member are variably modified. */ + if (TYPE_PTR_TO_MEMBER_P (type)) + return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type), fn) + || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type), + fn)); + + /* All other types are not variably modified. */ + return false; + } + + /* Construct a C++-aware pretty-printer for CONTEXT. It is assumed + that CONTEXT->printer is an already constructed basic pretty_printer. */ + void + cxx_initialize_diagnostics (diagnostic_context *context) + { + pretty_printer *base = context->printer; + cxx_pretty_printer *pp = xmalloc (sizeof (cxx_pretty_printer)); + memcpy (pp_base (pp), base, sizeof (pretty_printer)); + pp_cxx_pretty_printer_init (pp); + context->printer = (pretty_printer *) pp; + + /* It is safe to free this object because it was previously malloc()'d. */ + free (base); + } + + /* This compares two types for equivalence ("compatible" in C-based languages). + This routine should only return 1 if it is sure. It should not be used + in contexts where erroneously returning 0 causes problems. */ + + int + cxx_types_compatible_p (tree x, tree y) + { + if (same_type_ignoring_top_level_qualifiers_p (x, y)) + return 1; + + /* Once we get to the middle-end, references and pointers are + interchangeable. FIXME should we try to replace all references with + pointers? */ + if (POINTER_TYPE_P (x) && POINTER_TYPE_P (y) + && TYPE_MODE (x) == TYPE_MODE (y) + && TYPE_REF_CAN_ALIAS_ALL (x) == TYPE_REF_CAN_ALIAS_ALL (y) + && same_type_p (TREE_TYPE (x), TREE_TYPE (y))) + return 1; + + return 0; + } + + /* Stubs to keep c-opts.c happy. */ + void + push_file_scope (void) + { + } + + void + pop_file_scope (void) + { + } + + /* c-pragma.c needs to query whether a decl has extern "C" linkage. */ + bool + has_c_linkage (tree decl) + { + return DECL_EXTERN_C_P (decl); + } diff -Nrcpad gcc-3.4.3/gcc/cp/cp-objcp-common.h gcc-4.0.0/gcc/cp/cp-objcp-common.h *** gcc-3.4.3/gcc/cp/cp-objcp-common.h Thu Jan 1 00:00:00 1970 --- gcc-4.0.0/gcc/cp/cp-objcp-common.h Wed Feb 23 15:14:42 2005 *************** *** 0 **** --- 1,167 ---- + /* Language hooks common to C++ and ObjC++ front ends. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Contributed by Ziemowit Laski + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; 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_OBJCP_COMMON + #define GCC_CP_OBJCP_COMMON + + /* In cp/cp-objcp-common.c. */ + + extern HOST_WIDE_INT cxx_get_alias_set (tree); + extern bool cxx_warn_unused_global_decl (tree); + extern tree cp_expr_size (tree); + extern size_t cp_tree_size (enum tree_code); + extern bool cp_var_mod_type_p (tree, tree); + extern void cxx_initialize_diagnostics (struct diagnostic_context *); + extern int cxx_types_compatible_p (tree, tree); + + /* In cp/cp-lang.c and objcp/objcp-lang.c. */ + + extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t, + tree, bool); + + /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks + specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, + respectively. */ + + #undef LANG_HOOKS_TREE_SIZE + #define LANG_HOOKS_TREE_SIZE cp_tree_size + #undef LANG_HOOKS_FINISH + #define LANG_HOOKS_FINISH cxx_finish + #undef LANG_HOOKS_CLEAR_BINDING_STACK + #define LANG_HOOKS_CLEAR_BINDING_STACK pop_everything + #undef LANG_HOOKS_INIT_OPTIONS + #define LANG_HOOKS_INIT_OPTIONS c_common_init_options + #undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS + #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS cxx_initialize_diagnostics + #undef LANG_HOOKS_HANDLE_OPTION + #define LANG_HOOKS_HANDLE_OPTION c_common_handle_option + #undef LANG_HOOKS_HANDLE_FILENAME + #define LANG_HOOKS_HANDLE_FILENAME c_common_handle_filename + #undef LANG_HOOKS_MISSING_ARGUMENT + #define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument + #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_EXPAND_DECL + #define LANG_HOOKS_EXPAND_DECL c_expand_decl + #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_TRUTHVALUE_CONVERSION + #define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion + #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 + #define LANG_HOOKS_PRINT_XNODE cxx_print_xnode + #undef LANG_HOOKS_PRINT_DECL + #define LANG_HOOKS_PRINT_DECL cxx_print_decl + #undef LANG_HOOKS_PRINT_TYPE + #define LANG_HOOKS_PRINT_TYPE cxx_print_type + #undef LANG_HOOKS_PRINT_IDENTIFIER + #define LANG_HOOKS_PRINT_IDENTIFIER cxx_print_identifier + #undef LANG_HOOKS_TYPES_COMPATIBLE_P + #define LANG_HOOKS_TYPES_COMPATIBLE_P cxx_types_compatible_p + #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_COMDAT_GROUP + #define LANG_HOOKS_COMDAT_GROUP cxx_comdat_group + + #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 + #undef LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P + #define LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p + + /* 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 \ + cp_walk_subtrees + #undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN + #define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \ + cp_cannot_inline_tree_fn + #undef LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS + #define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \ + cp_add_pending_fn_decls + #undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P + #define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \ + cp_auto_var_in_fn_p + #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P + #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p + #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P + #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p + #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN + #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree + #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN + #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals + #undef LANG_HOOKS_EXPR_SIZE + #define LANG_HOOKS_EXPR_SIZE cp_expr_size + + #undef LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR + #define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR cxx_callgraph_analyze_expr + #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION + #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION expand_body + + #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 + #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE + #define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type + #undef LANG_HOOKS_TO_TARGET_CHARSET + #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset + #undef LANG_HOOKS_GIMPLIFY_EXPR + #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr + + #endif /* GCC_CP_OBJCP_COMMON */ diff -Nrcpad gcc-3.4.3/gcc/cp/cp-tree.def gcc-4.0.0/gcc/cp/cp-tree.def *** gcc-3.4.3/gcc/cp/cp-tree.def Fri Aug 15 12:15:56 2003 --- gcc-4.0.0/gcc/cp/cp-tree.def Fri Apr 8 19:36:00 2005 *************** *** 1,7 **** /* This file contains the definitions and documentation for the additional tree codes used in the GNU C++ compiler (see tree.def for the standard codes). ! Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) --- 1,7 ---- /* This file contains the definitions and documentation for the additional tree codes used in the GNU C++ compiler (see tree.def for the standard codes). ! Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003, 2004, 2005, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) *************** Boston, MA 02111-1307, USA. */ *** 31,40 **** BASELINK, or TEMPLATE_ID_EXPR (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. This form is only used during the parsing phase; once semantic analysis has taken place they are eliminated. --- 31,38 ---- BASELINK, or TEMPLATE_ID_EXPR (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 is not ! taken. This form is only used during the parsing phase; once semantic analysis has taken place they are eliminated. *************** Boston, MA 02111-1307, USA. */ *** 42,96 **** 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. */ ! DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2) /* A pointer-to-member constant. For a pointer-to-member constant `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the PTRMEM_CST_MEMBER is the _DECL for `Y'. */ ! DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 0) /* For NEW_EXPR, operand 0 is the placement list. Operand 1 is the new-declarator. ! Operand 2 is the initializer. */ ! DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 3) ! DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3) /* For DELETE_EXPR, operand 0 is the store to be destroyed. Operand 1 is the value to pass to the destroying function saying whether the store should be deallocated as well. */ ! DEFTREECODE (DELETE_EXPR, "dl_expr", 'e', 2) ! DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", 'e', 2) /* Value is reference to particular overloaded class method. Operand 0 is the class, operand 1 is the field The COMPLEXITY field holds the class level (usually 0). */ ! DEFTREECODE (SCOPE_REF, "scope_ref", 'r', 2) /* When composing an object with a member, this is the result. Operand 0 is the object. Operand 1 is the member (usually a dereferenced pointer to member). */ ! DEFTREECODE (MEMBER_REF, "member_ref", 'r', 2) /* Type conversion operator in C++. TREE_TYPE is type that this operator converts to. Operand is expression to be converted. */ ! DEFTREECODE (TYPE_EXPR, "type_expr", 'e', 1) /* For AGGR_INIT_EXPR, operand 0 is function which performs initialization, operand 1 is argument list to initialization function, and operand 2 is the slot which was allocated for this expression. */ ! DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", 'e', 3) /* A throw expression. operand 0 is the expression, if there was one, else it is NULL_TREE. */ ! DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1) /* An empty class object. The TREE_TYPE gives the class type. We use these to avoid actually creating instances of the empty classes. */ ! DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0) /* A DECL which is really just a placeholder for an expression. Used to implement non-class scope anonymous unions. */ ! DEFTREECODE (ALIAS_DECL, "alias_decl", 'd', 0) /* A reference to a member function or member functions from a base class. BASELINK_FUNCTIONS gives the FUNCTION_DECL, --- 40,95 ---- 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. */ ! DEFTREECODE (OFFSET_REF, "offset_ref", tcc_reference, 2) /* A pointer-to-member constant. For a pointer-to-member constant `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the PTRMEM_CST_MEMBER is the _DECL for `Y'. */ ! DEFTREECODE (PTRMEM_CST, "ptrmem_cst", tcc_constant, 0) /* For NEW_EXPR, operand 0 is the placement list. Operand 1 is the new-declarator. ! Operand 2 is the number of elements in the array. ! Operand 3 is the initializer. */ ! DEFTREECODE (NEW_EXPR, "nw_expr", tcc_expression, 4) ! DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", tcc_expression, 3) /* For DELETE_EXPR, operand 0 is the store to be destroyed. Operand 1 is the value to pass to the destroying function saying whether the store should be deallocated as well. */ ! DEFTREECODE (DELETE_EXPR, "dl_expr", tcc_expression, 2) ! DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", tcc_expression, 2) /* Value is reference to particular overloaded class method. Operand 0 is the class, operand 1 is the field The COMPLEXITY field holds the class level (usually 0). */ ! DEFTREECODE (SCOPE_REF, "scope_ref", tcc_reference, 2) /* When composing an object with a member, this is the result. Operand 0 is the object. Operand 1 is the member (usually a dereferenced pointer to member). */ ! DEFTREECODE (MEMBER_REF, "member_ref", tcc_reference, 2) /* Type conversion operator in C++. TREE_TYPE is type that this operator converts to. Operand is expression to be converted. */ ! DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1) /* For AGGR_INIT_EXPR, operand 0 is function which performs initialization, operand 1 is argument list to initialization function, and operand 2 is the slot which was allocated for this expression. */ ! DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_expression, 3) /* A throw expression. operand 0 is the expression, if there was one, else it is NULL_TREE. */ ! DEFTREECODE (THROW_EXPR, "throw_expr", tcc_expression, 1) /* An empty class object. The TREE_TYPE gives the class type. We use these to avoid actually creating instances of the empty classes. */ ! DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", tcc_expression, 0) /* A DECL which is really just a placeholder for an expression. Used to implement non-class scope anonymous unions. */ ! DEFTREECODE (ALIAS_DECL, "alias_decl", tcc_declaration, 0) /* A reference to a member function or member functions from a base class. BASELINK_FUNCTIONS gives the FUNCTION_DECL, *************** DEFTREECODE (ALIAS_DECL, "alias_decl", ' *** 103,110 **** 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", 'x', 0) /* Template definition. The following fields have the specified uses, although there are other macros in cp-tree.h that should be used for --- 102,109 ---- 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", tcc_exceptional, 0) /* Template definition. The following fields have the specified uses, although there are other macros in cp-tree.h that should be used for *************** DEFTREECODE (BASELINK, "baselink", 'x', *** 121,127 **** DECL_TEMPLATE_RESULT decl for object to be created (e.g., FUNCTION_DECL with tmpl parms used) */ ! DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0) /* Index into a template parameter list. The TEMPLATE_PARM_IDX gives the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL --- 120,126 ---- DECL_TEMPLATE_RESULT decl for object to be created (e.g., FUNCTION_DECL with tmpl parms used) */ ! DEFTREECODE (TEMPLATE_DECL, "template_decl", tcc_declaration, 0) /* Index into a template parameter list. The TEMPLATE_PARM_IDX gives the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL *************** DEFTREECODE (TEMPLATE_DECL, "template_de *** 156,166 **** The LEVEL is the level of the parameter when we are worrying about the types of things; the ORIG_LEVEL is the level when we are worrying about instantiating things. */ ! DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", 'x', 0) ! ! /* Index into a template parameter list. This parameter must be a type. ! The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */ ! DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0) /* Index into a template parameter list for template template parameters. This parameter must be a type. The TYPE_FIELDS value will be a --- 155,161 ---- The LEVEL is the level of the parameter when we are worrying about the types of things; the ORIG_LEVEL is the level when we are worrying about instantiating things. */ ! DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", tcc_exceptional, 0) /* Index into a template parameter list for template template parameters. This parameter must be a type. The TYPE_FIELDS value will be a *************** DEFTREECODE (TEMPLATE_TYPE_PARM, "templa *** 169,237 **** It is used without template arguments like TT in C, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO is NULL_TREE and TYPE_NAME is a TEMPLATE_DECL. */ ! DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0) ! /* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments ! like TT. ! In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the ! template name and its bound arguments. TYPE_NAME is a TYPE_DECL. */ ! DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", 't', 0) /* A type designated by `typename T::t'. TYPE_CONTEXT is `T', TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR. ! If TREE_TYPE is present, this type was generated by the implicit ! typename extension, and the TREE_TYPE is a _TYPE from a baseclass ! of `T'. */ ! DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0) /* For template template argument of the form `T::template C'. TYPE_CONTEXT is `T', the template parameter dependent object. TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template. */ ! DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 't', 0) ! ! /* A type designated by `__typeof (expr)'. TYPE_FIELDS is the ! expression in question. */ ! DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0) /* A using declaration. DECL_INITIAL contains the specified scope. This is not an alias, but is later expanded into multiple aliases. The decl will have a NULL_TYPE iff the scope is a dependent scope, ! otherwise it will have a void type. */ ! DEFTREECODE (USING_DECL, "using_decl", 'd', 0) ! /* A using directive. The operand is USING_STMT_NAMESPACE. */ ! DEFTREECODE (USING_STMT, "using_directive", 'e', 1) /* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */ ! DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 0) /* A template-id, like foo. The first operand is the template. The second is NULL if there are no explicit arguments, or a TREE_VEC of arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or an OVERLOAD. If the template-id refers to a member template, the template may be an IDENTIFIER_NODE. */ ! DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2) /* 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', 0) ! /* A generic wrapper for something not tree that we want to include in ! tree structure. */ ! DEFTREECODE (WRAPPER, "wrapper", 'x', 0) /* A whole bunch of tree codes for the initial, superficial parsing of templates. */ ! DEFTREECODE (MODOP_EXPR, "modop_expr", 'e', 3) ! DEFTREECODE (CAST_EXPR, "cast_expr", '1', 1) ! DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", '1', 1) ! DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", '1', 1) ! DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", '1', 1) ! DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", '1', 1) ! DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2) ! DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1) ! DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3) /* A placeholder for an expression that is not type-dependent, but does occur in a template. When an expression that is not --- 164,247 ---- It is used without template arguments like TT in C, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO is NULL_TREE and TYPE_NAME is a TEMPLATE_DECL. */ ! DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", tcc_type, 0) ! /* The ordering of the following codes is optimized for the checking ! macros in tree.h. Changing the order will degrade the speed of the ! compiler. TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE, ! BOUND_TEMPLATE_TEMPLATE_PARM. */ ! ! /* Index into a template parameter list. This parameter must be a type. ! The type.value field will be a TEMPLATE_PARM_INDEX. */ ! DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", tcc_type, 0) /* A type designated by `typename T::t'. TYPE_CONTEXT is `T', TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR. ! TREE_TYPE is always NULL. */ ! DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0) ! ! /* A type designated by `__typeof (expr)'. TYPEOF_TYPE_EXPR is the ! expression in question. */ ! DEFTREECODE (TYPEOF_TYPE, "typeof_type", tcc_type, 0) ! ! /* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments ! like TT. ! In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the ! template name and its bound arguments. TYPE_NAME is a TYPE_DECL. */ ! DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", ! tcc_type, 0) /* For template template argument of the form `T::template C'. TYPE_CONTEXT is `T', the template parameter dependent object. TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template. */ ! DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0) /* A using declaration. DECL_INITIAL contains the specified scope. This is not an alias, but is later expanded into multiple aliases. The decl will have a NULL_TYPE iff the scope is a dependent scope, ! otherwise it will have a void type. */ ! DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0) ! /* A using directive. The operand is USING_STMT_NAMESPACE. */ ! DEFTREECODE (USING_STMT, "using_directive", tcc_expression, 1) /* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */ ! DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0) /* A template-id, like foo. The first operand is the template. The second is NULL if there are no explicit arguments, or a TREE_VEC of arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or an OVERLOAD. If the template-id refers to a member template, the template may be an IDENTIFIER_NODE. */ ! DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 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", tcc_exceptional, 0) ! /* A pseudo-destructor, of the form "OBJECT.~DESTRUCTOR" or ! "OBJECT.SCOPE::~DESTRUCTOR. The first operand is the OBJECT. The ! second operand (if non-NULL) is the SCOPE. The third operand is ! the TYPE node corresponding to the DESTRUCTOR. The type of the ! first operand will always be a scalar type. ! ! The type of a PSEUDO_DTOR_EXPR is always "void", even though it can ! be used as if it were a zero-argument function. We handle the ! function-call case specially, and giving it "void" type prevents it ! being used in expressions in ways that are not permitted. */ ! DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", tcc_expression, 3) /* A whole bunch of tree codes for the initial, superficial parsing of templates. */ ! DEFTREECODE (MODOP_EXPR, "modop_expr", tcc_expression, 3) ! DEFTREECODE (CAST_EXPR, "cast_expr", tcc_unary, 1) ! DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", tcc_unary, 1) ! DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", tcc_unary, 1) ! DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1) ! DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1) ! DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2) ! DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1) /* A placeholder for an expression that is not type-dependent, but does occur in a template. When an expression that is not *************** DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_d *** 241,285 **** that expression if it appeared in a template argument list. In that situation, we create a NON_DEPENDENT_EXPR to take the place of the original expression. The expression is the only operand -- it ! is only needed for diagnostics. */ ! DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", 'e', 1) /* 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', 1) ! DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2) ! DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2) /* A HANDLER wraps a catch handler for the HANDLER_TYPE. If this is CATCH_ALL_TYPE, then the handler catches all types. The declaration of the catch variable is in HANDLER_PARMS, and the body block in HANDLER_BODY. */ ! DEFTREECODE (HANDLER, "handler", 'e', 2) /* A MUST_NOT_THROW_EXPR wraps an expression that may not throw, and must call terminate if it does. */ ! DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1) ! DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0) ! /* 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) ! DEFTREECODE (QUAL_CONV, "qual_conv", 'e', 1) ! DEFTREECODE (STD_CONV, "std_conv", 'e', 1) ! DEFTREECODE (PTR_CONV, "ptr_conv", 'e', 1) ! DEFTREECODE (PMEM_CONV, "pmem_conv", 'e', 1) ! DEFTREECODE (BASE_CONV, "base_conv", 'e', 1) ! DEFTREECODE (REF_BIND, "ref_bind", 'e', 1) ! DEFTREECODE (USER_CONV, "user_conv", 'e', 2) ! DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1) ! DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1) /* Local variables: --- 251,303 ---- that expression if it appeared in a template argument list. In that situation, we create a NON_DEPENDENT_EXPR to take the place of the original expression. The expression is the only operand -- it ! is only needed for diagnostics. */ ! DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", tcc_expression, 1) /* 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", tcc_expression, 1) ! ! DEFTREECODE (TRY_BLOCK, "try_block", tcc_expression, 2) ! ! DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", tcc_expression, 2) ! /* A HANDLER wraps a catch handler for the HANDLER_TYPE. If this is CATCH_ALL_TYPE, then the handler catches all types. The declaration of the catch variable is in HANDLER_PARMS, and the body block in HANDLER_BODY. */ ! DEFTREECODE (HANDLER, "handler", tcc_expression, 2) /* A MUST_NOT_THROW_EXPR wraps an expression that may not throw, and must call terminate if it does. */ ! DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", tcc_expression, 1) ! /* A CLEANUP_STMT marks the point at which a declaration is fully ! constructed. The CLEANUP_EXPR is run on behalf of CLEANUP_DECL ! when CLEANUP_BODY completes. */ ! DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", tcc_expression, 3) ! /* Represents an 'if' statement. The operands are IF_COND, ! THEN_CLAUSE, and ELSE_CLAUSE, respectively. */ ! /* ??? It is currently still necessary to distinguish between IF_STMT ! and COND_EXPR for the benefit of templates. */ ! DEFTREECODE (IF_STMT, "if_stmt", tcc_expression, 3) ! DEFTREECODE (TAG_DEFN, "tag_defn", tcc_expression, 0) ! /* Template instantiation level node. ! ! TINST_DECL contains the original DECL node. ! TINST_LOCATION contains the location where the template is instantiated. ! TINST_IN_SYSTEM_HEADER_P is true if the location is in a system header. ! ! A stack of template instantiation nodes is kept through the TREE_CHAIN ! fields of these nodes. */ ! ! DEFTREECODE (TINST_LEVEL, "TINST_LEVEL", tcc_exceptional, 0) ! ! /* Represents an 'offsetof' expression during template expansion. */ ! DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1) /* Local variables: diff -Nrcpad gcc-3.4.3/gcc/cp/cp-tree.h gcc-4.0.0/gcc/cp/cp-tree.h *** gcc-3.4.3/gcc/cp/cp-tree.h Sat Oct 9 17:55:28 2004 --- gcc-4.0.0/gcc/cp/cp-tree.h Fri Apr 8 19:36:00 2005 *************** *** 1,6 **** /* Definitions for C++ parsing and type checking. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Definitions for C++ parsing and type checking. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 27,88 **** #include "function.h" #include "hashtab.h" #include "splay-tree.h" #include "varray.h" - #include "c-common.h" #include "name-lookup.h" - struct diagnostic_context; /* Usage of TREE_LANG_FLAG_?: ! 0: BINFO_MARKED (BINFO nodes). ! IDENTIFIER_MARKED (IDENTIFIER_NODEs) NEW_EXPR_USE_GLOBAL (in NEW_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR). TREE_INDIRECT_USING (in NAMESPACE_DECL). - ICS_USER_FLAG (in _CONV) CLEANUP_P (in TRY_BLOCK) AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR) PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF) ! PARMLIST_ELLIPSIS_P (in PARMLIST) DECL_PRETTY_FUNCTION_P (in VAR_DECL) KOENIG_LOOKUP_P (in CALL_EXPR) ! 1: IDENTIFIER_VIRTUAL_P. TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. 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). ICS_ELLIPSIS_FLAG (in _CONV) - BINFO_DEPENDENT_BASE_P (in BINFO) DECL_INITIALIZED_P (in VAR_DECL) ! 2: IDENTIFIER_OPNAME_P. ! TYPE_POLYMORPHIC_P (in _TYPE) ICS_THIS_FLAG (in _CONV) - BINFO_LOST_PRIMARY_P (in BINFO) - TREE_PARMLIST (in TREE_LIST) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) ! 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). ! BINFO_VTABLE_PATH_MARKED. ! BINFO_PUSHDECLS_MARKED. ! (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) ! 4: BINFO_NEW_VTABLE_MARKED. ! TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). - NEED_TEMPORARY_P (in REF_BIND, BASE_CONV) IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) 5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE) DECL_VTABLE_OR_VTT_P (in VAR_DECL) ! 6: For future expansion Usage of TYPE_LANG_FLAG_?: 0: TYPE_DEPENDENT_P 1: TYPE_HAS_CONSTRUCTOR. ! 2: TYPE_HAS_DESTRUCTOR. 3: TYPE_FOR_JAVA. 4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR 5: IS_AGGR_TYPE. --- 27,86 ---- #include "function.h" #include "hashtab.h" #include "splay-tree.h" + #include "vec.h" #include "varray.h" #include "c-common.h" #include "name-lookup.h" struct diagnostic_context; /* Usage of TREE_LANG_FLAG_?: ! 0: IDENTIFIER_MARKED (IDENTIFIER_NODEs) NEW_EXPR_USE_GLOBAL (in NEW_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR). TREE_INDIRECT_USING (in NAMESPACE_DECL). CLEANUP_P (in TRY_BLOCK) AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR) PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF) ! PAREN_STRING_LITERAL (in STRING_CST) DECL_PRETTY_FUNCTION_P (in VAR_DECL) KOENIG_LOOKUP_P (in CALL_EXPR) ! STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST). ! EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT) ! BIND_EXPR_TRY_BLOCK (in BIND_EXPR) ! TYPENAME_IS_ENUM_P (in TYPENAME_TYPE) ! REFERENCE_REF_P (in INDIRECT_EXPR) ! 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. DELETE_EXPR_USE_VEC (in DELETE_EXPR). (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out). ICS_ELLIPSIS_FLAG (in _CONV) DECL_INITIALIZED_P (in VAR_DECL) ! TYPENAME_IS_CLASS_P (in TYPENAME_TYPE) ! 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) ! STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST) ! 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) ! BIND_EXPR_BODY_BLOCK (in BIND_EXPR) ! 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) + DECL_TINFO_P (in VAR_DECL) 5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE) DECL_VTABLE_OR_VTT_P (in VAR_DECL) ! 6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE) ! DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL) ! TYPE_MARKED_P (in _TYPE) Usage of TYPE_LANG_FLAG_?: 0: TYPE_DEPENDENT_P 1: TYPE_HAS_CONSTRUCTOR. ! 2: Unused 3: TYPE_FOR_JAVA. 4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR 5: IS_AGGR_TYPE. *************** struct diagnostic_context; *** 95,122 **** 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) 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 (in a FIELD_DECL) DECL_VAR_MARKED_P (in a VAR_DECL) DECL_SELF_REFERENCE_P (in a TYPE_DECL) 5: DECL_INTERFACE_KNOWN. 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL). 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL). DECL_THUNK_P (in a member FUNCTION_DECL) Usage of language-independent fields in a language-dependent manner: - TREE_USED - This field is BINFO_INDIRECT_PRIMARY_P in a BINFO. - TYPE_ALIAS_SET This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so forth as a substitute for the mark bits provided in `lang_type'. At present, only the six low-order bits are used. ! TYPE_BINFO For an ENUMERAL_TYPE, this is ENUM_TEMPLATE_INFO. For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS --- 93,120 ---- 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_MEMBER_TEMPLATE_P (in TEMPLATE_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 (in a FIELD_DECL) DECL_VAR_MARKED_P (in a VAR_DECL) DECL_SELF_REFERENCE_P (in a TYPE_DECL) + DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL) 5: DECL_INTERFACE_KNOWN. 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL). + DECL_FIELD_IS_BASE (in FIELD_DECL) 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL). DECL_THUNK_P (in a member FUNCTION_DECL) Usage of language-independent fields in a language-dependent manner: TYPE_ALIAS_SET This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so forth as a substitute for the mark bits provided in `lang_type'. At present, only the six low-order bits are used. ! TYPE_LANG_SLOT_1 For an ENUMERAL_TYPE, this is ENUM_TEMPLATE_INFO. For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS *************** struct diagnostic_context; *** 132,138 **** 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. The BV_FN is the declaration for the virtual function itself. --- 130,136 ---- 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. The BV_FN is the declaration for the virtual function itself. *************** struct diagnostic_context; *** 157,219 **** /* Language-specific tree checkers. */ ! #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) ! ! #define VAR_OR_FUNCTION_DECL_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! enum tree_code const __c = TREE_CODE(__t); \ ! if (__c != VAR_DECL && __c != FUNCTION_DECL) \ ! tree_check_failed (__t, VAR_DECL, __FILE__, __LINE__, \ ! __FUNCTION__); \ ! __t; }) ! #define VAR_FUNCTION_OR_PARM_DECL_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! enum tree_code const __c = TREE_CODE(__t); \ ! if (__c != VAR_DECL \ ! && __c != FUNCTION_DECL \ ! && __c != PARM_DECL) \ ! tree_check_failed (__t, VAR_DECL, __FILE__, __LINE__, \ ! __FUNCTION__); \ ! __t; }) ! #define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! enum tree_code const __c = TREE_CODE(__t); \ ! if (__c != VAR_DECL \ ! && __c != FUNCTION_DECL \ ! && __c != TYPE_DECL \ ! && __c != TEMPLATE_DECL) \ ! tree_check_failed (__t, VAR_DECL, __FILE__, __LINE__, \ ! __FUNCTION__); \ ! __t; }) ! #define RECORD_OR_UNION_TYPE_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! enum tree_code const __c = TREE_CODE(__t); \ ! if (__c != RECORD_TYPE && __c != UNION_TYPE) \ ! tree_check_failed (__t, RECORD_TYPE, __FILE__, __LINE__, \ ! __FUNCTION__); \ ! __t; }) ! #define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! enum tree_code const __c = TREE_CODE(__t); \ ! if (__c != BOUND_TEMPLATE_TEMPLATE_PARM) \ ! tree_check_failed (__t, BOUND_TEMPLATE_TEMPLATE_PARM, \ ! __FILE__, __LINE__, __FUNCTION__); \ __t; }) ! ! #else /* not ENABLE_TREE_CHECKING, or not gcc */ ! ! #define VAR_OR_FUNCTION_DECL_CHECK(NODE) (NODE) ! #define VAR_FUNCTION_OR_PARM_DECL_CHECK(NODE) (NODE) ! #define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE) (NODE) ! #define RECORD_OR_UNION_TYPE_CHECK(NODE) (NODE) ! #define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) (NODE) ! #endif - /* Language-dependent contents of an identifier. */ --- 155,190 ---- /* Language-specific tree checkers. */ ! #define VAR_OR_FUNCTION_DECL_CHECK(NODE) \ ! TREE_CHECK2(NODE,VAR_DECL,FUNCTION_DECL) ! #define VAR_FUNCTION_OR_PARM_DECL_CHECK(NODE) \ ! TREE_CHECK3(NODE,VAR_DECL,FUNCTION_DECL,PARM_DECL) ! #define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE) \ ! TREE_CHECK4(NODE,VAR_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL) ! #define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \ ! TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM) ! #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) ! #define NON_THUNK_FUNCTION_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! if (TREE_CODE (__t) != FUNCTION_DECL && \ ! TREE_CODE (__t) != TEMPLATE_DECL && __t->decl.lang_specific \ ! && __t->decl.lang_specific->decl_flags.thunk_p) \ ! tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \ __t; }) ! #define THUNK_FUNCTION_CHECK(NODE) __extension__ \ ! ({ const tree __t = (NODE); \ ! if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl.lang_specific \ ! || !__t->decl.lang_specific->decl_flags.thunk_p) \ ! tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \ ! __t; }) ! #else ! #define NON_THUNK_FUNCTION_CHECK(NODE) (NODE) ! #define THUNK_FUNCTION_CHECK(NODE) (NODE) #endif /* Language-dependent contents of an identifier. */ *************** struct lang_identifier GTY(()) *** 222,232 **** struct c_common_identifier c_common; cxx_binding *namespace_bindings; cxx_binding *bindings; - tree class_value; tree class_template_info; tree label_value; - tree implicit_decl; - tree error_locus; }; /* In an IDENTIFIER_NODE, nonzero if this identifier is actually a --- 193,200 ---- *************** struct lang_identifier GTY(()) *** 238,251 **** #define LANG_IDENTIFIER_CAST(NODE) \ ((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE)) ! typedef struct template_parm_index_s GTY(()) { struct tree_common common; HOST_WIDE_INT index; HOST_WIDE_INT level; HOST_WIDE_INT orig_level; tree decl; ! } template_parm_index; struct ptrmem_cst GTY(()) { --- 206,229 ---- #define LANG_IDENTIFIER_CAST(NODE) \ ((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE)) ! struct template_parm_index_s GTY(()) { struct tree_common common; HOST_WIDE_INT index; HOST_WIDE_INT level; HOST_WIDE_INT orig_level; tree decl; ! }; ! typedef struct template_parm_index_s template_parm_index; ! ! struct tinst_level_s GTY(()) ! { ! struct tree_common common; ! tree decl; ! location_t locus; ! int in_system_header_p; ! }; ! typedef struct tinst_level_s * tinst_level_t; struct ptrmem_cst GTY(()) { *************** typedef struct ptrmem_cst * ptrmem_cst_t *** 268,273 **** --- 246,267 ---- #define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (TRY_BLOCK_CHECK (NODE)) + #define BIND_EXPR_TRY_BLOCK(NODE) \ + TREE_LANG_FLAG_0 (BIND_EXPR_CHECK (NODE)) + + /* Used to mark the block around the member initializers and cleanups. */ + #define BIND_EXPR_BODY_BLOCK(NODE) \ + TREE_LANG_FLAG_3 (BIND_EXPR_CHECK (NODE)) + + #define STATEMENT_LIST_NO_SCOPE(NODE) \ + TREE_LANG_FLAG_0 (STATEMENT_LIST_CHECK (NODE)) + #define STATEMENT_LIST_TRY_BLOCK(NODE) \ + TREE_LANG_FLAG_2 (STATEMENT_LIST_CHECK (NODE)) + + /* Marks the result of a statement expression. */ + #define EXPR_STMT_STMT_EXPR_RESULT(NODE) \ + TREE_LANG_FLAG_0 (EXPR_STMT_CHECK (NODE)) + /* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual sense of `same'. */ #define same_type_p(TYPE1, TYPE2) \ *************** typedef struct ptrmem_cst * ptrmem_cst_t *** 280,286 **** /* 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 nonzero iff NODE is a declaration for the global function `main'. */ --- 274,280 ---- /* Nonzero if we are presently building a statement tree, rather than expanding each statement as we encounter it. */ ! #define building_stmt_tree() (cur_stmt_list != NULL_TREE) /* Returns nonzero iff NODE is a declaration for the global function `main'. */ *************** struct tree_overload GTY(()) *** 319,326 **** a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */ #define BASELINK_FUNCTIONS(NODE) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->functions) ! /* 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) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->access_binfo) --- 313,320 ---- a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */ #define BASELINK_FUNCTIONS(NODE) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->functions) ! /* 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) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->access_binfo) *************** struct tree_baselink GTY(()) *** 340,354 **** tree access_binfo; }; ! #define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c) ! ! struct tree_wrapper GTY(()) ! { ! struct tree_common common; ! struct z_candidate *z_c; ! }; ! ! /* The different kinds of ids that we ecounter. */ typedef enum cp_id_kind { --- 334,340 ---- tree access_binfo; }; ! /* The different kinds of ids that we encounter. */ typedef enum cp_id_kind { *************** typedef enum cp_id_kind *** 381,399 **** #define IDENTIFIER_BINDING(NODE) \ (LANG_IDENTIFIER_CAST (NODE)->bindings) - /* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or - NULL_TREE if there is no binding. */ - #define IDENTIFIER_VALUE(NODE) \ - (IDENTIFIER_BINDING (NODE) ? IDENTIFIER_BINDING (NODE)->value : NULL) - - /* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current - class, and IDENTIFIER_CLASS_VALUE is the value binding. This is - just a pointer to the VALUE field of one of the bindings in the - IDENTIFIER_BINDINGs list, so any time that this is non-NULL so is - IDENTIFIER_BINDING. */ - #define IDENTIFIER_CLASS_VALUE(NODE) \ - (LANG_IDENTIFIER_CAST (NODE)->class_value) - /* 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 --- 367,372 ---- *************** typedef enum cp_id_kind *** 408,423 **** #define SET_IDENTIFIER_LABEL_VALUE(NODE, VALUE) \ IDENTIFIER_LABEL_VALUE (NODE) = (VALUE) - #define IDENTIFIER_IMPLICIT_DECL(NODE) \ - (LANG_IDENTIFIER_CAST (NODE)->implicit_decl) - #define SET_IDENTIFIER_IMPLICIT_DECL(NODE, VALUE) \ - IDENTIFIER_IMPLICIT_DECL (NODE) = (VALUE) - - #define IDENTIFIER_ERROR_LOCUS(NODE) \ - (LANG_IDENTIFIER_CAST (NODE)->error_locus) - #define SET_IDENTIFIER_ERROR_LOCUS(NODE, VALUE) \ - IDENTIFIER_ERROR_LOCUS (NODE) = (VALUE) - /* Nonzero if this identifier is used as a virtual function name somewhere (optimizes searches). */ #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1 (NODE) --- 381,386 ---- *************** typedef enum cp_id_kind *** 436,449 **** #define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \ TREE_LANG_FLAG_3 (NODE) /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ #define C_TYPE_FIELDS_READONLY(TYPE) \ (LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly) - /* Store a value in that field. */ - #define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \ - (TREE_COMPLEXITY (EXP) = (int)(CODE)) - /* The tokens stored in the default argument. */ #define DEFARG_TOKENS(NODE) \ --- 399,414 ---- #define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \ TREE_LANG_FLAG_3 (NODE) + /* True iff NAME is the DECL_ASSEMBLER_NAME for an entity with vague + linkage which the prelinker has assigned to this translation + unit. */ + #define IDENTIFIER_REPO_CHOSEN(NAME) \ + (TREE_LANG_FLAG_6 (NAME)) + /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ #define C_TYPE_FIELDS_READONLY(TYPE) \ (LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly) /* The tokens stored in the default argument. */ #define DEFARG_TOKENS(NODE) \ *************** enum cp_tree_node_structure_enum { *** 459,464 **** --- 424,430 ---- TS_CP_GENERIC, TS_CP_IDENTIFIER, TS_CP_TPI, + TS_CP_TINST_LEVEL, TS_CP_PTRMEM, TS_CP_BINDING, TS_CP_OVERLOAD, *************** union lang_tree_node GTY((desc ("cp_tree *** 475,484 **** 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_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink; - struct tree_wrapper GTY ((tag ("TS_CP_WRAPPER"))) wrapper; struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg; struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier; }; --- 441,450 ---- 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 tinst_level_s GTY ((tag ("TS_CP_TINST_LEVEL"))) tinst_level; struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem; struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload; struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink; struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg; struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier; }; *************** enum cp_tree_index *** 520,528 **** CPTI_VTBL_PTR_TYPE, CPTI_STD, CPTI_ABI, ! CPTI_TYPE_INFO_TYPE, CPTI_TYPE_INFO_PTR_TYPE, - CPTI_TYPE_INFO_REF_TYPE, CPTI_ABORT_FNDECL, CPTI_GLOBAL_DELETE_FNDECL, CPTI_AGGR_TAG, --- 486,493 ---- CPTI_VTBL_PTR_TYPE, CPTI_STD, CPTI_ABI, ! CPTI_CONST_TYPE_INFO_TYPE, CPTI_TYPE_INFO_PTR_TYPE, CPTI_ABORT_FNDECL, CPTI_GLOBAL_DELETE_FNDECL, CPTI_AGGR_TAG, *************** extern GTY(()) tree cp_global_trees[CPTI *** 598,606 **** #define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE] #define std_node cp_global_trees[CPTI_STD] #define abi_node cp_global_trees[CPTI_ABI] ! #define type_info_type_node cp_global_trees[CPTI_TYPE_INFO_TYPE] #define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE] - #define type_info_ref_type cp_global_trees[CPTI_TYPE_INFO_REF_TYPE] #define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL] #define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL] #define current_aggr cp_global_trees[CPTI_AGGR_TAG] --- 563,570 ---- #define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE] #define std_node cp_global_trees[CPTI_STD] #define abi_node cp_global_trees[CPTI_ABI] ! #define const_type_info_type_node cp_global_trees[CPTI_CONST_TYPE_INFO_TYPE] #define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE] #define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL] #define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL] #define current_aggr cp_global_trees[CPTI_AGGR_TAG] *************** extern GTY(()) tree cp_global_trees[CPTI *** 687,693 **** struct saved_scope GTY(()) { ! cxx_saved_binding *old_bindings; tree old_namespace; tree decl_ns_list; tree class_name; --- 651,657 ---- struct saved_scope GTY(()) { ! VEC(cxx_saved_binding) *old_bindings; tree old_namespace; tree decl_ns_list; tree class_name; *************** struct saved_scope GTY(()) *** 697,704 **** varray_type lang_base; tree lang_name; tree template_parms; ! tree x_previous_class_type; ! tree x_previous_class_values; tree x_saved_tree; HOST_WIDE_INT x_processing_template_decl; --- 661,667 ---- varray_type lang_base; tree lang_name; tree template_parms; ! struct cp_binding_level *x_previous_class_level; tree x_saved_tree; HOST_WIDE_INT x_processing_template_decl; *************** struct saved_scope GTY(()) *** 751,766 **** #define processing_specialization scope_chain->x_processing_specialization #define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation ! /* _TYPE: the previous type that was a class */ ! ! #define previous_class_type scope_chain->x_previous_class_type ! ! /* This is a copy of the class_shadowed list of the previous class ! binding contour when at global scope. It's used to reset ! IDENTIFIER_CLASS_VALUEs when entering another class scope (i.e. a ! cache miss). */ ! #define previous_class_values scope_chain->x_previous_class_values /* A list of private types mentioned, for deferred access checking. */ --- 714,723 ---- #define processing_specialization scope_chain->x_processing_specialization #define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation ! /* The cached class binding level, from the most recently exited ! class, or NULL if none. */ ! #define previous_class_level scope_chain->x_previous_class_level /* A list of private types mentioned, for deferred access checking. */ *************** struct language_function GTY(()) *** 772,778 **** { struct c_language_function base; ! tree x_dtor_label; tree x_current_class_ptr; tree x_current_class_ref; tree x_eh_spec_block; --- 729,735 ---- { struct c_language_function base; ! tree x_cdtor_label; tree x_current_class_ptr; tree x_current_class_ref; tree x_eh_spec_block; *************** struct language_function GTY(()) *** 793,810 **** struct named_label_list *x_named_labels; struct cp_binding_level *bindings; varray_type x_local_names; - - const char *cannot_inline; }; /* The current C++-specific per-function global variables. */ #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. */ ! #define dtor_label cp_function_chain->x_dtor_label /* When we're processing a member function, current_class_ptr is the PARM_DECL for the `this' pointer. The current_class_ref is an --- 750,767 ---- struct named_label_list *x_named_labels; struct cp_binding_level *bindings; varray_type x_local_names; }; /* The current C++-specific per-function global variables. */ #define cp_function_chain (cfun->language) ! /* In a constructor destructor, the point at which all derived class ! destroying/construction has been has been done. Ie. just before a ! constructor returns, or before any base class destroying will be done ! in a destructor. */ ! #define cdtor_label cp_function_chain->x_cdtor_label /* When we're processing a member function, current_class_ptr is the PARM_DECL for the `this' pointer. The current_class_ref is an *************** struct language_function GTY(()) *** 875,887 **** #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 - we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN - 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; /* C++ language-specific tree codes. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, --- 832,837 ---- *************** enum cplus_tree_code { *** 894,900 **** #define cp_stmt_codes \ CTOR_INITIALIZER, TRY_BLOCK, HANDLER, \ ! EH_SPEC_BLOCK, USING_STMT, TAG_DEFN enum languages { lang_c, lang_cplusplus, lang_java }; --- 844,851 ---- #define cp_stmt_codes \ CTOR_INITIALIZER, TRY_BLOCK, HANDLER, \ ! EH_SPEC_BLOCK, USING_STMT, TAG_DEFN, \ ! IF_STMT, CLEANUP_STMT enum languages { lang_c, lang_cplusplus, lang_java }; *************** enum languages { lang_c, lang_cplusplus, *** 905,915 **** #define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE))) #define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE))) - #define TYPE_ASSEMBLER_NAME_STRING(NODE) \ - (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) - #define TYPE_ASSEMBLER_NAME_LENGTH(NODE) \ - (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) - /* Nonzero if NODE has no name for linkage purposes. */ #define TYPE_ANONYMOUS_P(NODE) \ (TAGGED_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE))) --- 856,861 ---- *************** enum languages { lang_c, lang_cplusplus, *** 921,927 **** for template type parameters, typename types, and instantiated template template parameters. Despite its name, this macro has nothing to do with the definition of aggregate given ! in the standard. Think of this macro as MAYBE_CLASS_TYPE_P. */ #define IS_AGGR_TYPE(T) \ (TREE_CODE (T) == TEMPLATE_TYPE_PARM \ || TREE_CODE (T) == TYPENAME_TYPE \ --- 867,874 ---- for template type parameters, typename types, and instantiated template template parameters. Despite its name, this macro has nothing to do with the definition of aggregate given ! in the standard. Think of this macro as MAYBE_CLASS_TYPE_P. Keep ! these checks in ascending code order. */ #define IS_AGGR_TYPE(T) \ (TREE_CODE (T) == TEMPLATE_TYPE_PARM \ || TREE_CODE (T) == TYPENAME_TYPE \ *************** enum languages { lang_c, lang_cplusplus, *** 937,945 **** /* Nonzero if T is a class type. Zero for template type parameters, typename types, and so forth. */ #define CLASS_TYPE_P(T) \ ! (IS_AGGR_TYPE_CODE (TREE_CODE (T)) && IS_AGGR_TYPE (T)) ! #define IS_AGGR_TYPE_CODE(T) ((T) == RECORD_TYPE || (T) == UNION_TYPE) #define TAGGED_TYPE_P(T) \ (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) --- 884,894 ---- /* Nonzero if T is a class type. Zero for template type parameters, typename types, and so forth. */ #define CLASS_TYPE_P(T) \ ! (IS_AGGR_TYPE_CODE (TREE_CODE (T)) && TYPE_LANG_FLAG_5 (T)) ! /* Keep these checks in ascending code order. */ ! #define IS_AGGR_TYPE_CODE(T) \ ! ((T) == RECORD_TYPE || (T) == UNION_TYPE) #define TAGGED_TYPE_P(T) \ (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) *************** enum languages { lang_c, lang_cplusplus, *** 999,1014 **** /* 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) != 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) != 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) \ ! != 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. */ --- 948,973 ---- /* Nonzero iff TYPE is uniquely derived from PARENT. Ignores accessibility. */ #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \ ! (lookup_base ((TYPE), (PARENT), ba_unique | 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_ignore_scope | ba_check | ba_quiet, \ ! NULL) != NULL_TREE) ! ! /* Gives the visibility specification for a class type. */ ! #define CLASSTYPE_VISIBILITY(TYPE) \ ! DECL_VISIBILITY (TYPE_NAME (TYPE)) ! #define CLASSTYPE_VISIBILITY_SPECIFIED(TYPE) \ ! DECL_VISIBILITY_SPECIFIED (TYPE_NAME (TYPE)) ! ! typedef struct tree_pair_s GTY (()) ! { ! tree purpose; ! tree value; ! } tree_pair_s; ! typedef tree_pair_s *tree_pair_p; ! DEF_VEC_GC_O (tree_pair_s); ! /* 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(()) *** 1019,1028 **** BOOL_BITFIELD has_type_conversion : 1; BOOL_BITFIELD has_init_ref : 1; BOOL_BITFIELD has_default_ctor : 1; - BOOL_BITFIELD uses_multiple_inheritance : 1; BOOL_BITFIELD const_needs_init : 1; BOOL_BITFIELD ref_needs_init : 1; BOOL_BITFIELD has_const_assign_ref : 1; }; /* This structure provides additional information above and beyond --- 978,988 ---- BOOL_BITFIELD has_type_conversion : 1; BOOL_BITFIELD has_init_ref : 1; BOOL_BITFIELD has_default_ctor : 1; BOOL_BITFIELD const_needs_init : 1; BOOL_BITFIELD ref_needs_init : 1; BOOL_BITFIELD has_const_assign_ref : 1; + + BOOL_BITFIELD spare : 1; }; /* This structure provides additional information above and beyond *************** struct lang_type_header GTY(()) *** 1041,1047 **** struct lang_type_class GTY(()) { struct lang_type_header h; ! unsigned char align; unsigned has_mutable : 1; --- 1001,1007 ---- struct lang_type_class GTY(()) { struct lang_type_header h; ! unsigned char align; unsigned has_mutable : 1; *************** struct lang_type_class GTY(()) *** 1061,1083 **** unsigned non_zero_init : 1; unsigned empty_p : 1; - unsigned marks: 6; unsigned vec_new_uses_cookie : 1; unsigned declared_class : 1; ! unsigned being_defined : 1; unsigned redefined : 1; unsigned debug_requested : 1; - unsigned use_template : 2; unsigned fields_readonly : 1; unsigned ptrmemfunc_flag : 1; unsigned was_anonymous : 1; - unsigned has_real_assign_ref : 1; unsigned has_const_init_ref : 1; unsigned has_complex_init_ref : 1; unsigned has_complex_assign_ref : 1; - unsigned has_abstract_assign_ref : 1; unsigned non_aggregate : 1; unsigned java_interface : 1; --- 1021,1046 ---- unsigned non_zero_init : 1; unsigned empty_p : 1; unsigned vec_new_uses_cookie : 1; unsigned declared_class : 1; ! unsigned diamond_shaped : 1; ! unsigned repeated_base : 1; unsigned being_defined : 1; unsigned redefined : 1; unsigned debug_requested : 1; unsigned fields_readonly : 1; + + unsigned use_template : 2; unsigned ptrmemfunc_flag : 1; unsigned was_anonymous : 1; + unsigned lazy_default_ctor : 1; + unsigned lazy_copy_ctor : 1; + unsigned lazy_assignment_op : 1; + unsigned lazy_destructor : 1; unsigned has_const_init_ref : 1; unsigned has_complex_init_ref : 1; unsigned has_complex_assign_ref : 1; unsigned non_aggregate : 1; unsigned java_interface : 1; *************** struct lang_type_class GTY(()) *** 1088,1110 **** /* 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 : 9; tree primary_base; ! tree vfields; ! tree vcall_indices; tree vtables; tree typeinfo_var; ! tree vbases; binding_table nested_udts; tree as_base; ! tree pure_virtuals; tree friend_classes; ! tree GTY ((reorder ("resort_type_method_vec"))) methods; tree key_method; tree decl_list; tree template_info; tree befriending_classes; }; struct lang_type_ptrmem GTY(()) --- 1051,1076 ---- /* 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 : 11; tree primary_base; ! VEC (tree_pair_s) *vcall_indices; tree vtables; tree typeinfo_var; ! VEC (tree) *vbases; binding_table nested_udts; tree as_base; ! VEC (tree) *pure_virtuals; tree friend_classes; ! VEC (tree) * GTY((reorder ("resort_type_method_vec"))) methods; tree key_method; tree decl_list; tree template_info; tree befriending_classes; + /* In a RECORD_TYPE, information specific to Objective-C++, such + as a list of adopted protocols or a pointer to a corresponding + @interface. See objc/objc-act.h for details. */ + tree objc_info; }; struct lang_type_ptrmem GTY(()) *************** struct lang_type_ptrmem GTY(()) *** 1115,1123 **** 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; --- 1081,1089 ---- struct lang_type GTY(()) { ! union lang_type_u { ! struct lang_type_header GTY((skip (""))) 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; *************** struct lang_type GTY(()) *** 1155,1161 **** /* Fields used for storing information before the class is defined. After the class is defined, these fields hold other information. */ ! /* List of friends which were defined inline in this class definition. */ #define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE) /* Nonzero for _CLASSTYPE means that operator delete is defined. */ --- 1121,1128 ---- /* Fields used for storing information before the class is defined. After the class is defined, these fields hold other information. */ ! /* VEC(tree) of friends which were defined inline in this class ! definition. */ #define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE) /* Nonzero for _CLASSTYPE means that operator delete is defined. */ *************** struct lang_type GTY(()) *** 1173,1180 **** --- 1140,1170 ---- #define TYPE_HAS_CONVERSION(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion) + /* Nonzero means that NODE (a class type) has a default constructor -- + but that it has not yet been declared. */ + #define CLASSTYPE_LAZY_DEFAULT_CTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_default_ctor) + + /* Nonzero means that NODE (a class type) has a copy constructor -- + but that it has not yet been declared. */ + #define CLASSTYPE_LAZY_COPY_CTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_copy_ctor) + + /* Nonzero means that NODE (a class type) has an assignment operator + -- but that it has not yet been declared. */ + #define CLASSTYPE_LAZY_ASSIGNMENT_OP(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_assignment_op) + + /* Nonzero means that NODE (a class type) has a destructor -- but that + it has not yet been declared. */ + #define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor) + /* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ #define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref) + + /* True iff the class type NODE has an "operator =" whose parameter + has a parameter of type "const X&". */ #define TYPE_HAS_CONST_ASSIGN_REF(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_const_assign_ref) *************** struct lang_type GTY(()) *** 1199,1214 **** convenient, don't reprocess any methods that appear in its redefinition. */ #define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined) ! /* 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) \ ! (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 --- 1189,1206 ---- convenient, don't reprocess any methods that appear in its redefinition. */ #define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined) ! /* Mark bits for repeated base checks. */ ! #define TYPE_MARKED_P(NODE) TREE_LANG_FLAG_6 (TYPE_CHECK (NODE)) ! /* Non-zero if the class NODE has multiple paths to the same (virtual) ! base object. */ ! #define CLASSTYPE_DIAMOND_SHAPED_P(NODE) \ ! (LANG_TYPE_CLASS_CHECK(NODE)->diamond_shaped) ! ! /* Non-zero if the class NODE has multiple instances of the same base ! type. */ ! #define CLASSTYPE_REPEATED_BASE_P(NODE) \ ! (LANG_TYPE_CLASS_CHECK(NODE)->repeated_base) /* The member function with which the vtable will be emitted: the first noninline non-pure-virtual member function. NULL_TREE *************** struct lang_type GTY(()) *** 1248,1300 **** /* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These are the constructors that take an in-charge parameter. */ #define CLASSTYPE_CONSTRUCTORS(NODE) \ ! (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT)) /* A FUNCTION_DECL for the destructor for NODE. These are the ! destructors that take an in-charge parameter. */ #define CLASSTYPE_DESTRUCTORS(NODE) \ ! (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT)) ! ! /* Mark bits for depth-first and breath-first searches. */ ! ! /* Get the value of the Nth mark bit. */ ! #define CLASSTYPE_MARKED_N(NODE, N) \ ! (((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) (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) (LANG_TYPE_CLASS_CHECK (NODE)->marks &= ~(1 << (N))) \ ! : (void) (TYPE_ALIAS_SET (NODE) &= ~(1 << (N)))) ! ! /* Get the value of the mark bits. */ ! #define CLASSTYPE_MARKED(NODE) CLASSTYPE_MARKED_N (NODE, 0) ! #define CLASSTYPE_MARKED2(NODE) CLASSTYPE_MARKED_N (NODE, 1) ! #define CLASSTYPE_MARKED3(NODE) CLASSTYPE_MARKED_N (NODE, 2) ! #define CLASSTYPE_MARKED4(NODE) CLASSTYPE_MARKED_N (NODE, 3) ! #define CLASSTYPE_MARKED5(NODE) CLASSTYPE_MARKED_N (NODE, 4) ! #define CLASSTYPE_MARKED6(NODE) CLASSTYPE_MARKED_N (NODE, 5) ! ! /* Macros to modify the above flags */ ! #define SET_CLASSTYPE_MARKED(NODE) SET_CLASSTYPE_MARKED_N (NODE, 0) ! #define CLEAR_CLASSTYPE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 0) ! #define SET_CLASSTYPE_MARKED2(NODE) SET_CLASSTYPE_MARKED_N (NODE, 1) ! #define CLEAR_CLASSTYPE_MARKED2(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 1) ! #define SET_CLASSTYPE_MARKED3(NODE) SET_CLASSTYPE_MARKED_N (NODE, 2) ! #define CLEAR_CLASSTYPE_MARKED3(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 2) ! #define SET_CLASSTYPE_MARKED4(NODE) SET_CLASSTYPE_MARKED_N (NODE, 3) ! #define CLEAR_CLASSTYPE_MARKED4(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 3) ! #define SET_CLASSTYPE_MARKED5(NODE) SET_CLASSTYPE_MARKED_N (NODE, 4) ! #define CLEAR_CLASSTYPE_MARKED5(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 4) ! #define SET_CLASSTYPE_MARKED6(NODE) SET_CLASSTYPE_MARKED_N (NODE, 5) ! #define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 5) /* A dictionary of the nested user-defined-types (class-types, or enums) found within this class. This table includes nested member class --- 1240,1255 ---- /* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These are the constructors that take an in-charge parameter. */ #define CLASSTYPE_CONSTRUCTORS(NODE) \ ! (VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT)) /* A FUNCTION_DECL for the destructor for NODE. These are the ! destructors that take an in-charge parameter. If ! CLASSTYPE_LAZY_DESTRUCTOR is true, then this entry will be NULL ! until the destructor is created with lazily_declare_fn. */ #define CLASSTYPE_DESTRUCTORS(NODE) \ ! (CLASSTYPE_METHOD_VEC (NODE) \ ! ? VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT) \ ! : NULL_TREE) /* A dictionary of the nested user-defined-types (class-types, or enums) found within this class. This table includes nested member class *************** struct lang_type GTY(()) *** 1313,1333 **** #define CLASSTYPE_PRIMARY_BINFO(NODE) \ (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 order. (In other words, these bases appear in the order that they should be initialized.) */ #define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases) - /* Number of direct baseclasses of NODE. */ - #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_SIZE (CLASSTYPE_AS_BASE (NODE)) --- 1268,1291 ---- #define CLASSTYPE_PRIMARY_BINFO(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->primary_base) ! /* A vector of BINFOs for the direct and indirect virtual base classes that this type uses in a post-order depth-first left-to-right order. (In other words, these bases appear in the order that they should be initialized.) */ #define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases) /* 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) + /* True iff NODE is the CLASSTYPE_AS_BASE version of some type. */ + + #define IS_FAKE_BASE_TYPE(NODE) \ + (TREE_CODE (NODE) == RECORD_TYPE \ + && TYPE_CONTEXT (NODE) && CLASS_TYPE_P (TYPE_CONTEXT (NODE)) \ + && CLASSTYPE_AS_BASE (TYPE_CONTEXT (NODE)) == (NODE)) + /* 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_SIZE (CLASSTYPE_AS_BASE (NODE)) *************** struct lang_type GTY(()) *** 1339,1352 **** #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) (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) (LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals) /* Nonzero means that this type has an X() constructor. */ #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \ --- 1297,1312 ---- #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) \ ! (LANG_TYPE_CLASS_CHECK (NODE)->java_interface) ! /* A VEC(tree) 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) \ ! (LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals) /* Nonzero means that this type has an X() constructor. */ #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \ *************** struct lang_type GTY(()) *** 1420,1426 **** way or the other. */ #define CLASSTYPE_INTERFACE_KNOWN(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown == 0) ! /* The opposite of CLASSTYPE_INTERFANCE_KNOWN. */ #define CLASSTYPE_INTERFACE_UNKNOWN(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown) --- 1380,1386 ---- way or the other. */ #define CLASSTYPE_INTERFACE_KNOWN(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown == 0) ! /* The opposite of CLASSTYPE_INTERFACE_KNOWN. */ #define CLASSTYPE_INTERFACE_UNKNOWN(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown) *************** struct lang_type GTY(()) *** 1437,1520 **** /* Additional macros for inheritance information. */ - /* The BINFO_INHERITANCE_CHAIN is used opposite to the description in - gcc/tree.h. In particular if D is non-virtually derived from B - then the BINFO for B (in D) will have a BINFO_INHERITANCE_CHAIN - pointing to D. If D is virtually derived, its - BINFO_INHERITANCE_CHAIN will point to the most derived binfo. In - tree.h, this pointer is described as pointing in other - direction. The binfos of virtual bases are shared. */ - - /* Nonzero means marked by DFS or BFS search. */ - #define BINFO_MARKED(NODE) TREE_LANG_FLAG_0 (NODE) - /* Nonzero means that this class is on a path leading to a new vtable. */ ! #define BINFO_VTABLE_PATH_MARKED(NODE) TREE_LANG_FLAG_3 (NODE) /* Nonzero means B (a BINFO) has its own vtable. Any copies will not have this flag set. */ ! #define BINFO_NEW_VTABLE_MARKED(B) (TREE_LANG_FLAG_4 (B)) /* Any subobject that needs a new vtable must have a vptr and must not be a non-virtual primary base (since it would then use the vtable from a derived class and never become non-primary.) */ #define SET_BINFO_NEW_VTABLE_MARKED(B) \ (BINFO_NEW_VTABLE_MARKED (B) = 1, \ ! my_friendly_assert (!BINFO_PRIMARY_P (B) \ ! || TREE_VIA_VIRTUAL (B), 20000517), \ ! my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE, \ ! 20000517)) ! ! /* Nonzero means this class has done dfs_pushdecls. */ ! #define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE) ! ! /* Nonzero if this BINFO is a primary base class. Note, this can be ! set for non-canonical virtual bases. For a virtual primary base ! you might also need to check whether it is canonical. */ ! ! #define BINFO_PRIMARY_P(NODE) \ ! (BINFO_PRIMARY_BASE_OF (NODE) != NULL_TREE) ! ! /* The index in the VTT where this subobject's sub-VTT can be found. ! NULL_TREE if there is no sub-VTT. */ ! #define BINFO_SUBVTT_INDEX(NODE) TREE_VEC_ELT (NODE, BINFO_ELTS + 0) ! ! /* The index in the VTT where the vptr for this subobject can be ! found. NULL_TREE if there is no secondary vptr in the VTT. */ ! #define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT (NODE, BINFO_ELTS + 1) ! ! /* The binfo of which NODE is a primary base. (This is different from ! BINFO_INHERITANCE_CHAIN for virtual base because a virtual base is ! sometimes a primary base for a class for which it is not an ! immediate base.) */ ! #define BINFO_PRIMARY_BASE_OF(NODE) TREE_VEC_ELT (NODE, BINFO_ELTS + 2) ! ! /* C++ binfos have 3 additional entries. */ ! ! #define BINFO_LANG_ELTS (BINFO_ELTS + 3) /* Nonzero if this binfo is for a dependent base - one that should not be searched. */ ! #define BINFO_DEPENDENT_BASE_P(NODE) TREE_LANG_FLAG_1(NODE) /* Nonzero if this binfo has lost its primary base binfo (because that is a nearly-empty virtual base that has been taken by some other base in the complete hierarchy. */ ! #define BINFO_LOST_PRIMARY_P(NODE) TREE_LANG_FLAG_2 (NODE) ! /* Nonzero if this binfo is an indirect primary base, i.e. a virtual ! base that is a primary base of some of other class in the ! hierarchy. */ ! #define BINFO_INDIRECT_PRIMARY_P(NODE) TREE_USED (NODE) /* 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) --- 1397,1445 ---- /* Additional macros for inheritance information. */ /* Nonzero means that this class is on a path leading to a new vtable. */ ! #define BINFO_VTABLE_PATH_MARKED(NODE) BINFO_FLAG_1 (NODE) /* Nonzero means B (a BINFO) has its own vtable. Any copies will not have this flag set. */ ! #define BINFO_NEW_VTABLE_MARKED(B) (BINFO_FLAG_2 (B)) ! ! /* Compare a BINFO_TYPE with another type for equality. For a binfo, ! this is functionally equivalent to using same_type_p, but ! measurably faster. At least one of the arguments must be a ! BINFO_TYPE. The other can be a BINFO_TYPE or a regular type. If ! BINFO_TYPE(T) ever stops being the main variant of the class the ! binfo is for, this macro must change. */ ! #define SAME_BINFO_TYPE_P(A, B) ((A) == (B)) /* Any subobject that needs a new vtable must have a vptr and must not be a non-virtual primary base (since it would then use the vtable from a derived class and never become non-primary.) */ #define SET_BINFO_NEW_VTABLE_MARKED(B) \ (BINFO_NEW_VTABLE_MARKED (B) = 1, \ ! gcc_assert (!BINFO_PRIMARY_P (B) || BINFO_VIRTUAL_P (B)), \ ! gcc_assert (TYPE_VFIELD (BINFO_TYPE (B)))) /* Nonzero if this binfo is for a dependent base - one that should not be searched. */ ! #define BINFO_DEPENDENT_BASE_P(NODE) BINFO_FLAG_3 (NODE) /* Nonzero if this binfo has lost its primary base binfo (because that is a nearly-empty virtual base that has been taken by some other base in the complete hierarchy. */ ! #define BINFO_LOST_PRIMARY_P(NODE) BINFO_FLAG_4 (NODE) ! /* Nonzero if this BINFO is a primary base class. */ ! #define BINFO_PRIMARY_P(NODE) BINFO_FLAG_5(NODE) /* Used by various search routines. */ #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE) ! /* A VEC(tree_pair_s) of the vcall indices associated with the class ! NODE. The PURPOSE of each element is a FUNCTION_DECL for a virtual ! function. The 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) *************** struct lang_type GTY(()) *** 1531,1545 **** /* Accessor macros for the vfield slots in structures. */ - /* 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). */ --- 1456,1461 ---- *************** struct lang_type GTY(()) *** 1565,1582 **** #define BV_FN(NODE) (TREE_VALUE (NODE)) - /* Nonzero for TREE_LIST node means that this list of things - is a list of parameters, as opposed to a list of expressions. */ - #define TREE_PARMLIST(NODE) (TREE_LANG_FLAG_2 (NODE)) - - /* Nonzero for a parmlist means that this parmlist ended in ... */ - #define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE) - /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE will be NULL_TREE to indicate a throw specification of `()', or no exceptions allowed. */ ! #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_BINFO (NODE) /* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */ #define TYPE_NOTHROW_P(NODE) \ --- 1481,1491 ---- #define BV_FN(NODE) (TREE_VALUE (NODE)) /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE will be NULL_TREE to indicate a throw specification of `()', or no exceptions allowed. */ ! #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_LANG_SLOT_1 (NODE) /* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */ #define TYPE_NOTHROW_P(NODE) \ *************** struct lang_type GTY(()) *** 1591,1606 **** /* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or a lang_decl (which has lang_decl_flags as its initial prefix). This macro is nonzero for tree nodes whose DECL_LANG_SPECIFIC is ! the full lang_decl, and not just lang_decl_flags. */ ! #define CAN_HAVE_FULL_LANG_DECL_P(NODE) \ ! (!(TREE_CODE (NODE) == VAR_DECL \ ! || TREE_CODE (NODE) == CONST_DECL \ ! || TREE_CODE (NODE) == FIELD_DECL \ || TREE_CODE (NODE) == USING_DECL)) struct lang_decl_flags GTY(()) { ! ENUM_BITFIELD(languages) language : 8; unsigned operator_attr : 1; unsigned constructor_attr : 1; --- 1500,1520 ---- /* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or a lang_decl (which has lang_decl_flags as its initial prefix). This macro is nonzero for tree nodes whose DECL_LANG_SPECIFIC is ! the full lang_decl, and not just lang_decl_flags. Keep these ! checks in ascending code order. */ ! #define CAN_HAVE_FULL_LANG_DECL_P(NODE) \ ! (!(TREE_CODE (NODE) == FIELD_DECL \ ! || TREE_CODE (NODE) == VAR_DECL \ ! || TREE_CODE (NODE) == CONST_DECL \ || TREE_CODE (NODE) == USING_DECL)) struct lang_decl_flags GTY(()) { ! ENUM_BITFIELD(languages) language : 4; ! unsigned global_ctor_p : 1; ! unsigned global_dtor_p : 1; ! unsigned anticipated_p : 1; ! unsigned template_conv_p : 1; unsigned operator_attr : 1; unsigned constructor_attr : 1; *************** struct lang_decl_flags GTY(()) *** 1615,1657 **** unsigned use_template : 2; unsigned nonconverting : 1; unsigned not_really_extern : 1; - unsigned needs_final_overrider : 1; unsigned initialized_in_class : 1; unsigned assignment_operator_p : 1; - - unsigned global_ctor_p : 1; - unsigned global_dtor_p : 1; - unsigned anticipated_p : 1; - unsigned template_conv_p : 1; unsigned u1sel : 1; unsigned u2sel : 1; unsigned can_be_full : 1; unsigned this_thunk_p : 1; union lang_decl_u { ! /* In a FUNCTION_DECL for which DECL_THUNK_P does not hold, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this is DECL_TEMPLATE_INFO. */ tree GTY ((tag ("0"))) template_info; /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */ struct cp_binding_level * GTY ((tag ("1"))) level; - - /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is - THUNK_ALIAS. */ - tree GTY ((tag ("2"))) thunk_alias; } GTY ((desc ("%1.u1sel"))) u; union lang_decl_u2 { ! /* This is DECL_ACCESS. */ tree GTY ((tag ("0"))) access; /* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */ int GTY ((tag ("1"))) discriminator; - - /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is - THUNK_VIRTUAL_OFFSET. */ - tree GTY((tag ("2"))) virtual_offset; } GTY ((desc ("%1.u2sel"))) u2; }; --- 1529,1565 ---- unsigned use_template : 2; unsigned nonconverting : 1; unsigned not_really_extern : 1; unsigned initialized_in_class : 1; unsigned assignment_operator_p : 1; unsigned u1sel : 1; + unsigned u2sel : 1; unsigned can_be_full : 1; + unsigned thunk_p : 1; unsigned this_thunk_p : 1; + unsigned repo_available_p : 1; + unsigned dummy : 3; union lang_decl_u { ! /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is ! THUNK_ALIAS. ! In a FUNCTION_DECL for which DECL_THUNK_P does not hold, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this is DECL_TEMPLATE_INFO. */ tree GTY ((tag ("0"))) template_info; /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */ struct cp_binding_level * GTY ((tag ("1"))) level; } GTY ((desc ("%1.u1sel"))) u; union lang_decl_u2 { ! /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is ! THUNK_VIRTUAL_OFFSET. ! Otherwise this is DECL_ACCESS. */ tree GTY ((tag ("0"))) access; /* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */ int GTY ((tag ("1"))) discriminator; } GTY ((desc ("%1.u2sel"))) u2; }; *************** struct lang_decl GTY(()) *** 1664,1676 **** union lang_decl_u4 { ! struct full_lang_decl { /* For a non-thunk function decl, this is a tree list of friendly classes. For a thunk function decl, it is the thunked to function decl. */ tree befriending_classes; ! /* For a non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both --- 1572,1592 ---- union lang_decl_u4 { ! struct full_lang_decl { + /* In an overloaded operator, this is the value of + DECL_OVERLOADED_OPERATOR_P. */ + ENUM_BITFIELD (tree_code) operator_code : 8; + + unsigned u3sel : 1; + unsigned pending_inline_p : 1; + unsigned spare : 22; + /* For a non-thunk function decl, this is a tree list of friendly classes. For a thunk function decl, it is the thunked to function decl. */ tree befriending_classes; ! /* For a non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both *************** struct lang_decl GTY(()) *** 1679,1704 **** will be chained on the return pointer thunk. */ 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_FIXED_OFFSET. */ ! HOST_WIDE_INT fixed_offset; ! ! /* 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 { ! struct sorted_fields_type * GTY ((tag ("0"), reorder ("resort_sorted_fields"))) sorted_fields; struct cp_token_cache * 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; --- 1595,1617 ---- will be chained on the return pointer thunk. */ tree context; ! union lang_decl_u5 ! { ! /* In a non-thunk FUNCTION_DECL or TEMPLATE_DECL, this is ! DECL_CLONED_FUNCTION. */ ! tree GTY ((tag ("0"))) cloned_function; ! ! /* In a FUNCTION_DECL for which THUNK_P holds this is the ! THUNK_FIXED_OFFSET. */ ! HOST_WIDE_INT GTY ((tag ("1"))) fixed_offset; ! } GTY ((desc ("%0.decl_flags.thunk_p"))) u5; union lang_decl_u3 { ! struct sorted_fields_type * GTY ((tag ("0"), reorder ("resort_sorted_fields"))) sorted_fields; struct cp_token_cache * 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; *************** struct lang_decl GTY(()) *** 1720,1743 **** #endif /* ENABLE_TREE_CHECKING */ - /* DECL_NEEDED_P holds of a declaration when we need to emit its - definition. This is true when the back-end tells us that - the symbol has been referenced in the generated code. If, however, - we are not generating code, then it is also true when a symbol has - just been used somewhere, even if it's not really needed. We need - anything that isn't comdat, but we don't know for sure whether or - not something is comdat until end-of-file. */ - #define DECL_NEEDED_P(DECL) \ - ((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL)) \ - || (DECL_ASSEMBLER_NAME_SET_P (DECL) \ - && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \ - || (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL)))) - /* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the declaration. Some entities (like a member function in a local class, or a local variable) do not have linkage at all, and this macro should not be used in those cases. ! Implementation note: A FUNCTION_DECL without DECL_LANG_SPECIFIC was created by language-independent code, and has C linkage. Most VAR_DECLs have C++ linkage, and do not have DECL_LANG_SPECIFIC, but --- 1633,1643 ---- #endif /* ENABLE_TREE_CHECKING */ /* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the declaration. Some entities (like a member function in a local class, or a local variable) do not have linkage at all, and this macro should not be used in those cases. ! Implementation note: A FUNCTION_DECL without DECL_LANG_SPECIFIC was created by language-independent code, and has C linkage. Most VAR_DECLs have C++ linkage, and do not have DECL_LANG_SPECIFIC, but *************** struct lang_decl GTY(()) *** 1784,1790 **** /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the specialized in-charge constructor, in-charge deleting constructor, ! or the the base destructor. */ #define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \ (DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE)) --- 1684,1690 ---- /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the specialized in-charge constructor, in-charge deleting constructor, ! or the base destructor. */ #define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \ (DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE)) *************** struct lang_decl GTY(()) *** 1808,1823 **** /* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or destructor. */ ! #define DECL_CLONED_FUNCTION_P(NODE) \ ! ((TREE_CODE (NODE) == FUNCTION_DECL \ ! || TREE_CODE (NODE) == TEMPLATE_DECL) \ ! && DECL_LANG_SPECIFIC (NODE) \ && DECL_CLONED_FUNCTION (NODE) != NULL_TREE) /* If DECL_CLONED_FUNCTION_P holds, this is the function that was cloned. */ #define DECL_CLONED_FUNCTION(NODE) \ ! (DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function) /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */ #define DECL_DISCRIMINATOR_P(NODE) \ --- 1708,1739 ---- /* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or destructor. */ ! #define DECL_CLONED_FUNCTION_P(NODE) \ ! ((TREE_CODE (NODE) == FUNCTION_DECL \ ! || TREE_CODE (NODE) == TEMPLATE_DECL) \ ! && DECL_LANG_SPECIFIC (NODE) \ ! && !DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p \ && DECL_CLONED_FUNCTION (NODE) != NULL_TREE) /* If DECL_CLONED_FUNCTION_P holds, this is the function that was cloned. */ #define DECL_CLONED_FUNCTION(NODE) \ ! (DECL_LANG_SPECIFIC (NON_THUNK_FUNCTION_CHECK(NODE))->u.f.u5.cloned_function) ! ! /* Perform an action for each clone of FN, if FN is a function with ! clones. This macro should be used like: ! ! FOR_EACH_CLONE (clone, fn) ! { ... } ! ! */ ! #define FOR_EACH_CLONE(CLONE, FN) \ ! if (TREE_CODE (FN) == FUNCTION_DECL \ ! && (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (FN) \ ! || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (FN))) \ ! for (CLONE = TREE_CHAIN (FN); \ ! CLONE && DECL_CLONED_FUNCTION_P (CLONE); \ ! CLONE = TREE_CHAIN (CLONE)) /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */ #define DECL_DISCRIMINATOR_P(NODE) \ *************** struct lang_decl GTY(()) *** 1834,1840 **** /* 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))) --- 1750,1756 ---- /* Nonzero if NODE is a FUNCTION_DECL for which a VTT parameter is required. */ #define DECL_NEEDS_VTT_PARM_P(NODE) \ ! (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (NODE)) \ && (DECL_BASE_CONSTRUCTOR_P (NODE) \ || DECL_BASE_DESTRUCTOR_P (NODE))) *************** struct lang_decl GTY(()) *** 1900,1913 **** (TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE))) /* Nonzero for a VAR_DECL that can be used in an integral constant ! expression. [expr.const] An integral constant-expression can only involve ... const variables of static or enumeration types initialized with constant expressions ... ! The standard does not require that the expression be non-volatile. G++ implements the proposed correction in DR 457. */ #define DECL_INTEGRAL_CONSTANT_VAR_P(NODE) \ --- 1816,1829 ---- (TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE))) /* Nonzero for a VAR_DECL that can be used in an integral constant ! expression. [expr.const] An integral constant-expression can only involve ... const variables of static or enumeration types initialized with constant expressions ... ! The standard does not require that the expression be non-volatile. G++ implements the proposed correction in DR 457. */ #define DECL_INTEGRAL_CONSTANT_VAR_P(NODE) \ *************** struct lang_decl GTY(()) *** 1980,1989 **** #define DECL_PURE_VIRTUAL_P(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.pure_virtual) ! /* Nonzero for FUNCTION_DECL means that this member function ! must be overridden by derived classes. */ ! #define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \ ! (DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider) /* The thunks associated with NODE, a FUNCTION_DECL. */ #define DECL_THUNKS(NODE) \ --- 1896,1907 ---- #define DECL_PURE_VIRTUAL_P(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.pure_virtual) ! /* True (in a FUNCTION_DECL) if NODE is a virtual function that is an ! invalid overrider for a function from a base class. Once we have ! complained about an invalid overrider we avoid complaining about it ! again. */ ! #define DECL_INVALID_OVERRIDER_P(NODE) \ ! (DECL_LANG_FLAG_4 (NODE)) /* The thunks associated with NODE, a FUNCTION_DECL. */ #define DECL_THUNKS(NODE) \ *************** struct lang_decl GTY(()) *** 1992,1998 **** /* Nonzero if NODE is a thunk, rather than an ordinary function. */ #define DECL_THUNK_P(NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \ ! && DECL_LANG_FLAG_7 (NODE)) /* Nonzero if NODE is a this pointer adjusting thunk. */ #define DECL_THIS_THUNK_P(NODE) \ --- 1910,1923 ---- /* Nonzero if NODE is a thunk, rather than an ordinary function. */ #define DECL_THUNK_P(NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \ ! && DECL_LANG_SPECIFIC (NODE) \ ! && DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p) ! ! /* Set DECL_THUNK_P for node. */ ! #define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \ ! (DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p = 1, \ ! DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \ ! DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING)) /* Nonzero if NODE is a this pointer adjusting thunk. */ #define DECL_THIS_THUNK_P(NODE) \ *************** struct lang_decl GTY(()) *** 2014,2024 **** #define DECL_EXTERN_C_FUNCTION_P(NODE) \ (DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE)) ! /* Set DECL_THUNK_P for node. */ ! #define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \ ! (DECL_LANG_FLAG_7 (NODE) = 1, \ ! DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \ ! DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING)) /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a template function. */ --- 1939,1948 ---- #define DECL_EXTERN_C_FUNCTION_P(NODE) \ (DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE)) ! /* True iff DECL is an entity with vague linkage whose definition is ! available in this translation unit. */ ! #define DECL_REPO_AVAILABLE_P(NODE) \ ! (DECL_LANG_SPECIFIC (NODE)->decl_flags.repo_available_p) /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a template function. */ *************** struct lang_decl GTY(()) *** 2064,2072 **** --- 1988,2006 ---- (DECL_CONTEXT (NODE) \ && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL) + /* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for + both the primary typeinfo object and the associated NTBS name. */ + #define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)) + /* 1 iff VAR_DECL node NODE is virtual table or VTT. */ #define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE)) + /* Returns 1 iff VAR_DECL is a construction virtual table. + DECL_VTABLE_OR_VTT_P will be true in this case and must be checked + before using this macro. */ + #define DECL_CONSTRUCTION_VTABLE_P(NODE) \ + TREE_LANG_FLAG_6 (VAR_DECL_CHECK (NODE)) + /* 1 iff NODE is function-local, but for types. */ #define LOCAL_CLASS_P(NODE) \ (decl_function_context (TYPE_MAIN_DECL (NODE)) != NULL_TREE) *************** struct lang_decl GTY(()) *** 2145,2157 **** /* Template information for a RECORD_TYPE or UNION_TYPE. */ #define CLASSTYPE_TEMPLATE_INFO(NODE) \ ! (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 primary template and the enumeration constants may depend on non-type template parameters. */ ! #define ENUM_TEMPLATE_INFO(NODE) (TYPE_BINFO (ENUMERAL_TYPE_CHECK (NODE))) /* Template information for a template template parameter. */ #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \ --- 2079,2092 ---- /* Template information for a RECORD_TYPE or UNION_TYPE. */ #define CLASSTYPE_TEMPLATE_INFO(NODE) \ ! (LANG_TYPE_CLASS_CHECK (RECORD_OR_UNION_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 primary template and the enumeration constants may depend on non-type template parameters. */ ! #define ENUM_TEMPLATE_INFO(NODE) \ ! (TYPE_LANG_SLOT_1 (ENUMERAL_TYPE_CHECK (NODE))) /* Template information for a template template parameter. */ #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \ *************** struct lang_decl GTY(()) *** 2273,2282 **** /* For a template instantiation TYPE, returns the TYPE corresponding to the primary template. Otherwise returns TYPE itself. */ ! #define CLASSTYPE_PRIMARY_TEMPLATE_TYPE(TYPE) \ ! ((CLASSTYPE_USE_TEMPLATE ((TYPE)) && !CLASSTYPE_TEMPLATE_SPECIALIZATION ((TYPE))) \ ! ? TREE_TYPE (DECL_TEMPLATE_RESULT (DECL_PRIMARY_TEMPLATE \ ! (CLASSTYPE_TI_TEMPLATE ((TYPE))))) \ : (TYPE)) /* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */ --- 2208,2218 ---- /* For a template instantiation TYPE, returns the TYPE corresponding to the primary template. Otherwise returns TYPE itself. */ ! #define CLASSTYPE_PRIMARY_TEMPLATE_TYPE(TYPE) \ ! ((CLASSTYPE_USE_TEMPLATE ((TYPE)) \ ! && !CLASSTYPE_TEMPLATE_SPECIALIZATION ((TYPE))) \ ! ? TREE_TYPE (DECL_TEMPLATE_RESULT (DECL_PRIMARY_TEMPLATE \ ! (CLASSTYPE_TI_TEMPLATE ((TYPE))))) \ : (TYPE)) /* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */ *************** struct lang_decl GTY(()) *** 2289,2294 **** --- 2225,2235 ---- #define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE (NODE) + /* Nonzero if NODE (a TEMPLATE_DECL) is a member template, in the + sense of [temp.mem]. */ + #define DECL_MEMBER_TEMPLATE_P(NODE) \ + (DECL_LANG_FLAG_1 (TEMPLATE_DECL_CHECK (NODE))) + /* Nonzero if the NODE corresponds to the template parameters for a member template, whose inline definition is being processed after the class definition is complete. */ *************** struct lang_decl GTY(()) *** 2299,2315 **** (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) ! #define DELETE_EXPR_USE_VEC(NODE) TREE_LANG_FLAG_1 (NODE) /* Indicates that this is a non-dependent COMPOUND_EXPR which will resolve to a function call. */ ! #define COMPOUND_EXPR_OVERLOADED(NODE) TREE_LANG_FLAG_0 (NODE) /* In a CALL_EXPR appearing in a template, true if Koenig lookup should be performed at instantiation time. */ ! #define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0(NODE) /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a constructor call, rather than an ordinary function call. */ --- 2240,2270 ---- (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \ ->u.f.u.saved_language_function) ! /* Indicates an indirect_expr is for converting a reference. */ ! #define REFERENCE_REF_P(NODE) \ ! TREE_LANG_FLAG_0 (INDIRECT_REF_CHECK (NODE)) ! ! #define NEW_EXPR_USE_GLOBAL(NODE) \ ! TREE_LANG_FLAG_0 (NEW_EXPR_CHECK (NODE)) ! #define DELETE_EXPR_USE_GLOBAL(NODE) \ ! TREE_LANG_FLAG_0 (DELETE_EXPR_CHECK (NODE)) ! #define DELETE_EXPR_USE_VEC(NODE) \ ! TREE_LANG_FLAG_1 (DELETE_EXPR_CHECK (NODE)) /* Indicates that this is a non-dependent COMPOUND_EXPR which will resolve to a function call. */ ! #define COMPOUND_EXPR_OVERLOADED(NODE) \ ! TREE_LANG_FLAG_0 (COMPOUND_EXPR_CHECK (NODE)) /* In a CALL_EXPR appearing in a template, true if Koenig lookup should be performed at instantiation time. */ ! #define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0 (CALL_EXPR_CHECK (NODE)) ! ! /* Indicates whether a string literal has been parenthesized. Such ! usages are disallowed in certain circumstances. */ ! ! #define PAREN_STRING_LITERAL_P(NODE) \ ! TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE)) /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a constructor call, rather than an ordinary function call. */ *************** struct lang_decl GTY(()) *** 2329,2345 **** this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the corresponding TYPE_DECL. However, this may also be a TEMPLATE_ID_EXPR if we had something like `typename X::Y'. */ ! #define TYPENAME_TYPE_FULLNAME(NODE) (TYPE_FIELDS (NODE)) /* Nonzero in INTEGER_CST means that this int is negative by dint of using a twos-complement negated operand. */ #define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE)) - /* Nonzero in any kind of _TYPE where conversions to base-classes may - involve pointer arithmetic. If this is zero, then converting to - a base-class never requires changing the value of the pointer. */ - #define TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P(NODE) (TREE_LANG_FLAG_1 (NODE)) - /* [class.virtual] A class that declares or inherits a virtual function is called a --- 2284,2304 ---- this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the corresponding TYPE_DECL. However, this may also be a TEMPLATE_ID_EXPR if we had something like `typename X::Y'. */ ! #define TYPENAME_TYPE_FULLNAME(NODE) (TYPENAME_TYPE_CHECK (NODE))->type.values ! ! /* True if a TYPENAME_TYPE was declared as an "enum". */ ! #define TYPENAME_IS_ENUM_P(NODE) \ ! (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE))) ! ! /* True if a TYPENAME_TYPE was declared as a "class", "struct", or ! "union". */ ! #define TYPENAME_IS_CLASS_P(NODE) \ ! (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE))) /* Nonzero in INTEGER_CST means that this int is negative by dint of using a twos-complement negated operand. */ #define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE)) /* [class.virtual] A class that declares or inherits a virtual function is called a *************** struct lang_decl GTY(()) *** 2348,2355 **** /* Nonzero if this class has a virtual function table pointer. */ #define TYPE_CONTAINS_VPTR_P(NODE) \ ! (TYPE_POLYMORPHIC_P (NODE) \ ! || TYPE_USES_VIRTUAL_BASECLASSES (NODE)) /* 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. */ --- 2307,2313 ---- /* Nonzero if this class has a virtual function table pointer. */ #define TYPE_CONTAINS_VPTR_P(NODE) \ ! (TYPE_POLYMORPHIC_P (NODE) || CLASSTYPE_VBASECLASSES (NODE)) /* 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. */ *************** struct lang_decl GTY(()) *** 2379,2386 **** #define DECL_EXTERNAL_LINKAGE_P(DECL) \ (decl_linkage (DECL) == lk_external) ! #define INTEGRAL_CODE_P(CODE) \ ! ((CODE) == INTEGER_TYPE || (CODE) == ENUMERAL_TYPE || (CODE) == BOOLEAN_TYPE) /* [basic.fundamental] --- 2337,2348 ---- #define DECL_EXTERNAL_LINKAGE_P(DECL) \ (decl_linkage (DECL) == lk_external) ! /* Keep these codes in ascending code order. CHAR_TYPE is used here ! to completely fill the range. */ ! ! #define INTEGRAL_CODE_P(CODE) \ ! ((CODE) == ENUMERAL_TYPE || (CODE) == BOOLEAN_TYPE \ ! || (CODE) == CHAR_TYPE || (CODE) == INTEGER_TYPE) /* [basic.fundamental] *************** struct lang_decl GTY(()) *** 2388,2418 **** are collectively called integral types. Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration ! types as well, which is incorrect in C++. */ #define CP_INTEGRAL_TYPE_P(TYPE) \ (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 ! types. */ #define ARITHMETIC_TYPE_P(TYPE) \ (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE) /* [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_PTR_TO_MEMBER_P (TYPE)) /* [dcl.init.aggr] --- 2350,2386 ---- are collectively called integral types. Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration ! types as well, which is incorrect in C++. Keep these checks in ! ascending code order. CHAR_TYPE is added to complete the interval of ! values. */ #define CP_INTEGRAL_TYPE_P(TYPE) \ (TREE_CODE (TYPE) == BOOLEAN_TYPE \ + || TREE_CODE (TYPE) == CHAR_TYPE \ || TREE_CODE (TYPE) == INTEGER_TYPE) ! /* Returns true if TYPE is an integral or enumeration name. Keep ! these checks in ascending code order. */ #define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \ ! (TREE_CODE (TYPE) == ENUMERAL_TYPE || CP_INTEGRAL_TYPE_P (TYPE)) /* [basic.fundamental] Integral and floating types are collectively called arithmetic ! types. Keep these checks in ascending code order. */ #define ARITHMETIC_TYPE_P(TYPE) \ (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE) /* [basic.types] Arithmetic types, enumeration types, pointer types, and ! pointer-to-member types, are collectively called scalar types. ! Keep these checks in ascending code order. */ #define SCALAR_TYPE_P(TYPE) \ ! (TYPE_PTRMEM_P (TYPE) \ || TREE_CODE (TYPE) == ENUMERAL_TYPE \ + || ARITHMETIC_TYPE_P (TYPE) \ || TYPE_PTR_P (TYPE) \ ! || TYPE_PTRMEMFUNC_P (TYPE)) /* [dcl.init.aggr] *************** struct lang_decl GTY(()) *** 2420,2431 **** constructors, no private or protected non-static data members, no base classes, and no virtual functions. ! As an extension, we also treat vectors as aggregates. */ ! #define CP_AGGREGATE_TYPE_P(TYPE) \ ! (TREE_CODE (TYPE) == ARRAY_TYPE \ ! || TREE_CODE (TYPE) == VECTOR_TYPE \ ! || (CLASS_TYPE_P (TYPE) \ ! && !CLASSTYPE_NON_AGGREGATE (TYPE))) /* Nonzero for a class type means that the class type has a user-declared constructor. */ --- 2388,2399 ---- constructors, no private or protected non-static data members, no base classes, and no virtual functions. ! As an extension, we also treat vectors as aggregates. Keep these ! checks in ascending code order. */ ! #define CP_AGGREGATE_TYPE_P(TYPE) \ ! (TREE_CODE (TYPE) == VECTOR_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. */ *************** struct lang_decl GTY(()) *** 2440,2459 **** When appearing in a SAVE_EXPR, it means that underneath is a call to a constructor. ! When appearing in a CONSTRUCTOR, it means that it was ! a GNU C constructor expression. When appearing in a FIELD_DECL, it means that this field has been duly initialized in its constructor. */ #define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4 (NODE)) #define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ && ! TREE_HAS_CONSTRUCTOR (NODE)) - /* Nonzero for _TYPE means that the _TYPE defines a destructor. */ - #define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2 (NODE)) - /* Nonzero means that an object of this type can not be initialized using an initializer list. */ #define CLASSTYPE_NON_AGGREGATE(NODE) \ --- 2408,2428 ---- When appearing in a SAVE_EXPR, it means that underneath is a call to a constructor. ! When appearing in a CONSTRUCTOR, the expression is a ! compound literal. When appearing in a FIELD_DECL, it means that this field has been duly initialized in its constructor. */ #define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4 (NODE)) + /* True if NODE is a brace-enclosed initializer. */ + #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \ + (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE)) + #define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ && ! TREE_HAS_CONSTRUCTOR (NODE)) /* Nonzero means that an object of this type can not be initialized using an initializer list. */ #define CLASSTYPE_NON_AGGREGATE(NODE) \ *************** struct lang_decl GTY(()) *** 2462,2470 **** (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) (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]: --- 2431,2437 ---- *************** struct lang_decl GTY(()) *** 2501,2518 **** /* Returns true if NODE is a pointer-to-data-member. */ #define TYPE_PTRMEM_P(NODE) \ (TREE_CODE (NODE) == OFFSET_TYPE) #define TYPE_PTR_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE) ! #define TYPE_PTROB_P(NODE) \ ! (TYPE_PTR_P (NODE) \ ! && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ ! && TREE_CODE (TREE_TYPE (NODE)) != METHOD_TYPE \ ! && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) ! #define TYPE_PTROBV_P(NODE) \ ! (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE) #define TYPE_PTRFN_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) #define TYPE_REFFN_P(NODE) \ (TREE_CODE (NODE) == REFERENCE_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) --- 2468,2501 ---- /* Returns true if NODE is a pointer-to-data-member. */ #define TYPE_PTRMEM_P(NODE) \ (TREE_CODE (NODE) == OFFSET_TYPE) + /* Returns true if NODE is a pointer. */ #define TYPE_PTR_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE) ! /* Returns true if NODE is a pointer to an object. Keep these checks ! in ascending tree code order. */ ! #define TYPE_PTROB_P(NODE) \ ! (TYPE_PTR_P (NODE) \ ! && !(TREE_CODE (TREE_TYPE (NODE)) == VOID_TYPE \ ! || TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ ! || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) ! /* Returns true if NODE is a reference to an object. Keep these checks ! in ascending tree code order. */ ! #define TYPE_REF_OBJ_P(NODE) \ ! (TREE_CODE (NODE) == REFERENCE_TYPE \ ! && !(TREE_CODE (TREE_TYPE (NODE)) == VOID_TYPE \ ! || TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ ! || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) ! /* Returns true if NODE is a pointer to an object, or a pointer to ! void. Keep these checks in ascending tree code order. */ ! #define TYPE_PTROBV_P(NODE) \ ! (TYPE_PTR_P (NODE) \ ! && !(TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ ! || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) ! /* Returns true if NODE is a pointer to function. */ #define TYPE_PTRFN_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) + /* Returns true if NODE is a reference to function. */ #define TYPE_REFFN_P(NODE) \ (TREE_CODE (NODE) == REFERENCE_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) *************** struct lang_decl GTY(()) *** 2533,2539 **** /* Indicates when overload resolution may resolve to a pointer to member function. [expr.unary.op]/3 */ ! #define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE) /* Get the POINTER_TYPE to the METHOD_TYPE associated with this pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, --- 2516,2523 ---- /* Indicates when overload resolution may resolve to a pointer to member function. [expr.unary.op]/3 */ ! #define PTRMEM_OK_P(NODE) \ ! TREE_LANG_FLAG_0 (TREE_CHECK2 ((NODE), ADDR_EXPR, OFFSET_REF)) /* Get the POINTER_TYPE to the METHOD_TYPE associated with this pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, *************** struct lang_decl GTY(()) *** 2553,2566 **** 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)) /* For a pointer-to-member type of the form `T X::*', this is `X'. For a type like `void (X::*)() const', this type is `X', not `const --- 2537,2548 ---- do { \ if (TYPE_LANG_SPECIFIC (NODE) == NULL) \ { \ ! TYPE_LANG_SPECIFIC (NODE) = GGC_CNEWVAR \ ! (struct lang_type, 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) /* For a pointer-to-member type of the form `T X::*', this is `X'. For a type like `void (X::*)() const', this type is `X', not `const *************** struct lang_decl GTY(()) *** 2587,2592 **** --- 2569,2577 ---- `Y'. */ #define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member) + /* The expression in question for a TYPEOF_TYPE. */ + #define TYPEOF_TYPE_EXPR(NODE) (TYPEOF_TYPE_CHECK (NODE))->type.values + /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was specified in its declaration. This can also be set for an erroneously declared PARM_DECL. */ *************** struct lang_decl GTY(()) *** 2599,2604 **** --- 2584,2594 ---- #define DECL_THIS_STATIC(NODE) \ DECL_LANG_FLAG_6 (VAR_FUNCTION_OR_PARM_DECL_CHECK (NODE)) + /* Nonzero for FIELD_DECL node means that this field is a base class + of the parent object, as opposed to a member field. */ + #define DECL_FIELD_IS_BASE(NODE) \ + DECL_LANG_FLAG_6 (FIELD_DECL_CHECK (NODE)) + /* Nonzero if TYPE is an anonymous union or struct type. We have to use a flag for this because "A union for which objects or pointers are declared is not an anonymous union" [class.union]. */ *************** struct lang_decl GTY(()) *** 2722,2728 **** This list is not used for static variable templates. */ #define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE) ! /* Nonzero for a DECL which is actually a template parameter. */ #define DECL_TEMPLATE_PARM_P(NODE) \ (DECL_LANG_FLAG_0 (NODE) \ && (TREE_CODE (NODE) == CONST_DECL \ --- 2712,2719 ---- This list is not used for static variable templates. */ #define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE) ! /* Nonzero for a DECL which is actually a template parameter. Keep ! these checks in ascending tree code order. */ #define DECL_TEMPLATE_PARM_P(NODE) \ (DECL_LANG_FLAG_0 (NODE) \ && (TREE_CODE (NODE) == CONST_DECL \ *************** struct lang_decl GTY(()) *** 2794,2800 **** 0=normal declaration, e.g. int min (int, int); 1=implicit template instantiation 2=explicit template specialization, e.g. int min (int, int); ! 3=explicit template instantiation, e.g. template int min (int, int); */ #define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template) #define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1) --- 2785,2794 ---- 0=normal declaration, e.g. int min (int, int); 1=implicit template instantiation 2=explicit template specialization, e.g. int min (int, int); ! 3=explicit template instantiation, e.g. template int min (int, int); ! ! If DECL_USE_TEMPLATE is non-zero, then DECL_TEMPLATE_INFO will also ! be non-NULL. */ #define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template) #define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1) *************** struct lang_decl GTY(()) *** 2803,2808 **** --- 2797,2805 ---- #define DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) == 2) #define SET_DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) = 2) + + /* Returns true for an explicit or partial specialization of a class + template. */ #define CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ (CLASSTYPE_USE_TEMPLATE (NODE) == 2) #define SET_CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ *************** struct lang_decl GTY(()) *** 2840,2846 **** /* Nonzero if this VAR_DECL or FUNCTION_DECL has already been instantiated, i.e. its definition has been generated from the ! pattern given in the the template. */ #define DECL_TEMPLATE_INSTANTIATED(NODE) \ DECL_LANG_FLAG_1 (VAR_OR_FUNCTION_DECL_CHECK (NODE)) --- 2837,2843 ---- /* 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 template. */ #define DECL_TEMPLATE_INSTANTIATED(NODE) \ DECL_LANG_FLAG_1 (VAR_OR_FUNCTION_DECL_CHECK (NODE)) *************** struct lang_decl GTY(()) *** 2868,2874 **** function, (or be implemented via passing some invisible parameter to the thunked function, which is modified to perform the adjustment just before returning). ! A thunk may perform either, or both, of the following operations: o Adjust the this or result pointer by a constant offset. --- 2865,2871 ---- function, (or be implemented via passing some invisible parameter to the thunked function, which is modified to perform the adjustment just before returning). ! A thunk may perform either, or both, of the following operations: o Adjust the this or result pointer by a constant offset. *************** struct lang_decl GTY(()) *** 2898,2904 **** /* An integer indicating how many bytes should be subtracted from the this or result pointer when this function is called. */ #define THUNK_FIXED_OFFSET(DECL) \ ! (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL))->u.f.fixed_offset) /* A tree indicating how to perform the virtual adjustment. For a this adjusting thunk it is the number of bytes to be added to the vtable --- 2895,2901 ---- /* An integer indicating how many bytes should be subtracted from the this or result pointer when this function is called. */ #define THUNK_FIXED_OFFSET(DECL) \ ! (DECL_LANG_SPECIFIC (THUNK_FUNCTION_CHECK (DECL))->u.f.u5.fixed_offset) /* A tree indicating how to perform the virtual adjustment. For a this adjusting thunk it is the number of bytes to be added to the vtable *************** struct lang_decl GTY(()) *** 2911,2923 **** binfos.) */ #define THUNK_VIRTUAL_OFFSET(DECL) \ ! (LANG_DECL_U2_CHECK (FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset) /* A thunk which is equivalent to another thunk. */ #define THUNK_ALIAS(DECL) \ ! (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.u.thunk_alias) ! /* For thunk NODE, this is the FUNCTION_DECL thunked to. */ #define THUNK_TARGET(NODE) \ (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) --- 2908,2921 ---- binfos.) */ #define THUNK_VIRTUAL_OFFSET(DECL) \ ! (LANG_DECL_U2_CHECK (FUNCTION_DECL_CHECK (DECL), 0)->access) /* A thunk which is equivalent to another thunk. */ #define THUNK_ALIAS(DECL) \ ! (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.u.template_info) ! /* For thunk NODE, this is the FUNCTION_DECL thunked to. It is ! possible for the target to be a thunk too. */ #define THUNK_TARGET(NODE) \ (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) *************** struct lang_decl GTY(()) *** 2937,2956 **** #define HANDLER_BODY(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 1) #define HANDLER_TYPE(NODE) TREE_TYPE (HANDLER_CHECK (NODE)) ! /* The parameters for a call-declarator. */ ! #define CALL_DECLARATOR_PARMS(NODE) \ ! (TREE_PURPOSE (TREE_OPERAND (NODE, 1))) ! ! /* The cv-qualifiers for a call-declarator. */ ! #define CALL_DECLARATOR_QUALS(NODE) \ ! (TREE_VALUE (TREE_OPERAND (NODE, 1))) ! /* The exception-specification for a call-declarator. */ ! #define CALL_DECLARATOR_EXCEPTION_SPEC(NODE) \ ! (TREE_TYPE (NODE)) /* An enumeration of the kind of tags that C++ accepts. */ ! enum tag_types { none_type = 0, /* Not a tag type. */ record_type, /* "struct" types. */ class_type, /* "class" types. */ --- 2935,2955 ---- #define HANDLER_BODY(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 1) #define HANDLER_TYPE(NODE) TREE_TYPE (HANDLER_CHECK (NODE)) ! /* CLEANUP_STMT accessors. The statement(s) covered, the cleanup to run ! and the VAR_DECL for which this cleanup exists. */ ! #define CLEANUP_BODY(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 0) ! #define CLEANUP_EXPR(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 1) ! #define CLEANUP_DECL(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 2) ! /* IF_STMT accessors. These give access to the condition of the if ! statement, the then block of the if statement, and the else block ! of the if statement if it exists. */ ! #define IF_COND(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 0) ! #define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) ! #define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) /* An enumeration of the kind of tags that C++ accepts. */ ! enum tag_types { none_type = 0, /* Not a tag type. */ record_type, /* "struct" types. */ class_type, /* "class" types. */ *************** typedef enum special_function_kind { *** 3015,3022 **** sfk_conversion /* A conversion operator. */ } special_function_kind; ! /* The various kinds of linkage. From [basic.link], ! A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced in another scope: --- 3014,3021 ---- sfk_conversion /* A conversion operator. */ } special_function_kind; ! /* The various kinds of linkage. From [basic.link], ! A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced in another scope: *************** typedef enum tsubst_flags_t { *** 3050,3061 **** instantiate_type use) */ tf_user = 1 << 5, /* found template must be a user template (lookup_template_class use) */ ! tf_stmt_expr_cmpd = 1 << 6, /* tsubsting the compound statement of ! a statement expr. */ ! tf_stmt_expr_body = 1 << 7, /* tsubsting the statements in the ! body of the compound statement of a ! statement expr. */ ! tf_conv = 1 << 8 /* We are determining what kind of conversion might be permissible, not actually performing the conversion. */ --- 3049,3055 ---- instantiate_type use) */ tf_user = 1 << 5, /* found template must be a user template (lookup_template_class use) */ ! tf_conv = 1 << 6 /* We are determining what kind of conversion might be permissible, not actually performing the conversion. */ *************** typedef enum tsubst_flags_t { *** 3063,3075 **** /* 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. */ ! ba_quiet = 4 /* Do not issue error messages (bit mask). */ } base_access; /* The various kinds of access check during parsing. */ --- 3057,3069 ---- /* 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_unique = 1 << 0, /* Must be a unique base. */ ! ba_check_bit = 1 << 1, /* Check access. */ ! ba_check = ba_unique | ba_check_bit, ! ba_ignore_scope = 1 << 2, /* Ignore access allowed by local scope. */ ! ba_quiet = 1 << 3 /* Do not issue error messages. */ } base_access; /* The various kinds of access check during parsing. */ *************** typedef enum base_kind { *** 3092,3102 **** binfo. */ } base_kind; - /* 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; - /* in decl{2}.c */ /* A node that is a list (length 1) of error_mark_nodes. */ extern GTY(()) tree error_mark_list; --- 3086,3091 ---- *************** extern GTY(()) tree integer_three_node; *** 3115,3146 **** function, two inside the body of a function in a local class, etc.) */ extern int function_depth; - typedef struct deferred_access GTY(()) - { - /* A TREE_LIST representing name-lookups for which we have deferred - checking access controls. We cannot check the accessibility of - names used in a decl-specifier-seq until we know what is being - declared because code like: - - class A { - class B {}; - B* f(); - } - - A::B* A::f() { return 0; } - - is valid, even though `A::B' is not generally accessible. - - The TREE_PURPOSE of each node is the scope used to qualify the - name being looked up; the TREE_VALUE is the DECL to which the - name was resolved. */ - tree deferred_access_checks; - /* The current mode of access checks. */ - enum deferring_kind deferring_access_checks_kind; - /* The next deferred access data in stack or linked-list. */ - struct deferred_access *next; - } deferred_access; - /* in pt.c */ /* These values are used for the `STRICT' parameter to type_unification and --- 3104,3109 ---- *************** typedef enum unification_kind_t { *** 3154,3165 **** DEDUCE_ORDER } unification_kind_t; ! /* Macros for operating on a template instantiation level node, represented ! by an EXPR_WITH_FILE_LOCATION. */ ! #define TINST_DECL(NODE) EXPR_WFL_NODE (NODE) ! #define TINST_LINE(NODE) EXPR_WFL_LINENO (NODE) ! #define TINST_FILE(NODE) EXPR_WFL_FILENAME (NODE) /* in class.c */ --- 3117,3130 ---- DEDUCE_ORDER } unification_kind_t; ! /* Macros for operating on a template instantiation level node. */ ! #define TINST_DECL(NODE) \ ! (((tinst_level_t) TINST_LEVEL_CHECK (NODE))->decl) ! #define TINST_LOCATION(NODE) \ ! (((tinst_level_t) TINST_LEVEL_CHECK (NODE))->locus) ! #define TINST_IN_SYSTEM_HEADER_P(NODE) \ ! (((tinst_level_t) TINST_LEVEL_CHECK (NODE))->in_system_header_p) /* in class.c */ *************** extern GTY(()) varray_type local_classes *** 3255,3262 **** #endif /* NO_DOLLAR_IN_LABEL */ #define THIS_NAME "this" - #define CTOR_NAME "__ct" - #define DTOR_NAME "__dt" #define IN_CHARGE_NAME "__in_chrg" --- 3220,3225 ---- *************** enum overload_flags { NO_SPECIAL = 0, DT *** 3334,3342 **** direct-initialization in cases where other parts of the compiler have already generated a temporary, such as reference initialization and the catch parameter. - LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are - after. Note, LOOKUP_COMPLAIN is checked and error messages printed - before LOOKUP_SPECULATIVELY is checked. LOOKUP_NO_CONVERSION means that user-defined conversions are not permitted. Built-in conversions are permitted. LOOKUP_DESTRUCTOR means explicit call to destructor. --- 3297,3302 ---- *************** enum overload_flags { NO_SPECIAL = 0, DT *** 3354,3369 **** #define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN) #define LOOKUP_NONVIRTUAL (1 << 2) #define LOOKUP_GLOBAL (1 << 3) ! #define LOOKUP_SPECULATIVELY (1 << 4) ! #define LOOKUP_ONLYCONVERTING (1 << 5) ! #define DIRECT_BIND (1 << 6) ! #define LOOKUP_NO_CONVERSION (1 << 7) ! #define LOOKUP_DESTRUCTOR (1 << 8) ! #define LOOKUP_NO_TEMP_BIND (1 << 9) ! #define LOOKUP_PREFER_TYPES (1 << 10) ! #define LOOKUP_PREFER_NAMESPACES (1 << 11) #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES) ! #define LOOKUP_CONSTRUCTOR_CALLABLE (1 << 12) #define LOOKUP_NAMESPACES_ONLY(F) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) --- 3314,3328 ---- #define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN) #define LOOKUP_NONVIRTUAL (1 << 2) #define LOOKUP_GLOBAL (1 << 3) ! #define LOOKUP_ONLYCONVERTING (1 << 4) ! #define DIRECT_BIND (1 << 5) ! #define LOOKUP_NO_CONVERSION (1 << 6) ! #define LOOKUP_DESTRUCTOR (1 << 7) ! #define LOOKUP_NO_TEMP_BIND (1 << 8) ! #define LOOKUP_PREFER_TYPES (1 << 9) ! #define LOOKUP_PREFER_NAMESPACES (1 << 10) #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES) ! #define LOOKUP_CONSTRUCTOR_CALLABLE (1 << 11) #define LOOKUP_NAMESPACES_ONLY(F) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) *************** enum overload_flags { NO_SPECIAL = 0, DT *** 3449,3455 **** /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM nodes. */ ! #define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE)) #define TEMPLATE_TYPE_IDX(NODE) \ (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE))) #define TEMPLATE_TYPE_LEVEL(NODE) \ --- 3408,3416 ---- /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM nodes. */ ! #define TEMPLATE_TYPE_PARM_INDEX(NODE) \ ! (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, \ ! BOUND_TEMPLATE_TEMPLATE_PARM))->type.values #define TEMPLATE_TYPE_IDX(NODE) \ (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE))) #define TEMPLATE_TYPE_LEVEL(NODE) \ *************** extern GTY(()) operator_name_info_t oper *** 3524,3529 **** --- 3485,3649 ---- extern GTY(()) operator_name_info_t assignment_operator_name_info [(int) LAST_CPLUS_TREE_CODE]; + /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL + constants. */ + + typedef int cp_cv_quals; + + /* A storage class. */ + + typedef enum cp_storage_class { + /* sc_none must be zero so that zeroing a cp_decl_specifier_seq + sets the storage_class field to sc_none. */ + sc_none = 0, + sc_auto, + sc_register, + sc_static, + sc_extern, + sc_mutable + } cp_storage_class; + + /* An individual decl-specifier. */ + + typedef enum cp_decl_spec { + ds_first, + ds_signed = ds_first, + ds_unsigned, + ds_short, + ds_long, + ds_const, + ds_volatile, + ds_restrict, + ds_inline, + ds_virtual, + ds_explicit, + ds_friend, + ds_typedef, + ds_complex, + ds_thread, + ds_last + } cp_decl_spec; + + /* A decl-specifier-seq. */ + + typedef struct cp_decl_specifier_seq { + /* The number of times each of the keywords has been seen. */ + unsigned specs[(int) ds_last]; + /* The primary type, if any, given by the decl-specifier-seq. + Modifiers, like "short", "const", and "unsigned" are not + reflected here. This field will be a TYPE, unless a typedef-name + was used, in which case it will be a TYPE_DECL. */ + tree type; + /* The attributes, if any, provided with the specifier sequence. */ + tree attributes; + /* If non-NULL, a built-in type that the user attempted to redefine + to some other type. */ + tree redefined_builtin_type; + /* The storage class specified -- or sc_none if no storage class was + explicitly specified. */ + cp_storage_class storage_class; + /* True iff TYPE_SPEC indicates a user-defined type. */ + BOOL_BITFIELD user_defined_type_p : 1; + /* True iff multiple types were (erroneously) specified for this + decl-specifier-seq. */ + BOOL_BITFIELD multiple_types_p : 1; + /* True iff multiple storage classes were (erroneously) specified + for this decl-specifier-seq. */ + BOOL_BITFIELD multiple_storage_classes_p : 1; + /* True iff at least one decl-specifier was found. */ + BOOL_BITFIELD any_specifiers_p : 1; + /* True iff "int" was explicitly provided. */ + BOOL_BITFIELD explicit_int_p : 1; + /* True iff "char" was explicitly provided. */ + BOOL_BITFIELD explicit_char_p : 1; + } cp_decl_specifier_seq; + + /* The various kinds of declarators. */ + + typedef enum cp_declarator_kind { + cdk_id, + cdk_function, + cdk_array, + cdk_pointer, + cdk_reference, + cdk_ptrmem, + cdk_error + } cp_declarator_kind; + + /* A declarator. */ + + typedef struct cp_declarator cp_declarator; + + typedef struct cp_parameter_declarator cp_parameter_declarator; + + /* A parameter, before it has been semantically analyzed. */ + struct cp_parameter_declarator { + /* The next parameter, or NULL_TREE if none. */ + cp_parameter_declarator *next; + /* The decl-specifiers-seq for the parameter. */ + cp_decl_specifier_seq decl_specifiers; + /* The declarator for the parameter. */ + cp_declarator *declarator; + /* The default-argument expression, or NULL_TREE, if none. */ + tree default_argument; + /* True iff this is the first parameter in the list and the + parameter sequence ends with an ellipsis. */ + bool ellipsis_p; + }; + + /* A declarator. */ + struct cp_declarator { + /* The kind of declarator. */ + cp_declarator_kind kind; + /* Attributes that apply to this declarator. */ + tree attributes; + /* For all but cdk_id and cdk_error, the contained declarator. For + cdk_id and cdk_error, guaranteed to be NULL. */ + cp_declarator *declarator; + union { + /* For identifiers. */ + struct { + /* If non-NULL, the qualifying scope (a NAMESPACE_DECL or + *_TYPE) for this identifier. */ + tree qualifying_scope; + /* The unqualified name of the entity -- an IDENTIFIER_NODE, + BIT_NOT_EXPR, or TEMPLATE_ID_EXPR. */ + tree unqualified_name; + /* If this is the name of a function, what kind of special + function (if any). */ + special_function_kind sfk; + } id; + /* For functions. */ + struct { + /* The parameters to the function. */ + cp_parameter_declarator *parameters; + /* The cv-qualifiers for the function. */ + cp_cv_quals qualifiers; + /* The exception-specification for the function. */ + tree exception_specification; + } function; + /* For arrays. */ + struct { + /* The bounds to the array. */ + tree bounds; + } array; + /* For cdk_pointer, cdk_reference, and cdk_ptrmem. */ + struct { + /* The cv-qualifiers for the pointer. */ + cp_cv_quals qualifiers; + /* For cdk_ptrmem, the class type containing the member. */ + tree class_type; + } pointer; + } u; + }; + + /* An erroneous declarator. */ + extern cp_declarator *cp_error_declarator; + + /* A parameter list indicating for a function with no parameters, + e.g "int f(void)". */ + extern cp_parameter_declarator *no_parameters; + /* in call.c */ extern bool check_dtor_name (tree, tree); *************** extern tree build_operator_new_call (tre *** 3540,3546 **** 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 (enum tree_code, int, tree, tree, tree, bool *); ! extern tree build_op_delete_call (enum tree_code, tree, tree, int, tree); extern bool can_convert (tree, tree); extern bool can_convert_arg (tree, tree, tree); extern bool can_convert_arg_bad (tree, tree, tree); --- 3660,3666 ---- 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 (enum tree_code, int, tree, tree, tree, bool *); ! extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree); extern bool can_convert (tree, tree); extern bool can_convert_arg (tree, tree, tree); extern bool can_convert_arg_bad (tree, tree, tree); *************** extern tree build_x_va_arg (tree, tree); *** 3551,3576 **** extern tree cxx_type_promotes_to (tree); extern tree type_passed_as (tree); extern tree convert_for_arg_passing (tree, tree); - extern tree cp_convert_parm_for_inlining (tree, tree, tree); extern bool is_properly_derived_from (tree, tree); extern tree initialize_reference (tree, tree, tree, tree *); extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree strip_top_quals (tree); extern tree perform_implicit_conversion (tree, tree); ! extern tree perform_direct_initialization_if_possible (tree, tree); extern tree in_charge_arg_for_name (tree); ! extern tree build_cxx_call (tree, tree, tree); /* in class.c */ extern tree build_base_path (enum tree_code, tree, tree, int); ! extern tree convert_to_base (tree, tree, bool); extern tree convert_to_base_statically (tree, tree); extern tree build_vtbl_ref (tree, tree); extern tree build_vfn_ref (tree, tree); extern tree get_vtable_decl (tree, int); extern void resort_type_method_vec (void *, void *, gt_pointer_operator, void *); ! extern void add_method (tree, tree, int); extern int currently_open_class (tree); extern tree currently_open_derived_class (tree); extern tree finish_struct (tree, tree); --- 3671,3698 ---- extern tree cxx_type_promotes_to (tree); extern tree type_passed_as (tree); extern tree convert_for_arg_passing (tree, tree); extern bool is_properly_derived_from (tree, tree); extern tree initialize_reference (tree, tree, tree, tree *); extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree strip_top_quals (tree); extern tree perform_implicit_conversion (tree, tree); ! extern tree perform_direct_initialization_if_possible (tree, tree, bool); extern tree in_charge_arg_for_name (tree); ! extern tree build_cxx_call (tree, tree); ! #ifdef ENABLE_CHECKING ! extern void validate_conversion_obstack (void); ! #endif /* ENABLE_CHECKING */ /* in class.c */ extern tree build_base_path (enum tree_code, tree, tree, int); ! extern tree convert_to_base (tree, tree, bool, bool); extern tree convert_to_base_statically (tree, tree); extern tree build_vtbl_ref (tree, tree); extern tree build_vfn_ref (tree, tree); extern tree get_vtable_decl (tree, int); extern void resort_type_method_vec (void *, void *, gt_pointer_operator, void *); ! extern void add_method (tree, tree); extern int currently_open_class (tree); extern tree currently_open_derived_class (tree); extern tree finish_struct (tree, tree); *************** extern void build_self_reference (void) *** 3598,3604 **** extern int same_signature_p (tree, tree); extern void warn_hidden (tree); extern void maybe_add_class_template_decl_list (tree, tree, int); - extern tree get_enclosing_class (tree); extern void unreverse_member_declarations (tree); extern void invalidate_class_lookup_cache (void); extern void maybe_note_name_used_in_class (tree, tree); --- 3720,3725 ---- *************** extern tree get_vtt_name *** 3608,3618 **** extern tree get_primary_binfo (tree); extern void debug_class (tree); extern void debug_thunks (tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree); extern tree convert_from_reference (tree); - extern tree convert_lvalue (tree, tree); extern tree force_rvalue (tree); extern tree ocp_convert (tree, tree, int, int); extern tree cp_convert (tree, tree); --- 3729,3742 ---- extern tree get_primary_binfo (tree); extern void debug_class (tree); extern void debug_thunks (tree); + extern tree cp_fold_obj_type_ref (tree, tree); + extern void set_linkage_according_to_type (tree, tree); + extern void determine_key_method (tree); + extern void check_for_override (tree, tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree); extern tree convert_from_reference (tree); extern tree force_rvalue (tree); extern tree ocp_convert (tree, tree, int, int); extern tree cp_convert (tree, tree); *************** extern void clone_function_decl *** 3626,3662 **** extern void adjust_clone_args (tree); /* decl.c */ extern void insert_block (tree); - extern void set_block (tree); extern tree pushdecl (tree); extern void cxx_init_decl_processing (void); ! enum cp_tree_node_structure_enum cp_tree_node_structure (union lang_tree_node *); extern bool cxx_mark_addressable (tree); extern void cxx_push_function_context (struct function *); extern void cxx_pop_function_context (struct function *); - extern void cxx_mark_function_context (struct function *); extern void maybe_push_cleanup_level (tree); extern void finish_scope (void); - extern void delete_block (tree); - extern void add_block_current_level (tree); extern void push_switch (tree); extern void pop_switch (void); ! extern void pushtag (tree, tree, int); extern tree make_anon_name (void); - extern void clear_anon_tags (void); extern int decls_match (tree, tree); extern tree duplicate_decls (tree, tree); extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level_and_finish (tree, tree); extern tree push_using_decl (tree, tree); - extern tree implicitly_declare (tree); extern tree declare_local_label (tree); extern tree define_label (location_t, tree); extern void check_goto (tree); ! extern void define_case_label (void); ! extern tree make_typename_type (tree, tree, tsubst_flags_t); ! extern tree make_unbound_class_template (tree, tree, tsubst_flags_t); extern tree check_for_out_of_scope_variable (tree); extern tree build_library_fn (tree, tree); extern tree build_library_fn_ptr (const char *, tree); --- 3750,3780 ---- extern void adjust_clone_args (tree); /* decl.c */ + extern tree poplevel (int, int, int); extern void insert_block (tree); extern tree pushdecl (tree); extern void cxx_init_decl_processing (void); ! enum cp_tree_node_structure_enum cp_tree_node_structure (union lang_tree_node *); extern bool cxx_mark_addressable (tree); extern void cxx_push_function_context (struct function *); extern void cxx_pop_function_context (struct function *); extern void maybe_push_cleanup_level (tree); extern void finish_scope (void); extern void push_switch (tree); extern void pop_switch (void); ! extern tree pushtag (tree, tree, int); extern tree make_anon_name (void); extern int decls_match (tree, tree); extern tree duplicate_decls (tree, tree); extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level_and_finish (tree, tree); extern tree push_using_decl (tree, tree); extern tree declare_local_label (tree); extern tree define_label (location_t, tree); extern void check_goto (tree); ! extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t); ! extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t); extern tree check_for_out_of_scope_variable (tree); extern tree build_library_fn (tree, tree); extern tree build_library_fn_ptr (const char *, tree); *************** extern tree build_cp_library_fn_ptr (co *** 3664,3699 **** extern tree push_library_fn (tree, tree); extern tree push_void_library_fn (tree, tree); extern tree push_throw_library_fn (tree, tree); ! extern int init_type_desc (void); ! extern tree check_tag_decl (tree); ! extern tree shadow_tag (tree); ! extern tree groktypename (tree); ! extern tree start_decl (tree, tree, int, tree, tree); extern void start_decl_1 (tree); extern void cp_finish_decl (tree, tree, tree, int); extern void finish_decl (tree, tree, tree); ! extern void maybe_inject_for_scope_var (tree); ! extern tree start_handler_parms (tree, tree); ! extern int complete_array_type (tree, tree, int); extern tree build_ptrmemfunc_type (tree); extern tree build_ptrmem_type (tree, tree); /* the grokdeclarator prototype is in decl.h */ extern int copy_fn_p (tree); ! extern tree get_scope_of_declarator (tree); extern void grok_special_member_properties (tree); extern int grok_ctor_properties (tree, tree); extern bool grok_op_properties (tree, int, bool); ! extern tree xref_tag (enum tag_types, tree, bool, bool); ! extern tree xref_tag_from_type (tree, tree, int); extern void xref_basetypes (tree, tree); extern tree start_enum (tree); extern void finish_enum (tree); extern void build_enumerator (tree, tree, tree); ! extern int start_function (tree, tree, tree, int); extern tree begin_function_body (void); extern void finish_function_body (tree); extern tree finish_function (int); ! extern tree start_method (tree, tree, tree); extern tree finish_method (tree); extern void maybe_register_incomplete_var (tree); extern void complete_vars (tree); --- 3782,3815 ---- extern tree push_library_fn (tree, tree); extern tree push_void_library_fn (tree, tree); extern tree push_throw_library_fn (tree, tree); ! extern tree check_tag_decl (cp_decl_specifier_seq *); ! extern tree shadow_tag (cp_decl_specifier_seq *); ! extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *); ! extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *); extern void start_decl_1 (tree); extern void cp_finish_decl (tree, tree, tree, int); extern void finish_decl (tree, tree, tree); ! extern int cp_complete_array_type (tree *, tree, bool); extern tree build_ptrmemfunc_type (tree); extern tree build_ptrmem_type (tree, tree); /* the grokdeclarator prototype is in decl.h */ extern int copy_fn_p (tree); ! extern tree get_scope_of_declarator (const cp_declarator *); extern void grok_special_member_properties (tree); extern int grok_ctor_properties (tree, tree); extern bool grok_op_properties (tree, int, bool); ! extern tree xref_tag (enum tag_types, tree, tag_scope, bool); ! extern tree xref_tag_from_type (tree, tree, tag_scope); extern void xref_basetypes (tree, tree); extern tree start_enum (tree); extern void finish_enum (tree); extern void build_enumerator (tree, tree, tree); ! extern void start_preparsed_function (tree, tree, int); ! extern int start_function (cp_decl_specifier_seq *, const cp_declarator *, tree); extern tree begin_function_body (void); extern void finish_function_body (tree); extern tree finish_function (int); ! extern tree start_method (cp_decl_specifier_seq *, const cp_declarator *, tree); extern tree finish_method (tree); extern void maybe_register_incomplete_var (tree); extern void complete_vars (tree); *************** extern void fixup_anonymous_aggr *** 3704,3716 **** extern int check_static_variable_definition (tree, tree); extern tree compute_array_index_type (tree, tree); extern tree check_default_argument (tree, tree); - extern int vtable_decl_p (tree, void *); - extern int vtype_decl_p (tree, void *); - extern int sigtable_decl_p (tree, void *); - typedef bool (*walk_globals_pred) (tree, void *); - typedef bool (*walk_globals_fn) (tree *, void *); - extern bool walk_globals (walk_globals_pred, walk_globals_fn, void *); - extern bool walk_vtables (walk_globals_pred, walk_globals_fn, void *); typedef int (*walk_namespaces_fn) (tree, void *); extern int walk_namespaces (walk_namespaces_fn, void *); --- 3820,3825 ---- *************** extern tree build_target_expr_with_type *** 3722,3772 **** extern int local_variable_p (tree); extern int nonstatic_local_decl_p (tree); extern tree declare_global_var (tree, tree); ! extern void register_dtor_fn (tree); extern tmpl_spec_kind current_tmpl_spec_kind (int); extern tree cp_fname_init (const char *, tree *); extern tree check_elaborated_type_specifier (enum tag_types, tree, bool); - extern tree cxx_builtin_type_decls (void); extern void warn_extern_redeclared_static (tree, tree); ! extern tree check_var_type (tree, tree); extern bool have_extern_spec; /* in decl2.c */ extern bool check_java_method (tree); ! extern int grok_method_quals (tree, tree, tree); ! extern void grok_x_components (tree); extern void maybe_retrofit_in_chrg (tree); extern void maybe_make_one_only (tree); ! extern void grokclassfn (tree, tree, enum overload_flags, tree); extern tree grok_array_decl (tree, tree); extern tree delete_sanity (tree, tree, bool, int); ! extern tree check_classfn (tree, tree, bool); extern void check_member_template (tree); ! extern tree grokfield (tree, tree, tree, tree, tree); ! extern tree grokbitfield (tree, tree, tree); ! extern tree groktypefield (tree, tree); extern void cplus_decl_attributes (tree *, tree, int); - extern void defer_fn (tree); extern void finish_anon_union (tree); ! extern tree finish_table (tree, tree, tree, int); extern tree coerce_new_type (tree); extern tree coerce_delete_type (tree); extern void comdat_linkage (tree); ! extern void import_export_vtable (tree, tree, int); extern void import_export_decl (tree); - extern void import_export_tinfo (tree, tree, bool); extern tree build_cleanup (tree); extern tree build_offset_ref_call_from_tree (tree, tree); extern void check_default_args (tree); extern void mark_used (tree); extern void finish_static_data_member_decl (tree, tree, tree, int); extern tree cp_build_parm_decl (tree, tree); - extern tree build_artificial_parm (tree, tree); extern tree get_guard (tree); extern tree get_guard_cond (tree); extern tree set_guard (tree); extern tree cxx_callgraph_analyze_expr (tree *, int *, tree); /* XXX Not i18n clean. */ #define cp_deprecated(STR) \ --- 3831,3885 ---- extern int local_variable_p (tree); extern int nonstatic_local_decl_p (tree); extern tree declare_global_var (tree, tree); ! extern tree register_dtor_fn (tree); extern tmpl_spec_kind current_tmpl_spec_kind (int); extern tree cp_fname_init (const char *, tree *); + extern tree builtin_function (const char *name, tree type, + int code, + enum built_in_class cl, + const char *libname, tree attrs); extern tree check_elaborated_type_specifier (enum tag_types, tree, bool); extern void warn_extern_redeclared_static (tree, tree); ! extern const char *cxx_comdat_group (tree); ! extern bool cp_missing_noreturn_ok_p (tree); ! extern void initialize_artificial_var (tree, tree); ! extern tree check_var_type (tree, tree); extern bool have_extern_spec; /* in decl2.c */ extern bool check_java_method (tree); ! extern cp_cv_quals grok_method_quals (tree, tree, cp_cv_quals); extern void maybe_retrofit_in_chrg (tree); extern void maybe_make_one_only (tree); ! extern void grokclassfn (tree, tree, enum overload_flags, cp_cv_quals); extern tree grok_array_decl (tree, tree); extern tree delete_sanity (tree, tree, bool, int); ! extern tree check_classfn (tree, tree, tree); extern void check_member_template (tree); ! extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree); ! extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, tree); extern void cplus_decl_attributes (tree *, tree, int); extern void finish_anon_union (tree); ! extern void cp_finish_file (void); extern tree coerce_new_type (tree); extern tree coerce_delete_type (tree); extern void comdat_linkage (tree); ! extern void determine_visibility (tree); extern void import_export_decl (tree); extern tree build_cleanup (tree); extern tree build_offset_ref_call_from_tree (tree, tree); extern void check_default_args (tree); extern void mark_used (tree); extern void finish_static_data_member_decl (tree, tree, tree, int); extern tree cp_build_parm_decl (tree, tree); extern tree get_guard (tree); extern tree get_guard_cond (tree); extern tree set_guard (tree); extern tree cxx_callgraph_analyze_expr (tree *, int *, tree); + extern void mark_needed (tree); + extern bool decl_needed_p (tree); + extern void note_vague_linkage_fn (tree); /* XXX Not i18n clean. */ #define cp_deprecated(STR) \ *************** extern void init_error (void); *** 3781,3801 **** extern const char *type_as_string (tree, int); extern const char *decl_as_string (tree, int); extern const char *expr_as_string (tree, int); - extern const char *context_as_string (tree, int); extern const char *lang_decl_name (tree, int); extern const char *language_to_string (enum languages); extern void print_instantiation_context (void); /* in except.c */ extern void init_exception_processing (void); extern tree expand_start_catch_block (tree); extern void expand_end_catch_block (void); - extern void expand_builtin_throw (void); - extern void expand_eh_spec_block (tree); - extern void expand_exception_blocks (void); extern tree build_exc_ptr (void); extern tree build_throw (tree); - extern void mark_all_runtime_matches (void); extern int nothrow_libfn_p (tree); extern void check_handlers (tree); extern void choose_personality_routine (enum languages); --- 3894,3910 ---- extern const char *type_as_string (tree, int); extern const char *decl_as_string (tree, int); extern const char *expr_as_string (tree, int); extern const char *lang_decl_name (tree, int); extern const char *language_to_string (enum languages); + extern const char *class_key_or_enum_as_string (tree); extern void print_instantiation_context (void); /* in except.c */ extern void init_exception_processing (void); extern tree expand_start_catch_block (tree); extern void expand_end_catch_block (void); extern tree build_exc_ptr (void); extern tree build_throw (tree); extern int nothrow_libfn_p (tree); extern void check_handlers (tree); extern void choose_personality_routine (enum languages); *************** extern tree cplus_expand_constant *** 3811,3817 **** extern int is_friend (tree, tree); extern void make_friend_class (tree, tree, bool); extern void add_friend (tree, tree, bool); ! extern tree do_friend (tree, tree, tree, tree, enum overload_flags, tree, int); /* in init.c */ extern tree expand_member_init (tree); --- 3920,3926 ---- extern int is_friend (tree, tree); extern void make_friend_class (tree, tree, bool); extern void add_friend (tree, tree, bool); ! extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int); /* in init.c */ extern tree expand_member_init (tree); *************** extern void emit_mem_initializers (tree *** 3819,3853 **** extern tree build_aggr_init (tree, tree, int); extern tree build_init (tree, tree, int); extern int is_aggr_type (tree, int); - extern tree get_aggr_from_typedef (tree, int); extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_offset_ref (tree, tree, bool); ! extern tree build_new (tree, tree, tree, int); extern tree build_vec_init (tree, tree, tree, int); extern tree build_x_delete (tree, int, tree); extern tree build_delete (tree, tree, special_function_kind, int, int); extern void push_base_cleanups (void); - extern tree build_vbase_delete (tree, tree); extern tree build_vec_delete (tree, tree, special_function_kind, int); extern tree create_temporary_var (tree); extern void initialize_vtbl_ptrs (tree); extern tree build_java_class_ref (tree); ! ! /* in input.c */ /* in lex.c */ extern void cxx_dup_lang_specific_decl (tree); - extern tree make_pointer_declarator (tree, tree); - extern tree make_reference_declarator (tree, tree); - extern tree make_call_declarator (tree, tree, tree, tree); - extern void set_quals_and_spec (tree, tree, tree); - extern void print_parse_statistics (void); - extern void do_pending_inlines (void); extern void yyungetc (int, int); - extern void snarf_method (tree); - extern void see_typename (void); extern tree unqualified_name_lookup_error (tree); extern tree unqualified_fn_lookup_error (tree); extern tree build_lang_decl (enum tree_code, tree, tree); --- 3928,3951 ---- extern tree build_aggr_init (tree, tree, int); extern tree build_init (tree, tree, int); extern int is_aggr_type (tree, int); extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_offset_ref (tree, tree, bool); ! extern tree build_new (tree, tree, tree, tree, int); extern tree build_vec_init (tree, tree, tree, int); extern tree build_x_delete (tree, int, tree); extern tree build_delete (tree, tree, special_function_kind, int, int); extern void push_base_cleanups (void); extern tree build_vec_delete (tree, tree, special_function_kind, int); extern tree create_temporary_var (tree); extern void initialize_vtbl_ptrs (tree); extern tree build_java_class_ref (tree); ! extern tree integral_constant_value (tree); /* in lex.c */ extern void cxx_dup_lang_specific_decl (tree); extern void yyungetc (int, int); extern tree unqualified_name_lookup_error (tree); extern tree unqualified_fn_lookup_error (tree); extern tree build_lang_decl (enum tree_code, tree, tree); *************** extern tree cxx_make_type (enum tree_c *** 3858,3880 **** extern tree make_aggr_type (enum tree_code); extern void yyerror (const char *); extern void yyhook (int); - extern int cp_type_qual_from_rid (tree); extern bool cxx_init (void); extern void cxx_finish (void); /* in method.c */ extern void init_method (void); - extern void set_mangled_name_for_decl (tree); extern tree make_thunk (tree, bool, tree, tree); extern void finish_thunk (tree); extern void use_thunk (tree, bool); extern void synthesize_method (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool); extern tree skip_artificial_parms_for (tree, tree); /* In optimize.c */ - extern void optimize_function (tree); - extern bool calls_setjmp_p (tree); extern bool maybe_clone_body (tree); /* in pt.c */ --- 3956,3975 ---- extern tree make_aggr_type (enum tree_code); extern void yyerror (const char *); extern void yyhook (int); extern bool cxx_init (void); extern void cxx_finish (void); /* in method.c */ extern void init_method (void); extern tree make_thunk (tree, bool, tree, tree); extern void finish_thunk (tree); extern void use_thunk (tree, bool); extern void synthesize_method (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool); + extern tree lazily_declare_fn (special_function_kind, tree); extern tree skip_artificial_parms_for (tree, tree); /* In optimize.c */ extern bool maybe_clone_body (tree); /* in pt.c */ *************** extern void end_specialization *** 3890,3896 **** extern void begin_explicit_instantiation (void); extern void end_explicit_instantiation (void); extern tree check_explicit_specialization (tree, tree, int, int); ! extern tree process_template_parm (tree, tree); extern tree end_template_parm_list (tree); extern void end_template_decl (void); extern tree current_template_args (void); --- 3985,3991 ---- extern void begin_explicit_instantiation (void); extern void end_explicit_instantiation (void); extern tree check_explicit_specialization (tree, tree, int, int); ! extern tree process_template_parm (tree, tree, bool); extern tree end_template_parm_list (tree); extern void end_template_decl (void); extern tree current_template_args (void); *************** extern int uses_template_parms_level (t *** 3904,3930 **** extern tree instantiate_class_template (tree); extern tree instantiate_template (tree, tree, tsubst_flags_t); extern int fn_type_unification (tree, tree, tree, tree, tree, unification_kind_t, int); - extern tree tinst_for_decl (void); extern void mark_decl_instantiated (tree, int); extern int more_specialized (tree, tree, int, int); extern void mark_class_instantiated (tree, int); extern void do_decl_instantiation (tree, tree); extern void do_type_instantiation (tree, tree, tsubst_flags_t); ! extern tree instantiate_decl (tree, int); extern int push_tinst_level (tree); extern void pop_tinst_level (void); extern int more_specialized_class (tree, tree, tree); - extern int is_member_template (tree); extern int comp_template_parms (tree, tree); extern int template_class_depth (tree); extern int is_specialization_of (tree, tree); extern bool is_specialization_of_friend (tree, tree); extern int comp_template_args (tree, tree); extern void maybe_process_partial_specialization (tree); - extern void maybe_check_template_type (tree); extern tree most_specialized_instantiation (tree); extern void print_candidates (tree); ! extern int instantiate_pending_templates (void); extern tree tsubst_default_argument (tree, tree, tree); extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree, bool); extern tree most_general_template (tree); --- 3999,4022 ---- extern tree instantiate_class_template (tree); extern tree instantiate_template (tree, tree, tsubst_flags_t); extern int fn_type_unification (tree, tree, tree, tree, tree, unification_kind_t, int); extern void mark_decl_instantiated (tree, int); extern int more_specialized (tree, tree, int, int); extern void mark_class_instantiated (tree, int); extern void do_decl_instantiation (tree, tree); extern void do_type_instantiation (tree, tree, tsubst_flags_t); ! extern tree instantiate_decl (tree, int, int); extern int push_tinst_level (tree); extern void pop_tinst_level (void); extern int more_specialized_class (tree, tree, tree); extern int comp_template_parms (tree, tree); extern int template_class_depth (tree); extern int is_specialization_of (tree, tree); extern bool is_specialization_of_friend (tree, tree); extern int comp_template_args (tree, tree); extern void maybe_process_partial_specialization (tree); extern tree most_specialized_instantiation (tree); extern void print_candidates (tree); ! extern void instantiate_pending_templates (int); extern tree tsubst_default_argument (tree, tree, tree); extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree, bool); extern tree most_general_template (tree); *************** extern tree build_non_dependent_expr *** 3947,3962 **** extern tree build_non_dependent_args (tree); extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); /* in repo.c */ ! extern void repo_template_used (tree); ! extern void repo_template_instantiated (tree, bool); ! extern void init_repo (const char *); extern void finish_repo (void); /* in rtti.c */ ! /* A varray of all tinfo decls that haven't been emitted yet. */ ! extern GTY(()) varray_type unemitted_tinfo_decls; extern void init_rtti_processing (void); extern tree build_typeid (tree); --- 4039,4055 ---- extern tree build_non_dependent_args (tree); extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); + extern tree fold_decl_constant_value (tree); /* in repo.c */ ! extern void init_repo (void); ! extern int repo_emit_p (tree); ! extern bool repo_export_class_p (tree); extern void finish_repo (void); /* in rtti.c */ ! /* A vector of all tinfo decls that haven't been emitted yet. */ ! extern GTY(()) VEC(tree) *unemitted_tinfo_decls; extern void init_rtti_processing (void); extern tree build_typeid (tree); *************** extern void emit_support_tinfos (void); *** 3967,3991 **** extern bool emit_tinfo_decl (tree); /* in search.c */ ! extern bool accessible_base_p (tree, tree); extern tree lookup_base (tree, tree, base_access, base_kind *); ! extern int types_overlap_p (tree, tree); ! extern tree get_dynamic_cast_base_type (tree, tree); ! extern int accessible_p (tree, tree); extern tree lookup_field_1 (tree, tree, bool); extern tree lookup_field (tree, tree, int, bool); extern int lookup_fnfields_1 (tree, tree); extern tree lookup_fnfields (tree, tree, int); extern tree lookup_member (tree, tree, int, bool); extern int look_for_overrides (tree, tree); extern void get_pure_virtuals (tree); extern void maybe_suppress_debug_info (tree); extern void note_debug_info_needed (tree); - extern void push_class_decls (tree); - extern void pop_class_decls (void); - extern void unuse_fields (tree); extern void print_search_statistics (void); - extern void init_search_processing (void); extern void reinit_search_statistics (void); extern tree current_scope (void); extern int at_function_scope_p (void); --- 4060,4080 ---- extern bool emit_tinfo_decl (tree); /* in search.c */ ! extern bool accessible_base_p (tree, tree, bool); extern tree lookup_base (tree, tree, base_access, base_kind *); ! extern tree dcast_base_hint (tree, tree); ! extern int accessible_p (tree, tree, bool); extern tree lookup_field_1 (tree, tree, bool); extern tree lookup_field (tree, tree, int, bool); extern int lookup_fnfields_1 (tree, tree); + extern int class_method_index_for_fn (tree, tree); extern tree lookup_fnfields (tree, tree, int); extern tree lookup_member (tree, tree, int, bool); extern int look_for_overrides (tree, tree); extern void get_pure_virtuals (tree); extern void maybe_suppress_debug_info (tree); extern void note_debug_info_needed (tree); extern void print_search_statistics (void); extern void reinit_search_statistics (void); extern tree current_scope (void); extern int at_function_scope_p (void); *************** extern bool at_class_scope_p *** 3993,4014 **** extern bool at_namespace_scope_p (void); extern tree context_for_name_lookup (tree); extern tree lookup_conversions (tree); - extern tree binfo_for_vtable (tree); extern tree binfo_from_vbase (tree); extern tree look_for_overrides_here (tree, tree); ! extern int check_final_overrider (tree, tree); ! extern tree dfs_walk (tree, ! tree (*) (tree, void *), ! tree (*) (tree, int, void *), ! void *); ! extern tree dfs_walk_real (tree, ! tree (*) (tree, void *), ! tree (*) (tree, void *), ! tree (*) (tree, int, void *), ! void *); ! extern tree dfs_unmark (tree, void *); ! extern tree markedp (tree, int, void *); ! extern tree unmarkedp (tree, int, void *); extern tree binfo_via_virtual (tree, tree); extern tree build_baselink (tree, tree, tree, tree); extern tree adjust_result_of_qualified_name_lookup --- 4082,4095 ---- extern bool at_namespace_scope_p (void); extern tree context_for_name_lookup (tree); extern tree lookup_conversions (tree); extern tree binfo_from_vbase (tree); + extern tree binfo_for_vbase (tree, tree); extern tree look_for_overrides_here (tree, tree); ! #define dfs_skip_bases ((tree)1) ! extern tree dfs_walk_all (tree, tree (*) (tree, void *), ! tree (*) (tree, void *), void *); ! extern tree dfs_walk_once (tree, tree (*) (tree, void *), ! tree (*) (tree, void *), void *); extern tree binfo_via_virtual (tree, tree); extern tree build_baselink (tree, tree, tree, tree); extern tree adjust_result_of_qualified_name_lookup *************** extern void pop_to_parent_deferring_acce *** 4027,4039 **** extern void perform_deferred_access_checks (void); extern void perform_or_defer_access_check (tree, tree); extern void init_cp_semantics (void); extern tree finish_expr_stmt (tree); extern tree begin_if_stmt (void); extern void finish_if_stmt_cond (tree, tree); extern tree finish_then_clause (tree); ! extern void begin_else_clause (void); extern void finish_else_clause (tree); ! extern void finish_if_stmt (void); extern tree begin_while_stmt (void); extern void finish_while_stmt_cond (tree, tree); extern void finish_while_stmt (tree); --- 4108,4121 ---- extern void perform_deferred_access_checks (void); extern void perform_or_defer_access_check (tree, tree); extern void init_cp_semantics (void); + extern void add_decl_expr (tree); extern tree finish_expr_stmt (tree); extern tree begin_if_stmt (void); extern void finish_if_stmt_cond (tree, tree); extern tree finish_then_clause (tree); ! extern void begin_else_clause (tree); extern void finish_else_clause (tree); ! extern void finish_if_stmt (tree); extern tree begin_while_stmt (void); extern void finish_while_stmt_cond (tree, tree); extern void finish_while_stmt (tree); *************** extern void finish_function_handler_sequ *** 4064,4082 **** extern void finish_cleanup_try_block (tree); extern tree begin_handler (void); extern void finish_handler_parms (tree, tree); - extern void begin_catch_block (tree); extern void finish_handler (tree); extern void finish_cleanup (tree, tree); ! extern tree begin_compound_stmt (bool); ! extern tree finish_compound_stmt (tree); ! extern tree finish_asm_stmt (tree, tree, tree, tree, tree); extern tree finish_label_stmt (tree); extern void finish_label_decl (tree); - extern void finish_subobject (tree); extern tree finish_parenthesized_expr (tree); extern tree finish_non_static_data_member (tree, tree, tree); extern tree begin_stmt_expr (void); ! extern tree finish_stmt_expr_expr (tree); extern tree finish_stmt_expr (tree, bool); extern tree perform_koenig_lookup (tree, tree); extern tree finish_call_expr (tree, tree, bool, bool); --- 4146,4169 ---- extern void finish_cleanup_try_block (tree); extern tree begin_handler (void); extern void finish_handler_parms (tree, tree); extern void finish_handler (tree); extern void finish_cleanup (tree, tree); ! ! enum { ! BCS_NO_SCOPE = 1, ! BCS_TRY_BLOCK = 2, ! BCS_FN_BODY = 4 ! }; ! extern tree begin_compound_stmt (unsigned int); ! ! extern void finish_compound_stmt (tree); ! extern tree finish_asm_stmt (int, tree, tree, tree, tree); extern tree finish_label_stmt (tree); extern void finish_label_decl (tree); extern tree finish_parenthesized_expr (tree); extern tree finish_non_static_data_member (tree, tree, tree); extern tree begin_stmt_expr (void); ! extern tree finish_stmt_expr_expr (tree, tree); extern tree finish_stmt_expr (tree, bool); extern tree perform_koenig_lookup (tree, tree); extern tree finish_call_expr (tree, tree, bool, bool); *************** extern tree finish_pseudo_destructor_exp *** 4086,4125 **** extern tree finish_unary_op_expr (enum tree_code, tree); extern tree finish_compound_literal (tree, tree); extern tree finish_fname (tree); - extern int begin_function_definition (tree, tree, tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); extern tree finish_template_template_parm (tree, tree); - extern tree finish_parmlist (tree, int); extern tree begin_class_definition (tree); - extern void finish_default_args (void); - extern tree finish_member_class_template (tree); extern void finish_template_decl (tree); extern tree finish_template_type (tree, tree, int); extern tree finish_base_specifier (tree, tree, bool); extern void finish_member_declaration (tree); ! extern void check_multiple_declarators (void); ! extern void qualified_name_lookup_error (tree, tree); extern tree finish_id_expression (tree, tree, tree, cp_id_kind *, tree *, ! bool, bool, bool *, const char **); extern tree finish_typeof (tree); extern void finish_decl_cleanup (tree, tree); extern void finish_eh_cleanup (tree); extern void expand_body (tree); - extern void cxx_expand_function_start (void); - extern tree nullify_returns_r (tree *, int *, void *); - extern void do_pushlevel (scope_kind); - extern tree do_poplevel (void); extern void finish_mem_initializers (tree); - extern void setup_vtbl_ptr (tree, tree); - extern void clear_out_block (void); extern tree check_template_template_default_arg (tree); extern void expand_or_defer_fn (tree); extern void check_accessibility_of_qualified_id (tree, tree, tree); extern tree finish_qualified_id_expr (tree, tree, bool, bool); extern void simplify_aggr_init_expr (tree *); /* in tree.c */ extern void lang_check_failed (const char *, int, --- 4173,4203 ---- extern tree finish_unary_op_expr (enum tree_code, tree); extern tree finish_compound_literal (tree, tree); extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); extern tree finish_template_template_parm (tree, tree); extern tree begin_class_definition (tree); extern void finish_template_decl (tree); extern tree finish_template_type (tree, tree, int); extern tree finish_base_specifier (tree, tree, bool); extern void finish_member_declaration (tree); ! extern void qualified_name_lookup_error (tree, tree, tree); extern tree finish_id_expression (tree, tree, tree, cp_id_kind *, tree *, ! bool, bool, bool *, const char **); extern tree finish_typeof (tree); extern void finish_decl_cleanup (tree, tree); extern void finish_eh_cleanup (tree); extern void expand_body (tree); extern void finish_mem_initializers (tree); extern tree check_template_template_default_arg (tree); extern void expand_or_defer_fn (tree); extern void check_accessibility_of_qualified_id (tree, tree, tree); extern tree finish_qualified_id_expr (tree, tree, bool, bool); extern void simplify_aggr_init_expr (tree *); + extern void finalize_nrv (tree *, tree, tree); + extern void note_decl_for_pch (tree); /* in tree.c */ extern void lang_check_failed (const char *, int, *************** extern void lang_check_failed (const c *** 4127,4160 **** extern tree stabilize_expr (tree, tree *); extern void stabilize_call (tree, tree *); extern bool stabilize_init (tree, tree *); ! extern tree cxx_unsave_expr_now (tree); extern tree cxx_maybe_build_cleanup (tree); extern void init_tree (void); extern int pod_type_p (tree); extern int zero_init_p (tree); extern tree canonical_type_variant (tree); ! extern tree copy_base_binfos (tree, tree, tree); extern int member_p (tree); extern cp_lvalue_kind real_lvalue_p (tree); extern tree build_min (enum tree_code, tree, ...); extern tree build_min_nt (enum tree_code, ...); extern tree build_min_non_dep (enum tree_code, tree, ...); extern tree build_cplus_new (tree, tree); extern tree get_target_expr (tree); - extern tree build_cplus_staticfn_type (tree, tree, tree); extern tree build_cplus_array_type (tree, tree); extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_chain (tree, tree); - extern tree hash_chainon (tree, tree); - extern tree make_binfo (tree, tree, tree, tree); - extern int count_functions (tree); extern int is_overloaded_fn (tree); extern tree get_first_fn (tree); - extern int bound_pmf_p (tree); extern tree ovl_cons (tree, tree); extern tree build_overload (tree, tree); - extern tree function_arg_chain (tree); - extern int promotes_to_aggr_type (tree, enum tree_code); extern const char *cxx_printable_name (tree, int); extern tree build_exception_variant (tree, tree); extern tree bind_template_template_parm (tree, tree); --- 4205,4233 ---- extern tree stabilize_expr (tree, tree *); extern void stabilize_call (tree, tree *); extern bool stabilize_init (tree, tree *); ! extern tree add_stmt_to_compound (tree, tree); extern tree cxx_maybe_build_cleanup (tree); extern void init_tree (void); extern int pod_type_p (tree); extern int zero_init_p (tree); extern tree canonical_type_variant (tree); ! extern tree copy_binfo (tree, tree, tree, ! tree *, int); extern int member_p (tree); extern cp_lvalue_kind real_lvalue_p (tree); + extern bool builtin_valid_in_constant_expr_p (tree); extern tree build_min (enum tree_code, tree, ...); extern tree build_min_nt (enum tree_code, ...); extern tree build_min_non_dep (enum tree_code, tree, ...); extern tree build_cplus_new (tree, tree); extern tree get_target_expr (tree); extern tree build_cplus_array_type (tree, tree); extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_chain (tree, tree); extern int is_overloaded_fn (tree); extern tree get_first_fn (tree); extern tree ovl_cons (tree, tree); extern tree build_overload (tree, tree); extern const char *cxx_printable_name (tree, int); extern tree build_exception_variant (tree, tree); extern tree bind_template_template_parm (tree, tree); *************** extern tree array_type_nelts_total (tre *** 4162,4176 **** extern tree array_type_nelts_top (tree); extern tree break_out_target_exprs (tree); extern tree get_type_decl (tree); - extern tree vec_binfo_member (tree, tree); extern tree decl_namespace_context (tree); extern tree lvalue_type (tree); extern tree error_type (tree); - extern tree build_zc_wrapper (struct z_candidate *); extern int varargs_function_p (tree); extern int really_overloaded_fn (tree); extern bool cp_tree_equal (tree, tree); ! extern tree no_linkage_check (tree); extern void debug_binfo (tree); extern tree build_dummy_object (tree); extern tree maybe_dummy_object (tree, tree *); --- 4235,4247 ---- extern tree array_type_nelts_top (tree); extern tree break_out_target_exprs (tree); extern tree get_type_decl (tree); extern tree decl_namespace_context (tree); extern tree lvalue_type (tree); extern tree error_type (tree); extern int varargs_function_p (tree); extern int really_overloaded_fn (tree); extern bool cp_tree_equal (tree, tree); ! extern tree no_linkage_check (tree, bool); extern void debug_binfo (tree); extern tree build_dummy_object (tree); extern tree maybe_dummy_object (tree, tree *); *************** extern tree cp_build_type_attribute_vari *** 4181,4202 **** extern tree cp_build_qualified_type_real (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 (int); extern special_function_kind special_function_p (tree); - extern bool name_p (tree); extern int count_trees (tree); extern int char_type_p (tree); extern void verify_stmt_tree (tree); extern tree find_tree (tree, tree); extern linkage_kind decl_linkage (tree); extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn, ! void*, void*); extern int cp_cannot_inline_tree_fn (tree*); extern tree cp_add_pending_fn_decls (void*,tree); - extern int cp_is_overload_p (tree); extern int cp_auto_var_in_fn_p (tree,tree); ! extern tree cp_copy_res_decl_for_inlining (tree, tree, tree, void*, ! int*, tree); /* in typeck.c */ extern int string_conv_p (tree, tree, int); --- 4252,4269 ---- extern tree cp_build_qualified_type_real (tree, int, tsubst_flags_t); #define cp_build_qualified_type(TYPE, QUALS) \ cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning) extern special_function_kind special_function_p (tree); extern int count_trees (tree); extern int char_type_p (tree); extern void verify_stmt_tree (tree); extern tree find_tree (tree, tree); extern linkage_kind decl_linkage (tree); extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn, ! void*, struct pointer_set_t*); extern int cp_cannot_inline_tree_fn (tree*); extern tree cp_add_pending_fn_decls (void*,tree); extern int cp_auto_var_in_fn_p (tree,tree); ! extern tree fold_if_not_in_template (tree); /* in typeck.c */ extern int string_conv_p (tree, tree, int); *************** extern tree condition_conversion (tree) *** 4205,4214 **** extern tree target_type (tree); extern tree require_complete_type (tree); extern tree complete_type (tree); ! extern tree complete_type_or_diagnostic (tree, tree, int); ! #define complete_type_or_else(T,V) (complete_type_or_diagnostic ((T), (V), 0)) extern int type_unknown_p (tree); - extern tree commonparms (tree, tree); extern tree original_type (tree); extern bool comp_except_specs (tree, tree, bool); extern bool comptypes (tree, tree, int); --- 4272,4279 ---- extern tree target_type (tree); extern tree require_complete_type (tree); extern tree complete_type (tree); ! extern tree complete_type_or_else (tree, tree); extern int type_unknown_p (tree); extern tree original_type (tree); extern bool comp_except_specs (tree, tree, bool); extern bool comptypes (tree, tree, int); *************** extern tree build_x_indirect_ref (tree, *** 4227,4234 **** extern tree build_indirect_ref (tree, const char *); extern tree build_array_ref (tree, tree); extern tree get_member_function_from_ptrfunc (tree *, tree); ! extern tree convert_arguments (tree, tree, tree, int); ! extern tree build_x_binary_op (enum tree_code, tree, tree, bool *); extern tree build_x_unary_op (enum tree_code, tree); extern tree unary_complex_lvalue (enum tree_code, tree); --- 4292,4298 ---- extern tree build_indirect_ref (tree, const char *); extern tree build_array_ref (tree, tree); extern tree get_member_function_from_ptrfunc (tree *, tree); ! extern tree build_x_binary_op (enum tree_code, tree, tree, bool *); extern tree build_x_unary_op (enum tree_code, tree); extern tree unary_complex_lvalue (enum tree_code, tree); *************** extern tree build_const_cast (tree, tr *** 4242,4256 **** extern tree build_c_cast (tree, tree); extern tree build_x_modify_expr (tree, enum tree_code, tree); extern tree build_modify_expr (tree, enum tree_code, tree); - extern tree dubious_conversion_warnings (tree, tree, const char *, tree, int); extern tree convert_for_initialization (tree, tree, tree, int, const char *, tree, int); extern int comp_ptr_ttypes (tree, tree); extern int ptr_reasonably_similar (tree, tree); ! extern tree build_ptrmemfunc (tree, tree, int); extern int cp_type_quals (tree); extern bool cp_has_mutable_p (tree); extern bool at_least_as_qualified_p (tree, tree); ! extern bool more_qualified_p (tree, tree); extern tree build_ptrmemfunc1 (tree, tree, tree); extern void expand_ptrmemfunc_cst (tree, tree *, tree *); extern tree pfn_from_ptrmemfunc (tree); --- 4306,4319 ---- extern tree build_c_cast (tree, tree); extern tree build_x_modify_expr (tree, enum tree_code, tree); extern tree build_modify_expr (tree, enum tree_code, tree); extern tree convert_for_initialization (tree, tree, tree, int, const char *, tree, int); extern int comp_ptr_ttypes (tree, tree); extern int ptr_reasonably_similar (tree, tree); ! extern tree build_ptrmemfunc (tree, tree, int, bool); extern int cp_type_quals (tree); extern bool cp_has_mutable_p (tree); extern bool at_least_as_qualified_p (tree, tree); ! extern void cp_apply_type_quals_to_decl (int, tree); extern tree build_ptrmemfunc1 (tree, tree, tree); extern void expand_ptrmemfunc_cst (tree, tree *, tree *); extern tree pfn_from_ptrmemfunc (tree); *************** extern tree build_nop *** 4269,4274 **** --- 4332,4339 ---- extern tree non_reference (tree); extern tree lookup_anon_field (tree, tree); extern bool invalid_nonstatic_memfn_p (tree); + extern tree convert_member_func_to_ptr (tree, tree); + extern tree convert_ptrmem (tree, tree, bool, bool); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); *************** extern void cxx_incomplete_type_error ( *** 4280,4285 **** --- 4345,4351 ---- extern tree error_not_base_type (tree, tree); extern tree binfo_or_else (tree, tree); extern void readonly_error (tree, const char *, int); + extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); extern tree store_init_value (tree, tree); *************** extern tree merge_exception_specifiers *** 4295,4301 **** extern void init_mangle (void); extern void mangle_decl (tree); extern const char *mangle_type_string (tree); - extern tree mangle_type (tree); extern tree mangle_typeinfo_for_type (tree); extern tree mangle_typeinfo_string_for_type (tree); extern tree mangle_vtbl_for_type (tree); --- 4361,4366 ---- *************** extern tree mangle_ref_init_variable *** 4309,4314 **** --- 4374,4383 ---- /* in dump.c */ extern bool cp_dump_tree (void *, tree); + /* in cp-gimplify.c */ + extern int cp_gimplify_expr (tree *, tree *, tree *); + extern void cp_genericize (tree); + /* -- end of C++ */ /* In order for the format checking to accept the C++ frontend diff -Nrcpad gcc-3.4.3/gcc/cp/cvt.c gcc-4.0.0/gcc/cp/cvt.c *** gcc-3.4.3/gcc/cp/cvt.c Mon May 31 21:04:10 2004 --- gcc-4.0.0/gcc/cp/cvt.c Wed Feb 9 02:53:37 2005 *************** *** 1,6 **** /* Language-level data type conversion for GNU C++. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Language-level data type conversion for GNU C++. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** cp_convert_to_pointer (tree type, tree e *** 79,92 **** tree intype = TREE_TYPE (expr); enum tree_code form; tree rval; if (IS_AGGR_TYPE (intype)) { intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { ! error ("can't convert from incomplete type `%T' to `%T'", ! intype, type); return error_mark_node; } --- 79,94 ---- tree intype = TREE_TYPE (expr); enum tree_code form; tree rval; + if (intype == error_mark_node) + return error_mark_node; if (IS_AGGR_TYPE (intype)) { intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { ! error ("can't convert from incomplete type %qT to %qT", ! intype, type); return error_mark_node; } *************** cp_convert_to_pointer (tree type, tree e *** 94,101 **** if (rval) { if (rval == error_mark_node) ! error ("conversion of `%E' from `%T' to `%T' is ambiguous", ! expr, intype, type); return rval; } } --- 96,103 ---- if (rval) { if (rval == error_mark_node) ! error ("conversion of %qE from %qT to %qT is ambiguous", ! expr, intype, type); return rval; } } *************** cp_convert_to_pointer (tree type, tree e *** 105,132 **** && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE || VOID_TYPE_P (TREE_TYPE (type)))) { ! /* Allow an implicit this pointer for pointer to member ! functions. */ ! if (TYPE_PTRMEMFUNC_P (intype)) ! { ! if (pedantic || warn_pmf2ptr) ! pedwarn ("converting from `%T' to `%T'", intype, type); ! if (TREE_CODE (expr) == PTRMEM_CST) ! expr = build_address (PTRMEM_CST_MEMBER (expr)); ! else ! { ! tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), ! 0); ! decl = build_address (decl); ! expr = get_member_function_from_ptrfunc (&decl, expr); ! } ! } ! else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) ! { ! if (pedantic || warn_pmf2ptr) ! pedwarn ("converting from `%T' to `%T'", intype, type); ! expr = build_addr_func (expr); ! } if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); --- 107,115 ---- && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE || VOID_TYPE_P (TREE_TYPE (type)))) { ! if (TYPE_PTRMEMFUNC_P (intype) ! || TREE_CODE (intype) == METHOD_TYPE) ! return convert_member_func_to_ptr (type, expr); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); *************** cp_convert_to_pointer (tree type, tree e *** 182,189 **** if (TYPE_PTRMEMFUNC_P (type)) { ! error ("cannot convert `%E' from type `%T' to type `%T'", ! expr, intype, type); return error_mark_node; } --- 165,172 ---- if (TYPE_PTRMEMFUNC_P (type)) { ! error ("cannot convert %qE from type %qT to type %qT", ! expr, intype, type); return error_mark_node; } *************** cp_convert_to_pointer (tree type, tree e *** 211,222 **** if (bk == bk_via_virtual) { if (force) ! warning ("pointer to member cast from `%T' to `%T' is via virtual base", ! intype, type); else { ! error ("pointer to member cast from `%T' to `%T' is via virtual base", ! intype, type); return error_mark_node; } /* This is a reinterpret cast, whose result is unspecified. --- 194,205 ---- if (bk == bk_via_virtual) { if (force) ! warning ("pointer to member cast from %qT to %qT is via" ! " virtual base", intype, type); else { ! error ("pointer to member cast from %qT to %qT is" ! " via virtual base", intype, type); return error_mark_node; } /* This is a reinterpret cast, whose result is unspecified. *************** cp_convert_to_pointer (tree type, tree e *** 234,240 **** 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); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) --- 217,224 ---- 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, ! /*c_cast_p=*/false); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) *************** cp_convert_to_pointer (tree type, tree e *** 250,279 **** TREE_OPERAND (expr, 1)); } } ! error ("cannot convert `%E' from type `%T' to type `%T'", ! expr, intype, type); return error_mark_node; } if (integer_zerop (expr)) { if (TYPE_PTRMEMFUNC_P (type)) ! return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); if (TYPE_PTRMEM_P (type)) ! /* A NULL pointer-to-member is represented by -1, not by ! zero. */ ! expr = build_int_2 (-1, -1); else ! expr = build_int_2 (0, 0); ! TREE_TYPE (expr) = type; ! /* Fix up the representation of -1 if appropriate. */ ! force_fit_type (expr, 0); return expr; } else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form)) { ! error ("invalid conversion from '%T' to '%T'", intype, type); return error_mark_node; } --- 234,266 ---- TREE_OPERAND (expr, 1)); } } ! error ("cannot convert %qE from type %qT to type %qT", ! expr, intype, type); return error_mark_node; } if (integer_zerop (expr)) { if (TYPE_PTRMEMFUNC_P (type)) ! return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, ! /*c_cast_p=*/false); if (TYPE_PTRMEM_P (type)) ! { ! /* A NULL pointer-to-member is represented by -1, not by ! zero. */ ! expr = build_int_cst (type, -1); ! /* Fix up the representation of -1 if appropriate. */ ! expr = force_fit_type (expr, 0, false, false); ! } else ! expr = build_int_cst (type, 0); ! return expr; } else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form)) { ! error ("invalid conversion from %qT to %qT", intype, type); return error_mark_node; } *************** cp_convert_to_pointer (tree type, tree e *** 282,301 **** if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, 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))) ! /* There is supposed to be some integral type ! that is the same width as a pointer. */ ! abort (); return convert_to_pointer (type, expr); } if (type_unknown_p (expr)) return instantiate_type (type, expr, tf_error | tf_warning); ! error ("cannot convert `%E' from type `%T' to type `%T'", ! expr, intype, type); return error_mark_node; } --- 269,288 ---- if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); ! /* Modes may be different but sizes should be the same. There ! is supposed to be some integral type that is the same width ! as a pointer. */ ! gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) ! == GET_MODE_SIZE (TYPE_MODE (type))); ! return convert_to_pointer (type, expr); } if (type_unknown_p (expr)) return instantiate_type (type, expr, tf_error | tf_warning); ! error ("cannot convert %qE from type %qT to type %qT", ! expr, intype, type); return error_mark_node; } *************** convert_to_pointer_force (tree type, tre *** 323,333 **** tree binfo; binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type), ! ba_ignore, NULL); if (!binfo) { binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ! ba_ignore, NULL); code = MINUS_EXPR; } if (binfo == error_mark_node) --- 310,320 ---- tree binfo; binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type), ! ba_unique, NULL); if (!binfo) { binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ! ba_unique, NULL); code = MINUS_EXPR; } if (binfo == error_mark_node) *************** build_up_reference (tree type, tree arg, *** 364,370 **** tree argtype = TREE_TYPE (arg); tree target_type = TREE_TYPE (type); ! my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187); if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) { --- 351,357 ---- tree argtype = TREE_TYPE (arg); tree target_type = TREE_TYPE (type); ! gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) { *************** warn_ref_binding (tree reftype, tree int *** 426,438 **** const char *msg; if (CP_TYPE_VOLATILE_P (ttl) && decl) ! msg = "initialization of volatile reference type `%#T' from rvalue of type `%T'"; else if (CP_TYPE_VOLATILE_P (ttl)) ! msg = "conversion to volatile reference type `%#T' from rvalue of type `%T'"; else if (decl) ! msg = "initialization of non-const reference type `%#T' from rvalue of type `%T'"; else ! msg = "conversion to non-const reference type `%#T' from rvalue of type `%T'"; pedwarn (msg, reftype, intype); } --- 413,429 ---- const char *msg; if (CP_TYPE_VOLATILE_P (ttl) && decl) ! msg = "initialization of volatile reference type %q#T from" ! " rvalue of type %qT"; else if (CP_TYPE_VOLATILE_P (ttl)) ! msg = "conversion to volatile reference type %q#T " ! " from rvalue of type %qT"; else if (decl) ! msg = "initialization of non-const reference type %q#T from" ! " rvalue of type %qT"; else ! msg = "conversion to non-const reference type %q#T from" ! " rvalue of type %qT"; pedwarn (msg, reftype, intype); } *************** convert_to_reference (tree reftype, tree *** 460,474 **** expr = instantiate_type (type, expr, (flags & LOOKUP_COMPLAIN) ? tf_error | tf_warning : tf_none); - else - expr = convert_from_reference (expr); if (expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); ! my_friendly_assert (TREE_CODE (intype) != REFERENCE_TYPE, 364); intype = TYPE_MAIN_VARIANT (intype); --- 451,463 ---- expr = instantiate_type (type, expr, (flags & LOOKUP_COMPLAIN) ? tf_error | tf_warning : tf_none); if (expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); ! gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE); intype = TYPE_MAIN_VARIANT (intype); *************** convert_to_reference (tree reftype, tree *** 505,512 **** if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) ! pedwarn ("conversion from `%T' to `%T' discards qualifiers", ! ttr, reftype); } return build_up_reference (reftype, expr, flags, decl); --- 494,501 ---- if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) ! pedwarn ("conversion from %qT to %qT discards qualifiers", ! ttr, reftype); } return build_up_reference (reftype, expr, flags, decl); *************** convert_to_reference (tree reftype, tree *** 523,529 **** if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) ! warning ("casting `%T' to `%T' does not dereference pointer", intype, reftype); rval = build_unary_op (ADDR_EXPR, expr, 0); --- 512,518 ---- if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) ! warning ("casting %qT to %qT does not dereference pointer", intype, reftype); rval = build_unary_op (ADDR_EXPR, expr, 0); *************** convert_to_reference (tree reftype, tree *** 550,559 **** } if (flags & LOOKUP_COMPLAIN) ! error ("cannot convert type `%T' to type `%T'", intype, reftype); ! ! if (flags & LOOKUP_SPECULATIVELY) ! return NULL_TREE; return error_mark_node; } --- 539,545 ---- } if (flags & LOOKUP_COMPLAIN) ! error ("cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; } *************** tree *** 565,587 **** convert_from_reference (tree val) { if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE) ! return build_indirect_ref (val, NULL); return val; } - /* Implicitly convert the lvalue EXPR to another lvalue of type TOTYPE, - preserving cv-qualification. */ - - tree - convert_lvalue (tree totype, tree expr) - { - totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr))); - totype = build_reference_type (totype); - expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL, - NULL_TREE); - return convert_from_reference (expr); - } - /* Really perform an lvalue-to-rvalue conversion, including copying an argument of class type into a temporary. */ --- 551,574 ---- convert_from_reference (tree val) { if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE) ! { ! tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val))); ! tree ref = build1 (INDIRECT_REF, t, val); ! ! /* We *must* set TREE_READONLY when dereferencing a pointer to const, ! so that we get the proper error message if the result is used ! to assign to. Also, &* is supposed to be a no-op. */ ! TREE_READONLY (ref) = CP_TYPE_CONST_P (t); ! TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t); ! TREE_SIDE_EFFECTS (ref) ! = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val)); ! REFERENCE_REF_P (ref) = 1; ! val = ref; ! } ! return val; } /* Really perform an lvalue-to-rvalue conversion, including copying an argument of class type into a temporary. */ *************** ocp_convert (tree type, tree expr, int c *** 621,627 **** complete_type (type); complete_type (TREE_TYPE (expr)); ! e = decl_constant_value (e); if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP) /* Some internal structures (vtable_entry_type, sigtbl_ptr_type) --- 608,614 ---- complete_type (type); complete_type (TREE_TYPE (expr)); ! e = integral_constant_value (e); if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP) /* Some internal structures (vtable_entry_type, sigtbl_ptr_type) *************** ocp_convert (tree type, tree expr, int c *** 642,664 **** /* For complex data types, we need to perform componentwise conversion. */ else if (TREE_CODE (type) == COMPLEX_TYPE) ! return fold (convert_to_complex (type, e)); else if (TREE_CODE (e) == TARGET_EXPR) { /* Don't build a NOP_EXPR of class type. Instead, change the type of the temporary. Only allow this for cv-qual changes, though. */ ! if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)), ! TYPE_MAIN_VARIANT (type))) ! abort (); TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type; return e; } - else if (TREE_ADDRESSABLE (type)) - /* We shouldn't be treating objects of ADDRESSABLE type as rvalues. */ - abort (); else ! return fold (build1 (NOP_EXPR, type, e)); } if (code == VOID_TYPE && (convtype & CONV_STATIC)) --- 629,652 ---- /* For complex data types, we need to perform componentwise conversion. */ else if (TREE_CODE (type) == COMPLEX_TYPE) ! return fold_if_not_in_template (convert_to_complex (type, e)); else if (TREE_CODE (e) == TARGET_EXPR) { /* Don't build a NOP_EXPR of class type. Instead, change the type of the temporary. Only allow this for cv-qual changes, though. */ ! gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)), ! TYPE_MAIN_VARIANT (type))); TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type; return e; } else ! { ! /* We shouldn't be treating objects of ADDRESSABLE type as ! rvalues. */ ! gcc_assert (!TREE_ADDRESSABLE (type)); ! return fold_if_not_in_template (build_nop (type, e)); ! } } if (code == VOID_TYPE && (convtype & CONV_STATIC)) *************** ocp_convert (tree type, tree expr, int c *** 673,682 **** /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (TREE_CODE (type) == ENUMERAL_TYPE ! && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC)) ! || (TREE_CODE (intype) == POINTER_TYPE))) { ! pedwarn ("conversion from `%#T' to `%#T'", intype, type); if (flag_pedantic_errors) return error_mark_node; --- 661,673 ---- /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (TREE_CODE (type) == ENUMERAL_TYPE ! && (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype) ! || TREE_CODE (intype) == REAL_TYPE) ! && ! (convtype & CONV_STATIC)) ! || TREE_CODE (intype) == POINTER_TYPE)) { ! if (flags & LOOKUP_COMPLAIN) ! pedwarn ("conversion from %q#T to %q#T", intype, type); if (flag_pedantic_errors) return error_mark_node; *************** ocp_convert (tree type, tree expr, int c *** 688,707 **** if (rval) return rval; if (flags & LOOKUP_COMPLAIN) ! error ("`%#T' used where a `%T' was expected", intype, type); ! if (flags & LOOKUP_SPECULATIVELY) ! return NULL_TREE; return error_mark_node; } if (code == BOOLEAN_TYPE) return cp_truthvalue_conversion (e); ! return fold (convert_to_integer (type, e)); } if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) ! return fold (cp_convert_to_pointer (type, e, false)); if (code == VECTOR_TYPE) ! return fold (convert_to_vector (type, e)); if (code == REAL_TYPE || code == COMPLEX_TYPE) { if (IS_AGGR_TYPE (TREE_TYPE (e))) --- 679,709 ---- if (rval) return rval; if (flags & LOOKUP_COMPLAIN) ! error ("%q#T used where a %qT was expected", intype, type); return error_mark_node; } if (code == BOOLEAN_TYPE) return cp_truthvalue_conversion (e); ! return fold_if_not_in_template (convert_to_integer (type, e)); } if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) ! return fold_if_not_in_template (cp_convert_to_pointer (type, e, false)); if (code == VECTOR_TYPE) ! { ! tree in_vtype = TREE_TYPE (e); ! if (IS_AGGR_TYPE (in_vtype)) ! { ! tree ret_val; ! ret_val = build_type_conversion (type, e); ! if (ret_val) ! return ret_val; ! if (flags & LOOKUP_COMPLAIN) ! error ("%q#T used where a %qT was expected", in_vtype, type); ! return error_mark_node; ! } ! return fold_if_not_in_template (convert_to_vector (type, e)); ! } if (code == REAL_TYPE || code == COMPLEX_TYPE) { if (IS_AGGR_TYPE (TREE_TYPE (e))) *************** ocp_convert (tree type, tree expr, int c *** 712,724 **** return rval; else if (flags & LOOKUP_COMPLAIN) ! error ("`%#T' used where a floating point value was expected", TREE_TYPE (e)); } if (code == REAL_TYPE) ! return fold (convert_to_real (type, e)); else if (code == COMPLEX_TYPE) ! return fold (convert_to_complex (type, e)); } /* New C++ semantics: since assignment is now based on --- 714,726 ---- return rval; else if (flags & LOOKUP_COMPLAIN) ! error ("%q#T used where a floating point value was expected", TREE_TYPE (e)); } if (code == REAL_TYPE) ! return fold_if_not_in_template (convert_to_real (type, e)); else if (code == COMPLEX_TYPE) ! return fold_if_not_in_template (convert_to_complex (type, e)); } /* New C++ semantics: since assignment is now based on *************** ocp_convert (tree type, tree expr, int c *** 753,768 **** 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 (flags & LOOKUP_COMPLAIN) ! error ("conversion from `%T' to non-scalar type `%T' requested", ! TREE_TYPE (expr), type); ! if (flags & LOOKUP_SPECULATIVELY) ! return NULL_TREE; return error_mark_node; } --- 755,768 ---- ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, ctor), ! type, flags); if (ctor) return build_cplus_new (type, ctor); } if (flags & LOOKUP_COMPLAIN) ! error ("conversion from %qT to non-scalar type %qT requested", ! TREE_TYPE (expr), type); return error_mark_node; } *************** convert_to_void (tree expr, const char * *** 793,798 **** --- 793,803 ---- return expr; if (invalid_nonstatic_memfn_p (expr)) return error_mark_node; + if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) + { + error ("pseudo-destructor is not called"); + return error_mark_node; + } if (VOID_TYPE_P (TREE_TYPE (expr))) return expr; switch (TREE_CODE (expr)) *************** convert_to_void (tree expr, const char * *** 809,816 **** (op2, (implicit && !TREE_SIDE_EFFECTS (op1) ? "third operand of conditional" : NULL)); ! expr = build (COND_EXPR, TREE_TYPE (new_op1), ! TREE_OPERAND (expr, 0), new_op1, new_op2); break; } --- 814,821 ---- (op2, (implicit && !TREE_SIDE_EFFECTS (op1) ? "third operand of conditional" : NULL)); ! expr = build3 (COND_EXPR, TREE_TYPE (new_op1), ! TREE_OPERAND (expr, 0), new_op1, new_op2); break; } *************** convert_to_void (tree expr, const char * *** 819,831 **** /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void ! (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr) ? "right-hand operand of comma" : NULL)); if (new_op1 != op1) { ! tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1), ! TREE_OPERAND (expr, 0), new_op1); expr = t; } --- 824,836 ---- /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void ! (op1, (implicit && !TREE_NO_WARNING (expr) ? "right-hand operand of comma" : NULL)); if (new_op1 != op1) { ! tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1), ! TREE_OPERAND (expr, 0), new_op1); expr = t; } *************** convert_to_void (tree expr, const char * *** 849,860 **** int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (is_volatile && !is_complete) ! warning ("object of incomplete type `%T' will not be accessed in %s", ! type, implicit ? implicit : "void context"); else if (is_reference && is_volatile) ! warning ("object of type `%T' will not be accessed in %s", ! TREE_TYPE (TREE_OPERAND (expr, 0)), ! implicit ? implicit : "void context"); if (is_reference || !is_volatile || !is_complete) expr = TREE_OPERAND (expr, 0); --- 854,865 ---- int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (is_volatile && !is_complete) ! warning ("object of incomplete type %qT will not be accessed in %s", ! type, implicit ? implicit : "void context"); else if (is_reference && is_volatile) ! warning ("object of type %qT will not be accessed in %s", ! TREE_TYPE (TREE_OPERAND (expr, 0)), ! implicit ? implicit : "void context"); if (is_reference || !is_volatile || !is_complete) expr = TREE_OPERAND (expr, 0); *************** convert_to_void (tree expr, const char * *** 868,875 **** int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete) ! warning ("object `%E' of incomplete type `%T' will not be accessed in %s", ! expr, type, implicit ? implicit : "void context"); break; } --- 873,880 ---- int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete) ! warning ("object %qE of incomplete type %qT will not be accessed in %s", ! expr, type, implicit ? implicit : "void context"); break; } *************** convert_to_void (tree expr, const char * *** 890,903 **** } else if (implicit && probe == expr && is_overloaded_fn (probe)) /* Only warn when there is no &. */ ! warning ("%s is a reference, not call, to function `%E'", implicit, expr); } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { ! if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value) ! warning ("%s has no effect", implicit); expr = build1 (CONVERT_EXPR, void_type_node, expr); } return expr; --- 895,946 ---- } else if (implicit && probe == expr && is_overloaded_fn (probe)) /* Only warn when there is no &. */ ! warning ("%s is a reference, not call, to function %qE", implicit, expr); } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { ! if (implicit && warn_unused_value && !TREE_NO_WARNING (expr)) ! { ! /* The middle end does not warn about expressions that have ! been explicitly cast to void, so we must do so here. */ ! if (!TREE_SIDE_EFFECTS (expr)) ! warning ("%s has no effect", implicit); ! else ! { ! tree e; ! enum tree_code code; ! enum tree_code_class class; ! ! e = expr; ! /* We might like to warn about (say) "(int) f()", as the ! cast has no effect, but the compiler itself will ! generate implicit conversions under some ! circumstances. (For example a block copy will be ! turned into a call to "__builtin_memcpy", with a ! conversion of the return value to an appropriate ! type.) So, to avoid false positives, we strip ! conversions. Do not use STRIP_NOPs because it will ! not strip conversions to "void", as that is not a ! mode-preserving conversion. */ ! while (TREE_CODE (e) == NOP_EXPR) ! e = TREE_OPERAND (e, 0); ! ! code = TREE_CODE (e); ! class = TREE_CODE_CLASS (code); ! if (class == tcc_comparison ! || class == tcc_unary ! || (class == tcc_binary ! && !(code == MODIFY_EXPR ! || code == INIT_EXPR ! || code == PREDECREMENT_EXPR ! || code == PREINCREMENT_EXPR ! || code == POSTDECREMENT_EXPR ! || code == POSTINCREMENT_EXPR))) ! warning ("value computed is not used"); ! } ! } expr = build1 (CONVERT_EXPR, void_type_node, expr); } return expr; *************** convert (tree type, tree expr) *** 931,940 **** intype = TREE_TYPE (expr); if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype)) ! { ! expr = decl_constant_value (expr); ! return fold (build1 (NOP_EXPR, type, expr)); ! } return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); --- 974,980 ---- intype = TREE_TYPE (expr); if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype)) ! return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); *************** convert_force (tree type, tree expr, int *** 951,963 **** enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) ! return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, ! NULL_TREE)); ! else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) ! e = convert_from_reference (e); if (code == POINTER_TYPE) ! return fold (convert_to_pointer_force (type, e)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR --- 991,1002 ---- enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) ! return (fold_if_not_in_template ! (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, ! NULL_TREE))); if (code == POINTER_TYPE) ! return fold_if_not_in_template (convert_to_pointer_force (type, e)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR *************** convert_force (tree type, tree expr, int *** 966,975 **** || integer_zerop (e) || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) && TYPE_PTRMEMFUNC_P (type)) ! { ! /* compatible pointer to member functions. */ ! return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); ! } return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); } --- 1005,1013 ---- || integer_zerop (e) || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) && TYPE_PTRMEMFUNC_P (type)) ! /* compatible pointer to member functions. */ ! return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, ! /*c_cast_p=*/1); return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); } *************** build_expr_type_conversion (int desires, *** 1010,1016 **** && !(desires & WANT_NULL)) warning ("converting NULL to non-pointer type"); - expr = convert_from_reference (expr); basetype = TREE_TYPE (expr); if (basetype == error_mark_node) --- 1048,1053 ---- *************** build_expr_type_conversion (int desires, *** 1081,1090 **** { if (complain) { ! error ("ambiguous default type conversion from `%T'", ! basetype); ! error (" candidate conversions include `%D' and `%D'", ! winner, cand); } return error_mark_node; } --- 1118,1127 ---- { if (complain) { ! error ("ambiguous default type conversion from %qT", ! basetype); ! error (" candidate conversions include %qD and %qD", ! winner, cand); } return error_mark_node; } *************** type_promotes_to (tree type) *** 1125,1131 **** int precision = MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)); tree totype = c_common_type_for_size (precision, 0); ! if (TREE_UNSIGNED (type) && ! int_fits_type_p (TYPE_MAX_VALUE (type), totype)) type = c_common_type_for_size (precision, 1); else --- 1162,1168 ---- int precision = MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)); tree totype = c_common_type_for_size (precision, 0); ! if (TYPE_UNSIGNED (type) && ! int_fits_type_p (TYPE_MAX_VALUE (type), totype)) type = c_common_type_for_size (precision, 1); else *************** type_promotes_to (tree type) *** 1134,1140 **** else if (c_promoting_integer_type_p (type)) { /* Retain unsignedness if really not getting bigger. */ ! if (TREE_UNSIGNED (type) && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) type = unsigned_type_node; else --- 1171,1177 ---- else if (c_promoting_integer_type_p (type)) { /* Retain unsignedness if really not getting bigger. */ ! if (TYPE_UNSIGNED (type) && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) type = unsigned_type_node; else diff -Nrcpad gcc-3.4.3/gcc/cp/cxx-pretty-print.c gcc-4.0.0/gcc/cp/cxx-pretty-print.c *** gcc-3.4.3/gcc/cp/cxx-pretty-print.c Wed Jul 28 14:55:06 2004 --- gcc-4.0.0/gcc/cp/cxx-pretty-print.c Tue Feb 8 14:46:52 2005 *************** *** 1,5 **** /* Implementation of subroutines for the GNU C++ pretty-printer. ! Copyright (C) 2003 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. --- 1,5 ---- /* Implementation of subroutines for the GNU C++ pretty-printer. ! Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. *************** static void pp_cxx_ptr_operator (cxx_pre *** 39,55 **** static void pp_cxx_type_id (cxx_pretty_printer *, tree); static void pp_cxx_direct_abstract_declarator (cxx_pretty_printer *, tree); static void pp_cxx_declarator (cxx_pretty_printer *, tree); static void pp_cxx_abstract_declarator (cxx_pretty_printer *, tree); static void pp_cxx_template_parameter (cxx_pretty_printer *, tree); - #define pp_cxx_whitespace(PP) pp_c_whitespace (pp_c_base (PP)) - #define pp_cxx_left_paren(PP) pp_c_left_paren (pp_c_base (PP)) - #define pp_cxx_right_paren(PP) pp_c_right_paren (pp_c_base (PP)) - #define pp_cxx_left_brace(PP) pp_c_left_brace (pp_c_base (PP)) - #define pp_cxx_right_brace(PP) pp_c_right_brace (pp_c_base (PP)) - #define pp_cxx_dot(PP) pp_c_dot (pp_c_base (PP)) - #define pp_cxx_arrow(PP) pp_c_arrow (pp_c_base (PP)) - #define pp_cxx_semicolon(PP) pp_c_semicolon (pp_c_base (PP)) static inline void pp_cxx_nonconsecutive_character (cxx_pretty_printer *pp, int c) --- 39,49 ---- static void pp_cxx_type_id (cxx_pretty_printer *, tree); static void pp_cxx_direct_abstract_declarator (cxx_pretty_printer *, tree); static void pp_cxx_declarator (cxx_pretty_printer *, tree); + static void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *, tree); static void pp_cxx_abstract_declarator (cxx_pretty_printer *, tree); + static void pp_cxx_statement (cxx_pretty_printer *, tree); static void pp_cxx_template_parameter (cxx_pretty_printer *, tree); static inline void pp_cxx_nonconsecutive_character (cxx_pretty_printer *pp, int c) *************** pp_cxx_nonconsecutive_character (cxx_pre *** 62,77 **** pp_base (pp)->padding = pp_none; } - #define pp_cxx_begin_template_argument_list(PP) \ - pp_cxx_nonconsecutive_character (PP, '<') - #define pp_cxx_end_template_argument_list(PP) \ - pp_cxx_nonconsecutive_character (PP, '>') - - #define pp_cxx_identifier(PP, ID) pp_c_identifier (pp_c_base (PP), ID) - #define pp_cxx_tree_identifier(PP, T) pp_c_tree_identifier (pp_c_base (PP), T) - - #define pp_cxx_cv_qualifier_seq(PP, T) \ - pp_c_type_qualifier_list (pp_c_base (PP), T) #define pp_cxx_storage_class_specifier(PP, T) \ pp_c_storage_class_specifier (pp_c_base (PP), T) #define pp_cxx_expression_list(PP, T) \ --- 56,61 ---- *************** pp_cxx_nonconsecutive_character (cxx_pre *** 83,95 **** #define pp_cxx_call_argument_list(PP, T) \ pp_c_call_argument_list (pp_c_base (PP), T) ! static void pp_cxx_colon_colon (cxx_pretty_printer *pp) { pp_colon_colon (pp); pp_base (pp)->padding = pp_none; } /* Expressions. */ --- 67,97 ---- #define pp_cxx_call_argument_list(PP, T) \ pp_c_call_argument_list (pp_c_base (PP), T) ! void pp_cxx_colon_colon (cxx_pretty_printer *pp) { pp_colon_colon (pp); pp_base (pp)->padding = pp_none; } + void + pp_cxx_begin_template_argument_list (cxx_pretty_printer *pp) + { + pp_cxx_nonconsecutive_character (pp, '<'); + } + + void + pp_cxx_end_template_argument_list (cxx_pretty_printer *pp) + { + pp_cxx_nonconsecutive_character (pp, '>'); + } + + void + pp_cxx_separate_with (cxx_pretty_printer *pp, int c) + { + pp_separate_with (pp, c); + pp_base (pp)->padding = pp_none; + } /* Expressions. */ *************** is_destructor_name (tree name) *** 109,114 **** --- 111,117 ---- conversion-declarator: ptr-operator conversion-declarator(opt) */ + static inline void pp_cxx_conversion_function_id (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_template_id (cxx_pretty_printer * *** 131,136 **** --- 134,140 ---- conversion-function-id ~ class-name template-id */ + static void pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_unqualified_id (cxx_pretty_printe *** 157,163 **** case IDENTIFIER_NODE: if (t == NULL) ! pp_cxx_identifier (pp, ""); else if (IDENTIFIER_TYPENAME_P (t)) pp_cxx_conversion_function_id (pp, t); else --- 161,167 ---- case IDENTIFIER_NODE: if (t == NULL) ! pp_cxx_identifier (pp, ""); else if (IDENTIFIER_TYPENAME_P (t)) pp_cxx_conversion_function_id (pp, t); else *************** pp_cxx_unqualified_id (cxx_pretty_printe *** 188,194 **** break; case TEMPLATE_TYPE_PARM: ! t = TYPE_FIELDS (t); case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t)); break; --- 192,204 ---- break; case TEMPLATE_TYPE_PARM: ! case TEMPLATE_TEMPLATE_PARM: ! if (TYPE_IDENTIFIER (t)) ! pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t)); ! else ! pp_cxx_canonical_template_parameter (pp, t); ! break; ! case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t)); break; *************** pp_cxx_unqualified_id (cxx_pretty_printe *** 199,204 **** --- 209,219 ---- } } + /* Pretty-print out the token sequence ":: template" in template codes + where it is needed to "inline declare" the (following) member as + a template. This situation arises when SCOPE of T is dependent + on template parameters. */ + static inline void pp_cxx_template_keyword_if_needed (cxx_pretty_printer *pp, tree scope, tree t) { *************** pp_cxx_template_keyword_if_needed (cxx_p *** 210,215 **** --- 225,231 ---- /* nested-name-specifier: class-or-namespace-name :: nested-name-specifier(opt) class-or-namespace-name :: template nested-name-specifier */ + static void pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_nested_name_specifier (cxx_pretty *** 225,240 **** --- 241,266 ---- /* qualified-id: nested-name-specifier template(opt) unqualified-id */ + static void pp_cxx_qualified_id (cxx_pretty_printer *pp, tree t) { switch (TREE_CODE (t)) { + /* A pointer-to-member is always qualified. */ case PTRMEM_CST: pp_cxx_nested_name_specifier (pp, PTRMEM_CST_CLASS (t)); pp_cxx_unqualified_id (pp, PTRMEM_CST_MEMBER (t)); break; + /* In Standard C++, functions cannot possibly be used as + nested-name-specifiers. However, there are situations where + is "makes sense" to output the surrounding function name for the + purpose of emphasizing on the scope kind. Just printing the + function name might not be sufficient as it may be overloaded; so, + we decorate the function with its signature too. + FIXME: This is probably the wrong pretty-printing for conversion + functions and some function templates. */ case OVERLOAD: t = OVL_CURRENT (t); case FUNCTION_DECL: *************** pp_cxx_qualified_id (cxx_pretty_printer *** 242,247 **** --- 268,274 ---- pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t)); pp_cxx_unqualified_id (pp, DECL_CONSTRUCTOR_P (t) ? DECL_CONTEXT (t) : t); + pp_cxx_parameter_declaration_clause (pp, TREE_TYPE (t)); break; case OFFSET_REF: *************** pp_cxx_qualified_id (cxx_pretty_printer *** 267,272 **** --- 294,300 ---- /* id-expression: unqualified-id qualified-id */ + static inline void pp_cxx_id_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_id_expression (cxx_pretty_printer *** 286,291 **** --- 314,320 ---- :: qualifier-id ( expression ) id-expression */ + static void pp_cxx_primary_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_primary_expression (cxx_pretty_pr *** 311,316 **** --- 340,346 ---- case RESULT_DECL: case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, t); break; *************** pp_cxx_postfix_expression (cxx_pretty_pr *** 397,403 **** } if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)) { ! pp_separate_with (pp, ','); pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2)); } break; --- 427,433 ---- } if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)) { ! pp_cxx_separate_with (pp, ','); pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2)); } break; *************** pp_cxx_postfix_expression (cxx_pretty_pr *** 419,431 **** case REINTERPRET_CAST_EXPR: case CONST_CAST_EXPR: if (code == DYNAMIC_CAST_EXPR) ! pp_identifier (pp, "dynamic_cast"); else if (code == STATIC_CAST_EXPR) ! pp_identifier (pp, "static_cast"); else if (code == REINTERPRET_CAST_EXPR) ! pp_identifier (pp, "reinterpret_cast"); else ! pp_identifier (pp, "const_cast"); pp_cxx_begin_template_argument_list (pp); pp_cxx_type_id (pp, TREE_TYPE (t)); pp_cxx_end_template_argument_list (pp); --- 449,461 ---- case REINTERPRET_CAST_EXPR: case CONST_CAST_EXPR: if (code == DYNAMIC_CAST_EXPR) ! pp_cxx_identifier (pp, "dynamic_cast"); else if (code == STATIC_CAST_EXPR) ! pp_cxx_identifier (pp, "static_cast"); else if (code == REINTERPRET_CAST_EXPR) ! pp_cxx_identifier (pp, "reinterpret_cast"); else ! pp_cxx_identifier (pp, "const_cast"); pp_cxx_begin_template_argument_list (pp); pp_cxx_type_id (pp, TREE_TYPE (t)); pp_cxx_end_template_argument_list (pp); *************** pp_cxx_postfix_expression (cxx_pretty_pr *** 486,491 **** --- 516,522 ---- new-initializer: ( expression-list(opt) ) */ + static void pp_cxx_new_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_new_expression (cxx_pretty_printe *** 526,531 **** --- 557,563 ---- /* delete-expression: ::(opt) delete cast-expression ::(opt) delete [ ] cast-expression */ + static void pp_cxx_delete_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_delete_expression (cxx_pretty_pri *** 566,571 **** --- 598,604 ---- GNU extensions: __alignof__ unary-expression __alignof__ ( type-id ) */ + static void pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_unary_expression (cxx_pretty_prin *** 591,596 **** --- 624,630 ---- /* cast-expression: unary-expression ( type-id ) cast-expression */ + static void pp_cxx_cast_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_cast_expression (cxx_pretty_print *** 611,616 **** --- 645,651 ---- cast-expression pm-expression .* cast-expression pm-expression ->* cast-expression */ + static void pp_cxx_pm_expression (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_pm_expression (cxx_pretty_printer *** 644,649 **** --- 679,685 ---- multiplicative-expression * pm-expression multiplicative-expression / pm-expression multiplicative-expression % pm-expression */ + static void pp_cxx_multiplicative_expression (cxx_pretty_printer *pp, tree e) { *************** pp_cxx_multiplicative_expression (cxx_pr *** 674,679 **** --- 710,716 ---- /* conditional-expression: logical-or-expression logical-or-expression ? expression : assignment-expression */ + static void pp_cxx_conditional_expression (cxx_pretty_printer *pp, tree e) { *************** pp_cxx_conditional_expression (cxx_prett *** 691,696 **** --- 728,735 ---- pp_c_logical_or_expression (pp_c_base (pp), e); } + /* Pretty-print a compound assignment operator token as indicated by T. */ + static void pp_cxx_assignment_operator (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_assignment_operator (cxx_pretty_p *** 737,742 **** --- 776,782 ---- assignment-operator: one of = *= /= %= += -= >>= <<= &= ^= |= */ + static void pp_cxx_assignment_expression (cxx_pretty_printer *pp, tree e) { *************** pp_cxx_expression (cxx_pretty_printer *p *** 803,808 **** --- 843,849 ---- case TEMPLATE_DECL: case TEMPLATE_TYPE_PARM: case TEMPLATE_PARM_INDEX: + case TEMPLATE_TEMPLATE_PARM: pp_cxx_primary_expression (pp, t); break; *************** pp_cxx_expression (cxx_pretty_printer *p *** 858,863 **** --- 899,909 ---- pp_cxx_assignment_expression (pp, t); break; + case NON_DEPENDENT_EXPR: + case MUST_NOT_THROW_EXPR: + pp_cxx_expression (pp, t); + break; + default: pp_c_expression (pp_c_base (pp), t); break; *************** pp_cxx_expression (cxx_pretty_printer *p *** 871,876 **** --- 917,923 ---- inline virtual explicit */ + static void pp_cxx_function_specifier (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_function_specifier (cxx_pretty_pr *** 898,903 **** --- 945,951 ---- function-specifier friend typedef */ + static void pp_cxx_decl_specifier_seq (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_decl_specifier_seq (cxx_pretty_pr *** 954,959 **** --- 1002,1008 ---- float double void */ + static void pp_cxx_simple_type_specifier (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_simple_type_specifier (cxx_pretty *** 966,971 **** --- 1015,1021 ---- break; case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, t); break; *************** pp_cxx_type_specifier_seq (cxx_pretty_pr *** 999,1007 **** { case TEMPLATE_DECL: case TEMPLATE_TYPE_PARM: case TYPE_DECL: case BOUND_TEMPLATE_TEMPLATE_PARM: ! pp_c_type_qualifier_list (pp_c_base (pp), t); pp_cxx_simple_type_specifier (pp, t); break; --- 1049,1058 ---- { case TEMPLATE_DECL: case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: case TYPE_DECL: case BOUND_TEMPLATE_TEMPLATE_PARM: ! pp_cxx_cv_qualifier_seq (pp, t); pp_cxx_simple_type_specifier (pp, t); break; *************** pp_cxx_ptr_operator (cxx_pretty_printer *** 1054,1059 **** --- 1105,1112 ---- case OFFSET_TYPE: if (TYPE_PTR_TO_MEMBER_P (t)) { + if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + pp_cxx_left_paren (pp); pp_cxx_nested_name_specifier (pp, TYPE_PTRMEM_CLASS_TYPE (t)); pp_star (pp); pp_cxx_cv_qualifier_seq (pp, t); *************** pp_cxx_implicit_parameter_type (tree mf) *** 1079,1084 **** --- 1132,1138 ---- decl-specifier-seq declarator = assignment-expression decl-specifier-seq abstract-declarator(opt) decl-specifier-seq abstract-declarator(opt) assignment-expression */ + static inline void pp_cxx_parameter_declaration (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_parameter_declaration (cxx_pretty *** 1096,1106 **** parameter-declaration-list: parameter-declaration parameter-declaration-list , parameter-declaration */ static void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t) { tree args = TYPE_P (t) ? NULL : FUNCTION_FIRST_USER_PARM (t); ! tree types = TYPE_P (t) ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t); const bool abstract = args == NULL || pp_c_base (pp)->flags & pp_c_flag_abstract; bool first = true; --- 1150,1162 ---- parameter-declaration-list: parameter-declaration parameter-declaration-list , parameter-declaration */ + static void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t) { tree args = TYPE_P (t) ? NULL : FUNCTION_FIRST_USER_PARM (t); ! tree types = ! TYPE_P (t) ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t); const bool abstract = args == NULL || pp_c_base (pp)->flags & pp_c_flag_abstract; bool first = true; *************** pp_cxx_parameter_declaration_clause (cxx *** 1113,1119 **** for (; args; args = TREE_CHAIN (args), types = TREE_CHAIN (types)) { if (!first) ! pp_separate_with (pp, ','); first = false; pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args); if (!abstract && pp_c_base (pp)->flags & pp_cxx_flag_default_argument) --- 1169,1175 ---- for (; args; args = TREE_CHAIN (args), types = TREE_CHAIN (types)) { if (!first) ! pp_cxx_separate_with (pp, ','); first = false; pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args); if (!abstract && pp_c_base (pp)->flags & pp_cxx_flag_default_argument) *************** pp_cxx_parameter_declaration_clause (cxx *** 1133,1138 **** --- 1189,1195 ---- type-id-list type-id type-id-list , type-id */ + static void pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_exception_specification (cxx_pret *** 1146,1152 **** { pp_cxx_type_id (pp, TREE_VALUE (ex_spec)); if (TREE_CHAIN (ex_spec)) ! pp_separate_with (pp, ','); } pp_cxx_right_paren (pp); } --- 1203,1209 ---- { pp_cxx_type_id (pp, TREE_VALUE (ex_spec)); if (TREE_CHAIN (ex_spec)) ! pp_cxx_separate_with (pp, ','); } pp_cxx_right_paren (pp); } *************** pp_cxx_exception_specification (cxx_pret *** 1157,1162 **** --- 1214,1220 ---- exception-specification(opt) direct-declaration [ constant-expression(opt) ] ( declarator ) */ + static void pp_cxx_direct_declarator (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_direct_declarator (cxx_pretty_pri *** 1192,1197 **** --- 1250,1256 ---- case TEMPLATE_DECL: case TEMPLATE_TYPE_PARM: case TEMPLATE_PARM_INDEX: + case TEMPLATE_TEMPLATE_PARM: break; default: *************** pp_cxx_direct_declarator (cxx_pretty_pri *** 1203,1208 **** --- 1262,1268 ---- /* declarator: direct-declarator ptr-operator declarator */ + static void pp_cxx_declarator (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_declarator (cxx_pretty_printer *p *** 1222,1227 **** --- 1282,1288 ---- mem-initializer-id: ::(opt) nested-name-specifier(opt) class-name identifier */ + static void pp_cxx_ctor_initializer (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_ctor_initializer (cxx_pretty_prin *** 1234,1240 **** pp_cxx_primary_expression (pp, TREE_PURPOSE (t)); pp_cxx_call_argument_list (pp, TREE_VALUE (t)); if (TREE_CHAIN (t)) ! pp_separate_with (pp, ','); } } --- 1295,1301 ---- pp_cxx_primary_expression (pp, TREE_PURPOSE (t)); pp_cxx_call_argument_list (pp, TREE_VALUE (t)); if (TREE_CHAIN (t)) ! pp_cxx_separate_with (pp, ','); } } *************** pp_cxx_ctor_initializer (cxx_pretty_prin *** 1242,1248 **** decl-specifier-seq(opt) declarator ctor-initializer(opt) function-body decl-specifier-seq(opt) declarator function-try-block */ ! void pp_cxx_function_definition (cxx_pretty_printer *pp, tree t) { tree saved_scope = pp->enclosing_scope; --- 1303,1309 ---- decl-specifier-seq(opt) declarator ctor-initializer(opt) function-body decl-specifier-seq(opt) declarator function-try-block */ ! static void pp_cxx_function_definition (cxx_pretty_printer *pp, tree t) { tree saved_scope = pp->enclosing_scope; *************** pp_cxx_function_definition (cxx_pretty_p *** 1251,1267 **** pp_needs_newline (pp) = true; pp->enclosing_scope = DECL_CONTEXT (t); if (DECL_SAVED_TREE (t)) ! { ! tree body = DECL_SAVED_TREE (t); ! if (TREE_CODE (body) == COMPOUND_STMT ! && TREE_CODE (COMPOUND_BODY (body)) == CTOR_INITIALIZER) ! { ! body = COMPOUND_BODY (body); ! pp_cxx_ctor_initializer (pp, body); ! body = TREE_CHAIN (body); ! } ! pp_cxx_statement (pp, body); ! } else { pp_cxx_semicolon (pp); --- 1312,1318 ---- pp_needs_newline (pp) = true; pp->enclosing_scope = DECL_CONTEXT (t); if (DECL_SAVED_TREE (t)) ! pp_cxx_statement (pp, DECL_SAVED_TREE (t)); else { pp_cxx_semicolon (pp); *************** pp_cxx_function_definition (cxx_pretty_p *** 1274,1279 **** --- 1325,1331 ---- /* abstract-declarator: ptr-operator abstract-declarator(opt) direct-abstract-declarator */ + static void pp_cxx_abstract_declarator (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_abstract_declarator (cxx_pretty_p *** 1294,1299 **** --- 1346,1352 ---- cv-qualifier-seq(opt) exception-specification(opt) direct-abstract-declarator(opt) [ constant-expression(opt) ] ( abstract-declarator ) */ + static void pp_cxx_direct_abstract_declarator (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_direct_abstract_declarator (cxx_p *** 1336,1341 **** --- 1389,1395 ---- /* type-id: type-specifier-seq abstract-declarator(opt) */ + static void pp_cxx_type_id (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_type_id (cxx_pretty_printer *pp, *** 1357,1365 **** case TEMPLATE_DECL: case TYPEOF_TYPE: case TEMPLATE_ID_EXPR: - /* FIXME: Should be pp_cxx_type_specifier_seq. */ pp_cxx_type_specifier_seq (pp, t); - pp_cxx_declarator (pp, t); break; default: --- 1411,1417 ---- *************** pp_cxx_type_id (cxx_pretty_printer *pp, *** 1378,1383 **** --- 1430,1436 ---- assignment-expression type-id template-name */ + static void pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_template_argument_list (cxx_prett *** 1388,1396 **** { tree arg = TREE_VEC_ELT (t, i); if (i != 0) ! pp_separate_with (pp, ','); if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL ! && TYPE_P (DECL_TEMPLATE_RESULT (arg)))) pp_cxx_type_id (pp, arg); else pp_cxx_expression (pp, arg); --- 1441,1449 ---- { tree arg = TREE_VEC_ELT (t, i); if (i != 0) ! pp_cxx_separate_with (pp, ','); if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL ! && TYPE_P (DECL_TEMPLATE_RESULT (arg)))) pp_cxx_type_id (pp, arg); else pp_cxx_expression (pp, arg); *************** pp_cxx_template_argument_list (cxx_prett *** 1401,1407 **** static void pp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t) { ! t = DECL_STMT_DECL (t); pp_cxx_type_specifier_seq (pp, t); if (TYPE_P (t)) pp_cxx_abstract_declarator (pp, t); --- 1454,1460 ---- static void pp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t) { ! t = DECL_EXPR_DECL (t); pp_cxx_type_specifier_seq (pp, t); if (TYPE_P (t)) pp_cxx_abstract_declarator (pp, t); *************** pp_cxx_exception_declaration (cxx_pretty *** 1411,1421 **** /* Statements. */ ! void pp_cxx_statement (cxx_pretty_printer *pp, tree t) { switch (TREE_CODE (t)) { case USING_STMT: pp_cxx_identifier (pp, "using"); pp_cxx_identifier (pp, "namespace"); --- 1464,1478 ---- /* Statements. */ ! static void pp_cxx_statement (cxx_pretty_printer *pp, tree t) { switch (TREE_CODE (t)) { + case CTOR_INITIALIZER: + pp_cxx_ctor_initializer (pp, t); + break; + case USING_STMT: pp_cxx_identifier (pp, "using"); pp_cxx_identifier (pp, "namespace"); *************** pp_cxx_statement (cxx_pretty_printer *pp *** 1468,1473 **** --- 1525,1567 ---- pp_needs_newline (pp) = true; break; + /* selection-statement: + if ( expression ) statement + if ( expression ) statement else statement */ + case IF_STMT: + pp_cxx_identifier (pp, "if"); + pp_cxx_whitespace (pp); + pp_cxx_left_paren (pp); + pp_cxx_expression (pp, IF_COND (t)); + pp_cxx_right_paren (pp); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, THEN_CLAUSE (t)); + pp_newline_and_indent (pp, -2); + if (ELSE_CLAUSE (t)) + { + tree else_clause = ELSE_CLAUSE (t); + pp_cxx_identifier (pp, "else"); + if (TREE_CODE (else_clause) == IF_STMT) + pp_cxx_whitespace (pp); + else + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, else_clause); + if (TREE_CODE (else_clause) != IF_STMT) + pp_newline_and_indent (pp, -2); + } + break; + + case CLEANUP_STMT: + pp_cxx_identifier (pp, "try"); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, CLEANUP_BODY (t)); + pp_newline_and_indent (pp, -2); + pp_cxx_identifier (pp, CLEANUP_EH_ONLY (t) ? "catch" : "finally"); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, CLEANUP_EXPR (t)); + pp_newline_and_indent (pp, -2); + break; + default: pp_c_statement (pp_c_base (pp), t); break; *************** pp_cxx_namespace_alias_definition (cxx_p *** 1515,1520 **** --- 1609,1615 ---- /* simple-declaration: decl-specifier-seq(opt) init-declarator-list(opt) */ + static void pp_cxx_simple_declaration (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_template_parameter_list (cxx_pret *** 1537,1543 **** for (i = 0; i < n; ++i) { if (i) ! pp_separate_with (pp, ','); pp_cxx_template_parameter (pp, TREE_VEC_ELT (t, i)); } } --- 1632,1638 ---- for (i = 0; i < n; ++i) { if (i) ! pp_cxx_separate_with (pp, ','); pp_cxx_template_parameter (pp, TREE_VEC_ELT (t, i)); } } *************** pp_cxx_template_parameter_list (cxx_pret *** 1554,1559 **** --- 1649,1655 ---- template < template-parameter-list > class identifier(opt) template < template-parameter-list > class identifier(opt) = template-name */ + static void pp_cxx_template_parameter (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_canonical_template_parameter (cxx *** 1604,1609 **** --- 1700,1706 ---- /* template-declaration: export(opt) template < template-parameter-list > declaration */ + static void pp_cxx_template_declaration (cxx_pretty_printer *pp, tree t) { *************** pp_cxx_declaration (cxx_pretty_printer * *** 1708,1713 **** --- 1805,1812 ---- typedef c_pretty_print_fn pp_fun; + /* Initialization of a C++ pretty-printer object. */ + void pp_cxx_pretty_printer_init (cxx_pretty_printer *pp) { diff -Nrcpad gcc-3.4.3/gcc/cp/cxx-pretty-print.h gcc-4.0.0/gcc/cp/cxx-pretty-print.h *** gcc-3.4.3/gcc/cp/cxx-pretty-print.h Tue Oct 7 07:07:02 2003 --- gcc-4.0.0/gcc/cp/cxx-pretty-print.h Tue Feb 8 14:46:52 2005 *************** *** 1,5 **** /* Interface for the GNU C++ pretty-printer. ! Copyright (C) 2003 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. --- 1,5 ---- /* Interface for the GNU C++ pretty-printer. ! Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. *************** typedef struct *** 41,52 **** tree enclosing_scope; } cxx_pretty_printer; void pp_cxx_pretty_printer_init (cxx_pretty_printer *); void pp_cxx_declaration (cxx_pretty_printer *, tree); - void pp_cxx_function_definition (cxx_pretty_printer *, tree); void pp_cxx_canonical_template_parameter (cxx_pretty_printer *, tree); - void pp_cxx_statement (cxx_pretty_printer *, tree); #endif /* GCC_CXX_PRETTY_PRINT_H */ --- 41,75 ---- tree enclosing_scope; } cxx_pretty_printer; + #define pp_cxx_cv_qualifier_seq(PP, T) \ + pp_c_type_qualifier_list (pp_c_base (PP), T) + + #define pp_cxx_whitespace(PP) pp_c_whitespace (pp_c_base (PP)) + #define pp_cxx_left_paren(PP) pp_c_left_paren (pp_c_base (PP)) + #define pp_cxx_right_paren(PP) pp_c_right_paren (pp_c_base (PP)) + #define pp_cxx_left_brace(PP) pp_c_left_brace (pp_c_base (PP)) + #define pp_cxx_right_brace(PP) pp_c_right_brace (pp_c_base (PP)) + #define pp_cxx_left_bracket(PP) pp_c_left_bracket (pp_c_base (PP)) + #define pp_cxx_right_bracket(PP) pp_c_right_bracket (pp_c_base (PP)) + #define pp_cxx_dot(PP) pp_c_dot (pp_c_base (PP)) + #define pp_cxx_ampersand(PP) pp_c_ampersand (pp_c_base (PP)) + #define pp_cxx_star(PP) pp_c_star (pp_c_base (PP)) + #define pp_cxx_arrow(PP) pp_c_arrow (pp_c_base (PP)) + #define pp_cxx_semicolon(PP) pp_c_semicolon (pp_c_base (PP)) + #define pp_cxx_complement(PP) pp_c_complement (pp_c_base (PP)) + + #define pp_cxx_identifier(PP, I) pp_c_identifier (pp_c_base (PP), I) + #define pp_cxx_tree_identifier(PP, T) \ + pp_c_tree_identifier (pp_c_base (PP), T) + void pp_cxx_pretty_printer_init (cxx_pretty_printer *); + void pp_cxx_begin_template_argument_list (cxx_pretty_printer *); + void pp_cxx_end_template_argument_list (cxx_pretty_printer *); + void pp_cxx_colon_colon (cxx_pretty_printer *); + void pp_cxx_separate_with (cxx_pretty_printer *, int); void pp_cxx_declaration (cxx_pretty_printer *, tree); void pp_cxx_canonical_template_parameter (cxx_pretty_printer *, tree); #endif /* GCC_CXX_PRETTY_PRINT_H */ diff -Nrcpad gcc-3.4.3/gcc/cp/decl.c gcc-4.0.0/gcc/cp/decl.c *** gcc-3.4.3/gcc/cp/decl.c Fri Oct 15 04:23:46 2004 --- gcc-4.0.0/gcc/cp/decl.c Wed Apr 6 17:21:47 2005 *************** *** 1,6 **** /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, ! 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, ! 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 39,45 **** #include "cp-tree.h" #include "tree-inline.h" #include "decl.h" - #include "lex.h" #include "output.h" #include "except.h" #include "toplev.h" --- 39,44 ---- *************** Boston, MA 02111-1307, USA. */ *** 51,58 **** #include "diagnostic.h" #include "debug.h" #include "timevar.h" ! static tree grokparms (tree, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); --- 50,58 ---- #include "diagnostic.h" #include "debug.h" #include "timevar.h" + #include "tree-flow.h" ! static tree grokparms (cp_parameter_declarator *, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); *************** static int ambi_op_p (enum tree_code); *** 61,73 **** static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, tree *); ! static tree grokfndecl (tree, tree, tree, tree, tree, int, ! enum overload_flags, tree, ! tree, int, int, int, int, int, int, tree); ! static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree); static void record_unknown_type (tree, const char *); ! static tree builtin_function_1 (const char *, tree, tree, int, ! enum built_in_class, const char *, tree); static tree build_library_fn_1 (tree, enum tree_code, tree); static int member_function_or_else (tree, tree, enum overload_flags); --- 61,72 ---- static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, tree *); ! static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, ! int, int, tree); static void record_unknown_type (tree, const char *); ! static tree builtin_function_1 (const char *, tree, tree, ! enum built_in_function code, ! enum built_in_class cl, const char *, tree); static tree build_library_fn_1 (tree, enum tree_code, tree); static int member_function_or_else (tree, tree, enum overload_flags); *************** static hashval_t typename_hash (const vo *** 78,87 **** static int typename_compare (const void *, const void *); static tree local_variable_p_walkfn (tree *, int *, void *); static tree record_builtin_java_type (const char *, int); ! static const char *tag_name (enum tag_types code); static int walk_namespaces_r (tree, walk_namespaces_fn, void *); - static int walk_globals_r (tree, void*); - static int walk_vtables_r (tree, void*); static tree make_label_decl (tree, int); static void use_label (tree); static void check_previous_goto_1 (tree, struct cp_binding_level *, tree, --- 77,85 ---- static int typename_compare (const void *, const void *); static tree local_variable_p_walkfn (tree *, int *, void *); static tree record_builtin_java_type (const char *, int); ! static const char *tag_name (enum tag_types); ! static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool); static int walk_namespaces_r (tree, walk_namespaces_fn, void *); static tree make_label_decl (tree, int); static void use_label (tree); static void check_previous_goto_1 (tree, struct cp_binding_level *, tree, *************** static tree check_initializer (tree, tre *** 98,104 **** static void make_rtl_for_nonlocal_decl (tree, tree, const char *); static void save_function_data (tree); static void check_function_type (tree, tree); - static void begin_constructor_body (void); static void finish_constructor_body (void); static void begin_destructor_body (void); static void finish_destructor_body (void); --- 96,101 ---- *************** static tree start_cleanup_fn (void); *** 109,126 **** static void end_cleanup_fn (void); static tree cp_make_fname_decl (tree, int); static void initialize_predefined_identifiers (void); ! static tree check_special_function_return_type (special_function_kind, tree, tree); static tree push_cp_library_fn (enum tree_code, tree); static tree build_cp_library_fn (tree, enum tree_code, tree); static void store_parm_decls (tree); - static int cp_missing_noreturn_ok_p (tree); 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 *); - static bool reshape_init_array (tree, tree, tree *, tree); - static tree build_typename_type (tree, tree, tree); /* Erroneous argument lists can use this *IFF* they do not modify it. */ tree error_mark_list; --- 106,120 ---- static void end_cleanup_fn (void); static tree cp_make_fname_decl (tree, int); static void initialize_predefined_identifiers (void); ! static tree check_special_function_return_type (special_function_kind, tree, tree); static tree push_cp_library_fn (enum tree_code, tree); static tree build_cp_library_fn (tree, enum tree_code, tree); static void store_parm_decls (tree); 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; *************** int function_depth; *** 235,241 **** with __attribute__((deprecated)). An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ ! enum deprecated_states { DEPRECATED_NORMAL, DEPRECATED_SUPPRESS --- 229,235 ---- with __attribute__((deprecated)). An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ ! enum deprecated_states { DEPRECATED_NORMAL, DEPRECATED_SUPPRESS *************** enum deprecated_states { *** 243,253 **** static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; - /* Set by add_implicitly_declared_members() to keep those members from - 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; --- 237,242 ---- *************** current_tmpl_spec_kind (int n_class_scop *** 272,279 **** struct cp_binding_level *b; /* Scan through the template parameter scopes. */ ! for (b = current_binding_level; ! b->kind == sk_template_parms; b = b->level_chain) { /* If we see a specialization scope inside a parameter scope, --- 261,268 ---- struct cp_binding_level *b; /* Scan through the template parameter scopes. */ ! for (b = current_binding_level; ! b->kind == sk_template_parms; b = b->level_chain) { /* If we see a specialization scope inside a parameter scope, *************** pop_label (tree label, tree old_value) *** 369,382 **** { location_t location; ! cp_error_at ("label `%D' used but not defined", label); location.file = input_filename; location.line = 0; /* Avoid crashing later. */ define_label (location, DECL_NAME (label)); } else if (warn_unused_label && !TREE_USED (label)) ! cp_warning_at ("label `%D' defined but not used", label); } SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value); --- 358,375 ---- { location_t location; ! cp_error_at ("label %qD used but not defined", label); ! #ifdef USE_MAPPED_LOCATION ! location = input_location; /* FIXME want (input_filename, (line)0) */ ! #else location.file = input_filename; location.line = 0; + #endif /* Avoid crashing later. */ define_label (location, DECL_NAME (label)); } else if (warn_unused_label && !TREE_USED (label)) ! cp_warning_at ("label %qD defined but not used", label); } SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value); *************** pop_labels (tree block) *** 405,410 **** --- 398,440 ---- named_labels = NULL; } + /* The following two routines are used to interface to Objective-C++. + The binding level is purposely treated as an opaque type. */ + + void * + objc_get_current_scope (void) + { + return current_binding_level; + } + + /* The following routine is used by the NeXT-style SJLJ exceptions; + variables get marked 'volatile' so as to not be clobbered by + _setjmp()/_longjmp() calls. All variables in the current scope, + as well as parent scopes up to (but not including) ENCLOSING_BLK + shall be thusly marked. */ + + void + objc_mark_locals_volatile (void *enclosing_blk) + { + struct cp_binding_level *scope; + + for (scope = current_binding_level; + scope && scope != enclosing_blk && scope->kind == sk_block; + scope = scope->level_chain) + { + tree decl; + + for (decl = scope->names; decl; decl = TREE_CHAIN (decl)) + { + if (TREE_CODE (decl) == VAR_DECL) + { + DECL_REGISTER (decl) = 0; + TREE_THIS_VOLATILE (decl) = 1; + } + } + } + } + /* Exit a binding level. Pop the level off, and restore the state of the identifier-decl mappings that were in effect when this level was entered. *************** poplevel (int keep, int reverse, int fun *** 430,455 **** int tmp = functionbody; int real_functionbody; tree subblocks; ! tree block = NULL_TREE; tree decl; int leaving_for_scope; scope_kind kind; timevar_push (TV_NAME_LOOKUP); ! my_friendly_assert (current_binding_level->kind != sk_class, 19990916); real_functionbody = (current_binding_level->kind == sk_cleanup ? ((functionbody = 0), tmp) : functionbody); subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; ! my_friendly_assert (!current_binding_level->class_shadowed, ! 19990414); /* We used to use KEEP == 2 to indicate that the new block should go at the beginning of the list of blocks at this binding level, rather than the end. This hack is no longer used. */ ! my_friendly_assert (keep == 0 || keep == 1, 0); if (current_binding_level->keep) keep = 1; --- 460,488 ---- int tmp = functionbody; int real_functionbody; tree subblocks; ! tree block; tree decl; int leaving_for_scope; scope_kind kind; timevar_push (TV_NAME_LOOKUP); + restart: ! block = NULL_TREE; ! ! gcc_assert (current_binding_level->kind != sk_class); real_functionbody = (current_binding_level->kind == sk_cleanup ? ((functionbody = 0), tmp) : functionbody); subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; ! gcc_assert (!VEC_length(cp_class_binding, ! current_binding_level->class_shadowed)); /* We used to use KEEP == 2 to indicate that the new block should go at the beginning of the list of blocks at this binding level, rather than the end. This hack is no longer used. */ ! gcc_assert (keep == 0 || keep == 1); if (current_binding_level->keep) keep = 1; *************** poplevel (int keep, int reverse, int fun *** 500,535 **** else decls = current_binding_level->names; - /* Output any nested inline functions within this block - if they weren't already output. */ - for (decl = decls; decl; decl = TREE_CHAIN (decl)) - if (TREE_CODE (decl) == FUNCTION_DECL - && ! TREE_ASM_WRITTEN (decl) - && DECL_INITIAL (decl) != NULL_TREE - && TREE_ADDRESSABLE (decl) - && decl_function_context (decl) == current_function_decl) - { - /* If this decl was copied from a file-scope decl - on account of a block-scope extern decl, - propagate TREE_ADDRESSABLE to the file-scope decl. */ - if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE) - TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; - else - { - push_function_context (); - output_inline_function (decl); - pop_function_context (); - } - } - - /* When not in function-at-a-time mode, expand_end_bindings will - warn about unused variables. But, in function-at-a-time mode - expand_end_bindings is not passed the list of variables in the - current scope, and therefore no warning is emitted. So, we - explicitly warn here. */ - if (!processing_template_decl) - warn_about_unused_variables (getdecls ()); - /* If there were any declarations or structure tags in that level, or if this level is a function body, create a BLOCK to record them for the life of this function. */ --- 533,538 ---- *************** poplevel (int keep, int reverse, int fun *** 554,576 **** leaving_for_scope = current_binding_level->kind == sk_for && flag_new_for_scope == 1; /* Remove declarations for all the DECLs in this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { if (leaving_for_scope && TREE_CODE (link) == VAR_DECL && DECL_NAME (link)) { ! cxx_binding *outer_binding ! = IDENTIFIER_BINDING (DECL_NAME (link))->previous; tree ns_binding; ! if (!outer_binding) ! ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link)); else ns_binding = NULL_TREE; ! if (outer_binding ! && outer_binding->scope == current_binding_level->level_chain) /* We have something like: int i; --- 557,591 ---- leaving_for_scope = current_binding_level->kind == sk_for && flag_new_for_scope == 1; + /* Before we remove the declarations first check for unused variables. */ + if (warn_unused_variable + && !processing_template_decl) + for (decl = getdecls (); decl; decl = TREE_CHAIN (decl)) + if (TREE_CODE (decl) == VAR_DECL + && ! TREE_USED (decl) + && ! DECL_IN_SYSTEM_HEADER (decl) + && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)) + warning ("%Junused variable %qD", decl, decl); + /* Remove declarations for all the DECLs in this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { if (leaving_for_scope && TREE_CODE (link) == VAR_DECL && DECL_NAME (link)) { ! tree name = DECL_NAME (link); ! cxx_binding *ob; tree ns_binding; ! ob = outer_binding (name, ! IDENTIFIER_BINDING (name), ! /*class_p=*/true); ! if (!ob) ! ns_binding = IDENTIFIER_NAMESPACE_VALUE (name); else ns_binding = NULL_TREE; ! if (ob && ob->scope == current_binding_level->level_chain) /* We have something like: int i; *************** poplevel (int keep, int reverse, int fun *** 578,586 **** and we are leaving the `for' scope. There's no reason to keep the binding of the inner `i' in this case. */ ! pop_binding (DECL_NAME (link), link); ! else if ((outer_binding ! && (TREE_CODE (outer_binding->value) == TYPE_DECL)) || (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL)) /* Here, we have something like: --- 593,600 ---- and we are leaving the `for' scope. There's no reason to keep the binding of the inner `i' in this case. */ ! pop_binding (name, link); ! else if ((ob && (TREE_CODE (ob->value) == TYPE_DECL)) || (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL)) /* Here, we have something like: *************** poplevel (int keep, int reverse, int fun *** 592,598 **** We must pop the for-scope binding so we know what's a type and what isn't. */ ! pop_binding (DECL_NAME (link), link); else { /* Mark this VAR_DECL as dead so that we can tell we left it --- 606,612 ---- We must pop the for-scope binding so we know what's a type and what isn't. */ ! pop_binding (name, link); else { /* Mark this VAR_DECL as dead so that we can tell we left it *************** poplevel (int keep, int reverse, int fun *** 601,608 **** /* Keep track of what should have happened when we popped the binding. */ ! if (outer_binding && outer_binding->value) ! DECL_SHADOWED_FOR_VAR (link) = outer_binding->value; /* Add it to the list of dead variables in the next outermost binding to that we can remove these when we --- 615,622 ---- /* Keep track of what should have happened when we popped the binding. */ ! if (ob && ob->value) ! DECL_SHADOWED_FOR_VAR (link) = ob->value; /* Add it to the list of dead variables in the next outermost binding to that we can remove these when we *************** poplevel (int keep, int reverse, int fun *** 614,634 **** /* Although we don't pop the cxx_binding, we do clear its SCOPE since the scope is going away now. */ ! IDENTIFIER_BINDING (DECL_NAME (link))->scope = NULL; } } else { /* Remove the binding. */ decl = link; if (TREE_CODE (decl) == TREE_LIST) decl = TREE_VALUE (decl); ! if (DECL_P (decl)) ! pop_binding (DECL_NAME (decl), decl); ! else if (TREE_CODE (decl) == OVERLOAD) ! pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl); ! else ! abort (); } } --- 628,653 ---- /* Although we don't pop the cxx_binding, we do clear its SCOPE since the scope is going away now. */ ! IDENTIFIER_BINDING (name)->scope ! = current_binding_level->level_chain; } } else { + tree name; + /* Remove the binding. */ decl = link; + if (TREE_CODE (decl) == TREE_LIST) decl = TREE_VALUE (decl); ! name = decl; ! ! if (TREE_CODE (name) == OVERLOAD) ! name = OVL_FUNCTION (name); ! ! gcc_assert (DECL_P (name)); ! pop_binding (DECL_NAME (name), decl); } } *************** poplevel (int keep, int reverse, int fun *** 680,685 **** --- 699,715 ---- } kind = current_binding_level->kind; + if (kind == sk_cleanup) + { + tree stmt; + + /* If this is a temporary binding created for a cleanup, then we'll + have pushed a statement list level. Pop that, create a new + BIND_EXPR for the block, and insert it into the stream. */ + stmt = pop_stmt_list (current_binding_level->statement_list); + stmt = c_build_bind_expr (block, stmt); + add_stmt (stmt); + } leave_scope (); if (functionbody) *************** poplevel (int keep, int reverse, int fun *** 703,750 **** if (block) TREE_USED (block) = 1; ! /* Take care of compiler's internal binding structures. */ if (kind == sk_cleanup) ! { ! tree scope_stmts; ! ! scope_stmts ! = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1); ! if (block) ! { ! SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; ! SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; ! } ! ! block = poplevel (keep, reverse, functionbody); ! } POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block); } - /* Delete the node BLOCK from the current binding level. - This is used for the block inside a stmt expr ({...}) - so that the block can be reinserted where appropriate. */ - - void - delete_block (tree block) - { - tree t; - if (current_binding_level->blocks == block) - current_binding_level->blocks = TREE_CHAIN (block); - for (t = current_binding_level->blocks; t;) - { - if (TREE_CHAIN (t) == block) - TREE_CHAIN (t) = TREE_CHAIN (block); - else - t = TREE_CHAIN (t); - } - TREE_CHAIN (block) = NULL_TREE; - /* Clear TREE_USED which is always set by poplevel. - The flag is set again if insert_block is called. */ - TREE_USED (block) = 0; - } - /* Insert BLOCK at the end of the list of subblocks of the current binding level. This is used when a BIND_EXPR is expanded, to handle the BLOCK node inside the BIND_EXPR. */ --- 733,745 ---- if (block) TREE_USED (block) = 1; ! /* All temporary bindings created for cleanups are popped silently. */ if (kind == sk_cleanup) ! goto restart; POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block); } /* Insert BLOCK at the end of the list of subblocks of the current binding level. This is used when a BIND_EXPR is expanded, to handle the BLOCK node inside the BIND_EXPR. */ *************** insert_block (tree block) *** 757,830 **** = chainon (current_binding_level->blocks, block); } - /* Set the BLOCK node for the innermost scope - (the one we are currently in). */ - - void - set_block (tree block ATTRIBUTE_UNUSED ) - { - /* The RTL expansion machinery requires us to provide this callback, - but it is not applicable in function-at-a-time mode. */ - } - - /* Returns nonzero if T is a virtual function table. */ - - int - vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED ) - { - return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t)); - } - - /* Returns nonzero if T is a TYPE_DECL for a type with virtual - functions. */ - - int - vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED ) - { - return (TREE_CODE (t) == TYPE_DECL - && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE - && TYPE_POLYMORPHIC_P (TREE_TYPE (t))); - } - - 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 (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. */ - bool - walk_vtables (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. */ --- 752,757 ---- *************** static int *** 832,838 **** walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data) { int result = 0; ! tree current = NAMESPACE_LEVEL (namespace)->namespaces; result |= (*f) (namespace, data); --- 759,765 ---- walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data) { int result = 0; ! tree current = NAMESPACE_LEVEL (namespace)->namespaces; result |= (*f) (namespace, data); *************** walk_namespaces (walk_namespaces_fn f, v *** 851,903 **** return walk_namespaces_r (global_namespace, f, data); } - /* Walk the global 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_globals_r (tree namespace, void* data) - { - struct walk_globals_data* wgd = (struct walk_globals_data *) data; - walk_globals_pred p = wgd->p; - walk_globals_fn f = wgd->f; - void *d = wgd->data; - tree *t; - int result = 0; - - t = &NAMESPACE_LEVEL (namespace)->names; - - while (*t) - { - tree glbl = *t; - - if ((*p) (glbl, d)) - result |= (*f) (t, d); - - /* If F changed *T, then *T still points at the next item to - examine. */ - if (*t == glbl) - t = &TREE_CHAIN (*t); - } - - return result; - } - - /* Walk the global declarations. Whenever one is found for which P - returns true, call F with its address. If any call to F - returns true, return true. */ - - bool - walk_globals (walk_globals_pred p, walk_globals_fn f, void *data) - { - struct walk_globals_data wgd; - wgd.p = p; - wgd.f = f; - wgd.data = data; - - return walk_namespaces (walk_globals_r, &wgd); - } - /* Call wrapup_globals_declarations for the globals in NAMESPACE. If DATA is non-NULL, this is the last time we will call wrapup_global_declarations for this NAMESPACE. */ --- 778,783 ---- *************** decls_match (tree newdecl, tree olddecl) *** 1068,1073 **** --- 948,959 ---- } else { + /* Need to check scope for variable declaration (VAR_DECL). + For typedef (TYPE_DECL), scope is ignored. */ + if (TREE_CODE (newdecl) == VAR_DECL + && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)) + return 0; + if (TREE_TYPE (newdecl) == error_mark_node) types_match = TREE_TYPE (olddecl) == error_mark_node; else if (TREE_TYPE (olddecl) == NULL_TREE) *************** decls_match (tree newdecl, tree olddecl) *** 1095,1105 **** void warn_extern_redeclared_static (tree newdecl, tree olddecl) { - static const char *const explicit_extern_static_warning - = "`%D' was declared `extern' and later `static'"; - static const char *const implicit_extern_static_warning - = "`%D' was declared implicitly `extern' and later `static'"; - tree name; if (TREE_CODE (newdecl) == TYPE_DECL --- 981,986 ---- *************** warn_extern_redeclared_static (tree newd *** 1125,1134 **** return; name = DECL_ASSEMBLER_NAME (newdecl); ! pedwarn (IDENTIFIER_IMPLICIT_DECL (name) ! ? implicit_extern_static_warning ! : explicit_extern_static_warning, newdecl); ! cp_pedwarn_at ("previous declaration of `%D'", olddecl); } /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations. --- 1006,1013 ---- return; name = DECL_ASSEMBLER_NAME (newdecl); ! pedwarn ("%qD was declared % and later %", newdecl); ! cp_pedwarn_at ("previous declaration of %qD", olddecl); } /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations. *************** duplicate_decls (tree newdecl, tree oldd *** 1176,1192 **** && DECL_UNINLINABLE (olddecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) { ! warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl); ! warning ("%Jprevious declaration of '%D' with attribute noinline", olddecl, olddecl); } else if (DECL_DECLARED_INLINE_P (olddecl) && DECL_UNINLINABLE (newdecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) { ! warning ("%Jfunction '%D' redeclared with attribute noinline", newdecl, newdecl); ! warning ("%Jprevious declaration of '%D' was inline", olddecl, olddecl); } } --- 1055,1071 ---- && DECL_UNINLINABLE (olddecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) { ! warning ("%Jfunction %qD redeclared as inline", newdecl, newdecl); ! warning ("%Jprevious declaration of %qD with attribute noinline", olddecl, olddecl); } else if (DECL_DECLARED_INLINE_P (olddecl) && DECL_UNINLINABLE (newdecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) { ! warning ("%Jfunction %qD redeclared with attribute noinline", newdecl, newdecl); ! warning ("%Jprevious declaration of %qD was inline", olddecl, olddecl); } } *************** duplicate_decls (tree newdecl, tree oldd *** 1207,1228 **** if (! TREE_PUBLIC (newdecl)) { if (warn_shadow) ! warning ("shadowing %s function `%#D'", ! DECL_BUILT_IN (olddecl) ? "built-in" : "library", ! olddecl); /* Discard the old built-in function. */ return NULL_TREE; } /* If the built-in is not ansi, then programs can override it even globally without an error. */ else if (! DECL_BUILT_IN (olddecl)) ! warning ("library function `%#D' redeclared as non-function `%#D'", ! olddecl, newdecl); else { ! error ("declaration of `%#D'", newdecl); ! error ("conflicts with built-in declaration `%#D'", ! olddecl); } return NULL_TREE; } --- 1086,1107 ---- if (! TREE_PUBLIC (newdecl)) { if (warn_shadow) ! warning ("shadowing %s function %q#D", ! DECL_BUILT_IN (olddecl) ? "built-in" : "library", ! olddecl); /* Discard the old built-in function. */ return NULL_TREE; } /* If the built-in is not ansi, then programs can override it even globally without an error. */ else if (! DECL_BUILT_IN (olddecl)) ! warning ("library function %q#D redeclared as non-function %q#D", ! olddecl, newdecl); else { ! error ("declaration of %q#D", newdecl); ! error ("conflicts with built-in declaration %q#D", ! olddecl); } return NULL_TREE; } *************** duplicate_decls (tree newdecl, tree oldd *** 1230,1236 **** { /* Avoid warnings redeclaring anticipated built-ins. */ if (DECL_ANTICIPATED (olddecl)) ! ; /* Do nothing yet. */ else if ((DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), --- 1109,1148 ---- { /* Avoid warnings redeclaring anticipated built-ins. */ if (DECL_ANTICIPATED (olddecl)) ! { ! /* Deal with fileptr_type_node. FILE type is not known ! at the time we create the builtins. */ ! tree t1, t2; ! ! for (t1 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)), ! t2 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); ! t1 || t2; ! t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) ! if (!t1 || !t2) ! break; ! else if (TREE_VALUE (t2) == fileptr_type_node) ! { ! tree t = TREE_VALUE (t1); ! ! if (TREE_CODE (t) == POINTER_TYPE ! && TYPE_NAME (TREE_TYPE (t)) ! && DECL_NAME (TYPE_NAME (TREE_TYPE (t))) ! == get_identifier ("FILE") ! && compparms (TREE_CHAIN (t1), TREE_CHAIN (t2))) ! { ! tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); ! ! TYPE_ARG_TYPES (TREE_TYPE (olddecl)) ! = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); ! types_match = decls_match (newdecl, olddecl); ! if (types_match) ! return duplicate_decls (newdecl, olddecl); ! TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs; ! } ! } ! else if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2))) ! break; ! } else if ((DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), *************** duplicate_decls (tree newdecl, tree oldd *** 1240,1260 **** if (TREE_PUBLIC (newdecl)) { ! warning ("new declaration `%#D'", newdecl); ! warning ("ambiguates built-in declaration `%#D'", ! olddecl); } else if (warn_shadow) ! warning ("shadowing %s function `%#D'", ! DECL_BUILT_IN (olddecl) ? "built-in" : "library", ! olddecl); } else /* Discard the old built-in function. */ return NULL_TREE; /* 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 anticipated built-ins, for exception lists, etc... */ --- 1152,1172 ---- if (TREE_PUBLIC (newdecl)) { ! warning ("new declaration %q#D", newdecl); ! warning ("ambiguates built-in declaration %q#D", ! olddecl); } else if (warn_shadow) ! warning ("shadowing %s function %q#D", ! DECL_BUILT_IN (olddecl) ? "built-in" : "library", ! olddecl); } else /* Discard the old built-in function. */ return NULL_TREE; /* Replace the old RTL to avoid problems with inlining. */ ! COPY_DECL_RTL (newdecl, olddecl); } /* Even if the types match, prefer the new declarations type for anticipated built-ins, for exception lists, etc... */ *************** duplicate_decls (tree newdecl, tree oldd *** 1283,1289 **** that all remnants of the builtin-ness of this function will be banished. */ SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); ! SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); } } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) --- 1195,1201 ---- that all remnants of the builtin-ness of this function will be banished. */ SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); ! COPY_DECL_RTL (newdecl, olddecl); } } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) *************** duplicate_decls (tree newdecl, tree oldd *** 1312,1326 **** && DECL_FUNCTION_TEMPLATE_P (newdecl))) return NULL_TREE; ! error ("`%#D' redeclared as different kind of symbol", newdecl); if (TREE_CODE (olddecl) == TREE_LIST) olddecl = TREE_VALUE (olddecl); ! cp_error_at ("previous declaration of `%#D'", olddecl); ! ! /* New decl is completely inconsistent with the old one => ! tell caller to replace the old one. */ ! return NULL_TREE; } else if (!types_match) { --- 1224,1235 ---- && DECL_FUNCTION_TEMPLATE_P (newdecl))) return NULL_TREE; ! error ("%q#D redeclared as different kind of symbol", newdecl); if (TREE_CODE (olddecl) == TREE_LIST) olddecl = TREE_VALUE (olddecl); ! cp_error_at ("previous declaration of %q#D", olddecl); ! return error_mark_node; } else if (!types_match) { *************** duplicate_decls (tree newdecl, tree oldd *** 1337,1344 **** if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) { ! error ("declaration of template `%#D'", newdecl); ! cp_error_at ("conflicts with previous declaration `%#D'", olddecl); } else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL --- 1246,1253 ---- if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) { ! error ("declaration of template %q#D", newdecl); ! cp_error_at ("conflicts with previous declaration %q#D", olddecl); } else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL *************** duplicate_decls (tree newdecl, tree oldd *** 1352,1359 **** && 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); } return NULL_TREE; } --- 1261,1268 ---- && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)), TREE_TYPE (TREE_TYPE (olddecl)))) { ! error ("new declaration %q#D", newdecl); ! cp_error_at ("ambiguates old declaration %q#D", olddecl); } return NULL_TREE; } *************** duplicate_decls (tree newdecl, tree oldd *** 1361,1388 **** { if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) { ! error ("declaration of C function `%#D' conflicts with", ! newdecl); ! cp_error_at ("previous declaration `%#D' here", olddecl); } else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) { ! error ("new declaration `%#D'", newdecl); ! cp_error_at ("ambiguates old declaration `%#D'", olddecl); } else return NULL_TREE; } ! ! /* Already complained about this, so don't do so again. */ ! else if (current_class_type == NULL_TREE ! || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) { ! error ("conflicting declaration '%#D'", newdecl); ! cp_error_at ("'%D' has a previous declaration as `%#D'", olddecl, olddecl); ! return NULL_TREE; } } else if (TREE_CODE (newdecl) == FUNCTION_DECL --- 1270,1294 ---- { if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) { ! error ("declaration of C function %q#D conflicts with", ! newdecl); ! cp_error_at ("previous declaration %q#D here", olddecl); } else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) { ! error ("new declaration %q#D", newdecl); ! cp_error_at ("ambiguates old declaration %q#D", olddecl); } else return NULL_TREE; } ! else { ! error ("conflicting declaration %q#D", newdecl); ! cp_error_at ("%qD has a previous declaration as %q#D", olddecl, olddecl); ! return error_mark_node; } } else if (TREE_CODE (newdecl) == FUNCTION_DECL *************** duplicate_decls (tree newdecl, tree oldd *** 1431,1440 **** A namespace-name or namespace-alias shall not be declared as the name of any other entity in the same declarative region. A namespace-name defined at global scope shall not be ! declared as the name of any other entity in any glogal scope of the program. */ ! error ("declaration of `namespace %D' conflicts with", newdecl); ! cp_error_at ("previous declaration of `namespace %D' here", olddecl); return error_mark_node; } else --- 1337,1346 ---- A namespace-name or namespace-alias shall not be declared as the name of any other entity in the same declarative region. A namespace-name defined at global scope shall not be ! declared as the name of any other entity in any global scope of the program. */ ! error ("declaration of namespace %qD conflicts with", newdecl); ! cp_error_at ("previous declaration of namespace %qD here", olddecl); return error_mark_node; } else *************** duplicate_decls (tree newdecl, tree oldd *** 1446,1453 **** if (DECL_NAME (olddecl) != NULL_TREE) cp_error_at ((DECL_INITIAL (olddecl) && namespace_bindings_p ()) ! ? "`%#D' previously defined here" ! : "`%#D' previously declared here", olddecl); return error_mark_node; } else if (TREE_CODE (olddecl) == FUNCTION_DECL --- 1352,1359 ---- if (DECL_NAME (olddecl) != NULL_TREE) cp_error_at ((DECL_INITIAL (olddecl) && namespace_bindings_p ()) ! ? "%q#D previously defined here" ! : "%q#D previously declared here", olddecl); return error_mark_node; } else if (TREE_CODE (olddecl) == FUNCTION_DECL *************** duplicate_decls (tree newdecl, tree oldd *** 1456,1462 **** && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE) { /* Prototype decl follows defn w/o prototype. */ ! cp_warning_at ("prototype for `%#D'", newdecl); warning ("%Jfollows non-prototype definition here", olddecl); } else if (TREE_CODE (olddecl) == FUNCTION_DECL --- 1362,1368 ---- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE) { /* Prototype decl follows defn w/o prototype. */ ! cp_warning_at ("prototype for %q#D", newdecl); warning ("%Jfollows non-prototype definition here", olddecl); } else if (TREE_CODE (olddecl) == FUNCTION_DECL *************** duplicate_decls (tree newdecl, tree oldd *** 1469,1478 **** SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else { ! cp_error_at ("previous declaration of `%#D' with %L linkage", olddecl, DECL_LANGUAGE (olddecl)); ! error ("conflicts with new declaration with %L linkage", ! DECL_LANGUAGE (newdecl)); } } --- 1375,1384 ---- SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else { ! cp_error_at ("previous declaration of %q#D with %qL linkage", olddecl, DECL_LANGUAGE (olddecl)); ! error ("conflicts with new declaration with %qL linkage", ! DECL_LANGUAGE (newdecl)); } } *************** duplicate_decls (tree newdecl, tree oldd *** 1494,1518 **** if (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))) { ! pedwarn ("default argument given for parameter %d of `%#D'", i, newdecl); ! cp_pedwarn_at ("after previous specification in `%#D'", olddecl); } else { ! error ("default argument given for parameter %d of `%#D'", ! i, newdecl); ! cp_error_at ("after previous specification in `%#D'", olddecl); } } ! if (DECL_DECLARED_INLINE_P (newdecl) && ! DECL_DECLARED_INLINE_P (olddecl) && TREE_ADDRESSABLE (olddecl) && warn_inline) { ! warning ("`%#D' was used before it was declared inline", newdecl); warning ("%Jprevious non-inline declaration here", olddecl); } } --- 1400,1424 ---- if (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))) { ! pedwarn ("default argument given for parameter %d of %q#D", i, newdecl); ! cp_pedwarn_at ("after previous specification in %q#D", olddecl); } else { ! error ("default argument given for parameter %d of %q#D", ! i, newdecl); ! cp_error_at ("after previous specification in %q#D", olddecl); } } ! if (DECL_DECLARED_INLINE_P (newdecl) && ! DECL_DECLARED_INLINE_P (olddecl) && TREE_ADDRESSABLE (olddecl) && warn_inline) { ! warning ("%q#D was used before it was declared inline", newdecl); warning ("%Jprevious non-inline declaration here", olddecl); } } *************** duplicate_decls (tree newdecl, tree oldd *** 1549,1555 **** DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl); DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl); - DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl); DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl); if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK) SET_OVERLOADED_OPERATOR_CODE --- 1455,1460 ---- *************** duplicate_decls (tree newdecl, tree oldd *** 1566,1573 **** /* 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); ! cp_warning_at ("previous declaration of `%D'", olddecl); } } --- 1471,1478 ---- /* Don't warn about friends, let add_friend take care of it. */ && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl))) { ! warning ("redundant redeclaration of %qD in same scope", newdecl); ! cp_warning_at ("previous declaration of %qD", olddecl); } } *************** duplicate_decls (tree newdecl, tree oldd *** 1602,1608 **** if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE) { ! DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl)) = DECL_SOURCE_LOCATION (newdecl); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) --- 1507,1513 ---- if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE) { ! DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl)) = DECL_SOURCE_LOCATION (newdecl); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) *************** duplicate_decls (tree newdecl, tree oldd *** 1612,1618 **** if (DECL_FUNCTION_TEMPLATE_P (newdecl)) { ! DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl)) |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl)); DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl)) |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl)); --- 1517,1523 ---- if (DECL_FUNCTION_TEMPLATE_P (newdecl)) { ! DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl)) |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl)); DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl)) |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl)); *************** duplicate_decls (tree newdecl, tree oldd *** 1655,1668 **** TYPE_RAISES_EXCEPTIONS (oldtype)); if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl)) ! && DECL_SOURCE_LINE (olddecl) != 0 && flag_exceptions && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)), TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1)) { ! error ("declaration of `%F' throws different exceptions", ! newdecl); ! cp_error_at ("than previous declaration `%F'", olddecl); } } TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; --- 1560,1573 ---- TYPE_RAISES_EXCEPTIONS (oldtype)); if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl)) ! && ! DECL_IS_BUILTIN (olddecl) && flag_exceptions && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)), TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1)) { ! error ("declaration of %qF throws different exceptions", ! newdecl); ! cp_error_at ("than previous declaration %qF", olddecl); } } TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; *************** duplicate_decls (tree newdecl, tree oldd *** 1686,1691 **** --- 1591,1602 ---- TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) TREE_THIS_VOLATILE (olddecl) = 1; + if (TREE_NOTHROW (newdecl)) + TREE_NOTHROW (olddecl) = 1; + + /* Merge deprecatedness. */ + if (TREE_DEPRECATED (newdecl)) + TREE_DEPRECATED (olddecl) = 1; /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == NULL_TREE *************** duplicate_decls (tree newdecl, tree oldd *** 1698,1704 **** && DECL_LANG_SPECIFIC (olddecl)) { DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); ! DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); } } --- 1609,1615 ---- && DECL_LANG_SPECIFIC (olddecl)) { DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); ! DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); } } *************** duplicate_decls (tree newdecl, tree oldd *** 1722,1728 **** /* Keep the old RTL. */ COPY_DECL_RTL (olddecl, newdecl); } ! else if (TREE_CODE (newdecl) == VAR_DECL && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl))) { /* Keep the old RTL. We cannot keep the old RTL if the old --- 1633,1639 ---- /* Keep the old RTL. */ COPY_DECL_RTL (olddecl, newdecl); } ! else if (TREE_CODE (newdecl) == VAR_DECL && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl))) { /* Keep the old RTL. We cannot keep the old RTL if the old *************** duplicate_decls (tree newdecl, tree oldd *** 1764,1775 **** DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl); DECL_TEMPLATE_INSTANTIATED (newdecl) |= DECL_TEMPLATE_INSTANTIATED (olddecl); /* Don't really know how much of the language-specific values we should copy from old to new. */ DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); ! DECL_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) |= DECL_INITIALIZED_IN_CLASS_P (olddecl); --- 1675,1694 ---- DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl); DECL_TEMPLATE_INSTANTIATED (newdecl) |= DECL_TEMPLATE_INSTANTIATED (olddecl); + /* If the OLDDECL is an implicit instantiation, then the NEWDECL + must be too. But, it may not yet be marked as such if the + caller has created NEWDECL, but has not yet figured out that + it is a redeclaration. */ + if (DECL_IMPLICIT_INSTANTIATION (olddecl) + && !DECL_USE_TEMPLATE (newdecl)) + SET_DECL_IMPLICIT_INSTANTIATION (newdecl); /* 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_LANG_SPECIFIC (newdecl)->decl_flags.u2 = DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2; DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); + DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl); DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); DECL_INITIALIZED_IN_CLASS_P (newdecl) |= DECL_INITIALIZED_IN_CLASS_P (olddecl); *************** duplicate_decls (tree newdecl, tree oldd *** 1797,1804 **** /* If newdecl is not a specialization, then it is not a template-related function at all. And that means that we should have exited above, returning 0. */ ! my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl), ! 0); if (TREE_USED (olddecl)) /* From [temp.expl.spec]: --- 1716,1722 ---- /* If newdecl is not a specialization, then it is not a template-related function at all. And that means that we should have exited above, returning 0. */ ! gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl)); if (TREE_USED (olddecl)) /* From [temp.expl.spec]: *************** duplicate_decls (tree newdecl, tree oldd *** 1809,1815 **** that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs. */ ! error ("explicit specialization of %D after first use", olddecl); SET_DECL_TEMPLATE_SPECIALIZATION (olddecl); --- 1727,1733 ---- that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs. */ ! error ("explicit specialization of %qD after first use", olddecl); SET_DECL_TEMPLATE_SPECIALIZATION (olddecl); *************** duplicate_decls (tree newdecl, tree oldd *** 1824,1830 **** 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; --- 1742,1748 ---- 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; *************** duplicate_decls (tree newdecl, tree oldd *** 1841,1847 **** { SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl); ! SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); } if (! types_match || new_defines_function) { --- 1759,1765 ---- { SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl); ! COPY_DECL_RTL (newdecl, olddecl); } if (! types_match || new_defines_function) { *************** duplicate_decls (tree newdecl, tree oldd *** 1865,1871 **** DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); /* If we're keeping the built-in definition, keep the rtl, regardless of declaration matches. */ ! SET_DECL_RTL (newdecl, DECL_RTL (olddecl)); } DECL_RESULT (newdecl) = DECL_RESULT (olddecl); --- 1783,1789 ---- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); /* If we're keeping the built-in definition, keep the rtl, regardless of declaration matches. */ ! COPY_DECL_RTL (olddecl, newdecl); } DECL_RESULT (newdecl) = DECL_RESULT (olddecl); *************** duplicate_decls (tree newdecl, tree oldd *** 1883,1899 **** DECL_COMMON (newdecl) = DECL_COMMON (olddecl); COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); ! /* If either declaration has a nondefault visibility, use it. */ ! if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT) { - if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT - && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) - { - warning ("%J'%D': visibility attribute ignored because it", - newdecl, newdecl); - warning ("%Jconflicts with previous declaration here", olddecl); - } DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); } if (TREE_CODE (newdecl) == FUNCTION_DECL) --- 1801,1829 ---- DECL_COMMON (newdecl) = DECL_COMMON (olddecl); COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); ! /* Warn about conflicting visibility specifications. */ ! if (DECL_VISIBILITY_SPECIFIED (olddecl) ! && DECL_VISIBILITY_SPECIFIED (newdecl) ! && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) ! { ! warning ("%J%qD: visibility attribute ignored because it", ! newdecl, newdecl); ! warning ("%Jconflicts with previous declaration here", olddecl); ! } ! /* Choose the declaration which specified visibility. */ ! if (DECL_VISIBILITY_SPECIFIED (olddecl)) { DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); + DECL_VISIBILITY_SPECIFIED (newdecl) = 1; + } + + /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced + with that from NEWDECL below. */ + if (DECL_LANG_SPECIFIC (olddecl)) + { + gcc_assert (DECL_LANG_SPECIFIC (olddecl) + != DECL_LANG_SPECIFIC (newdecl)); + ggc_free (DECL_LANG_SPECIFIC (olddecl)); } if (TREE_CODE (newdecl) == FUNCTION_DECL) *************** duplicate_decls (tree newdecl, tree oldd *** 1928,1935 **** olddecl, and not newdecl, is on the list of instantiations so that if we try to do the instantiation again we won't get the clobbered declaration. */ ! reregister_specialization (newdecl, ! DECL_TI_TEMPLATE (newdecl), olddecl); } else --- 1858,1865 ---- olddecl, and not newdecl, is on the list of instantiations so that if we try to do the instantiation again we won't get the clobbered declaration. */ ! reregister_specialization (newdecl, ! DECL_TI_TEMPLATE (newdecl), olddecl); } else *************** duplicate_decls (tree newdecl, tree oldd *** 1951,1998 **** /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl so that encode_section_info has a chance to look at the new decl flags and attributes. */ ! if (DECL_RTL_SET_P (olddecl) && (TREE_CODE (olddecl) == FUNCTION_DECL || (TREE_CODE (olddecl) == VAR_DECL && TREE_STATIC (olddecl)))) ! make_decl_rtl (olddecl, NULL); return olddecl; } - /* Generate an implicit declaration for identifier FUNCTIONID - as a function of type int (). Print a warning if appropriate. */ - - tree - implicitly_declare (tree functionid) - { - tree decl; - - /* We used to reuse an old implicit decl here, - but this loses with inline functions because it can clobber - the saved decl chains. */ - decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type); - - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; - - /* ISO standard says implicit declarations are in the innermost block. - So we record the decl in the standard fashion. */ - pushdecl (decl); - rest_of_decl_compilation (decl, NULL, 0, 0); - - if (warn_implicit - /* Only one warning per identifier. */ - && IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE) - { - pedwarn ("implicit declaration of function `%#D'", decl); - } - - SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl); - - return decl; - } - /* Return zero if the declaration NEWDECL is valid when the declaration OLDDECL (assumed to be for the same name) has already been seen. --- 1881,1900 ---- /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl so that encode_section_info has a chance to look at the new decl flags and attributes. */ ! if (DECL_RTL_SET_P (olddecl) && (TREE_CODE (olddecl) == FUNCTION_DECL || (TREE_CODE (olddecl) == VAR_DECL && TREE_STATIC (olddecl)))) ! make_decl_rtl (olddecl); ! ! /* The NEWDECL will no longer be needed. Because every out-of-class ! declaration of a member results in a call to duplicate_decls, ! freeing these nodes represents in a significant savings. */ ! ggc_free (newdecl); return olddecl; } /* Return zero if the declaration NEWDECL is valid when the declaration OLDDECL (assumed to be for the same name) has already been seen. *************** redeclaration_error_message (tree newdec *** 2010,2030 **** if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl))) return 0; else ! return "redefinition of `%#D'"; } else if (TREE_CODE (newdecl) == FUNCTION_DECL) { /* If this is a pure function, its olddecl will actually be the original initialization to `0' (which we force to call abort()). Don't complain about redefinition in this case. */ ! if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)) return 0; /* If both functions come from different namespaces, this is not a redeclaration - this is a conflict with a used function. */ if (DECL_NAMESPACE_SCOPE_P (olddecl) ! && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)) ! return "`%D' conflicts with used function"; /* We'll complain about linkage mismatches in warn_extern_redeclared_static. */ --- 1912,1934 ---- if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl))) return 0; else ! return "redefinition of %q#D"; } else if (TREE_CODE (newdecl) == FUNCTION_DECL) { /* If this is a pure function, its olddecl will actually be the original initialization to `0' (which we force to call abort()). Don't complain about redefinition in this case. */ ! if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl) ! && DECL_INITIAL (olddecl) == NULL_TREE) return 0; /* If both functions come from different namespaces, this is not a redeclaration - this is a conflict with a used function. */ if (DECL_NAMESPACE_SCOPE_P (olddecl) ! && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl) ! && ! decls_match (olddecl, newdecl)) ! return "%qD conflicts with used function"; /* We'll complain about linkage mismatches in warn_extern_redeclared_static. */ *************** redeclaration_error_message (tree newdec *** 2034,2042 **** && DECL_INITIAL (newdecl) != NULL_TREE) { if (DECL_NAME (olddecl) == NULL_TREE) ! return "`%#D' not declared in class"; else ! return "redefinition of `%#D'"; } return 0; } --- 1938,1946 ---- && DECL_INITIAL (newdecl) != NULL_TREE) { if (DECL_NAME (olddecl) == NULL_TREE) ! return "%q#D not declared in class"; else ! return "redefinition of %q#D"; } return 0; } *************** redeclaration_error_message (tree newdec *** 2048,2059 **** { if (COMPLETE_TYPE_P (TREE_TYPE (newdecl)) && COMPLETE_TYPE_P (TREE_TYPE (olddecl))) ! return "redefinition of `%#D'"; return NULL; } if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL ! || (DECL_TEMPLATE_RESULT (newdecl) == DECL_TEMPLATE_RESULT (olddecl))) return NULL; --- 1952,1963 ---- { if (COMPLETE_TYPE_P (TREE_TYPE (newdecl)) && COMPLETE_TYPE_P (TREE_TYPE (olddecl))) ! return "redefinition of %q#D"; return NULL; } if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL ! || (DECL_TEMPLATE_RESULT (newdecl) == DECL_TEMPLATE_RESULT (olddecl))) return NULL; *************** redeclaration_error_message (tree newdec *** 2064,2070 **** if (DECL_TEMPLATE_INFO (ot)) ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot)); if (DECL_INITIAL (nt) && DECL_INITIAL (ot)) ! return "redefinition of `%#D'"; return NULL; } --- 1968,1974 ---- if (DECL_TEMPLATE_INFO (ot)) ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot)); if (DECL_INITIAL (nt) && DECL_INITIAL (ot)) ! return "redefinition of %q#D"; return NULL; } *************** redeclaration_error_message (tree newdec *** 2075,2081 **** if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ ! return "redefinition of `%#D'"; } else { --- 1979,1985 ---- if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ ! return "redefinition of %q#D"; } else { *************** redeclaration_error_message (tree newdec *** 2083,2089 **** /* Reject two definitions, and reject a definition together with an external reference. */ if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) ! return "redeclaration of `%#D'"; return 0; } } --- 1987,1993 ---- /* Reject two definitions, and reject a definition together with an external reference. */ if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) ! return "redeclaration of %q#D"; return 0; } } *************** use_label (tree decl) *** 2124,2130 **** || named_label_uses->label_decl != decl) { struct named_label_use_list *new_ent; ! new_ent = ggc_alloc (sizeof (struct named_label_use_list)); new_ent->label_decl = decl; new_ent->names_in_scope = current_binding_level->names; new_ent->binding_level = current_binding_level; --- 2028,2034 ---- || named_label_uses->label_decl != decl) { struct named_label_use_list *new_ent; ! new_ent = GGC_NEW (struct named_label_use_list); new_ent->label_decl = decl; new_ent->names_in_scope = current_binding_level->names; new_ent->binding_level = current_binding_level; *************** lookup_label (tree id) *** 2148,2155 **** /* 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)); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); } --- 2052,2058 ---- /* You can't use labels at global scope. */ if (current_function_decl == NULL_TREE) { ! error ("label %qE referenced outside of any function", id); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); } *************** lookup_label (tree id) *** 2161,2167 **** /* 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 IDENTIFIER_LABEL_VALUE before the new label is declared. */ ! ent = ggc_alloc_cleared (sizeof (struct named_label_list)); ent->old_value = IDENTIFIER_LABEL_VALUE (id); ent->next = named_labels; named_labels = ent; --- 2064,2070 ---- /* 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 IDENTIFIER_LABEL_VALUE before the new label is declared. */ ! ent = GGC_CNEW (struct named_label_list); ent->old_value = IDENTIFIER_LABEL_VALUE (id); ent->next = named_labels; named_labels = ent; *************** check_previous_goto_1 (tree decl, *** 2245,2251 **** if (! identified) { if (decl) ! pedwarn ("jump to label `%D'", decl); else pedwarn ("jump to case label"); --- 2148,2154 ---- if (! identified) { if (decl) ! pedwarn ("jump to label %qD", decl); else pedwarn ("jump to case label"); *************** check_previous_goto_1 (tree decl, *** 2255,2264 **** } if (problem > 1) ! cp_error_at (" crosses initialization of `%#D'", new_decls); else ! cp_pedwarn_at (" enters scope of non-POD `%#D'", new_decls); } --- 2158,2167 ---- } if (problem > 1) ! cp_error_at (" crosses initialization of %q#D", new_decls); else ! cp_pedwarn_at (" enters scope of non-POD %q#D", new_decls); } *************** check_previous_goto_1 (tree decl, *** 2269,2275 **** if (! identified) { if (decl) ! pedwarn ("jump to label `%D'", decl); else pedwarn ("jump to case label"); --- 2172,2178 ---- if (! identified) { if (decl) ! pedwarn ("jump to label %qD", decl); else pedwarn ("jump to case label"); *************** check_goto (tree decl) *** 2357,2363 **** if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls) && !identified) { ! cp_pedwarn_at ("jump to label `%D'", decl); pedwarn (" from here"); identified = 1; } --- 2260,2266 ---- if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls) && !identified) { ! cp_pedwarn_at ("jump to label %qD", decl); pedwarn (" from here"); identified = 1; } *************** check_goto (tree decl) *** 2371,2379 **** /* Can't skip init of __exception_info. */ error ("%J enters catch block", b); else if (u > 1) ! cp_error_at (" skips initialization of `%#D'", b); else ! cp_pedwarn_at (" enters scope of non-POD `%#D'", b); } if (lab->in_try_scope) --- 2274,2282 ---- /* Can't skip init of __exception_info. */ error ("%J enters catch block", b); else if (u > 1) ! cp_error_at (" skips initialization of %q#D", b); else ! cp_pedwarn_at (" enters scope of non-POD %q#D", b); } if (lab->in_try_scope) *************** define_label (location_t location, tree *** 2399,2406 **** /* After labels, make any new cleanups in the function go into their own new (temporary) binding contour. */ ! for (p = current_binding_level; ! p->kind != sk_function_parms; p = p->level_chain) p->more_cleanups_ok = 0; --- 2302,2309 ---- /* After labels, make any new cleanups in the function go into their own new (temporary) binding contour. */ ! for (p = current_binding_level; ! p->kind != sk_function_parms; p = p->level_chain) p->more_cleanups_ok = 0; *************** define_label (location_t location, tree *** 2408,2414 **** pedwarn ("label named wchar_t"); if (DECL_INITIAL (decl) != NULL_TREE) ! error ("duplicate label `%D'", decl); else { /* Mark label as having been defined. */ --- 2311,2317 ---- pedwarn ("label named wchar_t"); if (DECL_INITIAL (decl) != NULL_TREE) ! error ("duplicate label %qD", decl); else { /* Mark label as having been defined. */ *************** define_label (location_t location, tree *** 2423,2430 **** check_previous_gotos (decl); } ! timevar_pop (TV_NAME_LOOKUP); ! return decl; } struct cp_switch --- 2326,2332 ---- check_previous_gotos (decl); } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl); } struct cp_switch *************** push_switch (tree switch_stmt) *** 2466,2474 **** void pop_switch (void) { ! struct cp_switch *cs; - cs = switch_stack; splay_tree_delete (cs->cases); switch_stack = switch_stack->next; free (cs); --- 2368,2378 ---- void pop_switch (void) { ! struct cp_switch *cs = switch_stack; ! ! /* Emit warnings as needed. */ ! c_do_switch_warnings (cs->cases, cs->switch_stmt); splay_tree_delete (cs->cases); switch_stack = switch_stack->next; free (cs); *************** finish_case_label (tree low_value, tree *** 2494,2511 **** } /* Find the condition on which this switch statement depends. */ ! cond = SWITCH_COND (switch_stack->switch_stmt); if (cond && TREE_CODE (cond) == TREE_LIST) cond = TREE_VALUE (cond); ! r = c_add_case_label (switch_stack->cases, cond, low_value, high_value); check_switch_goto (switch_stack->level); /* After labels, make any new cleanups in the function go into their own new (temporary) binding contour. */ ! for (p = current_binding_level; ! p->kind != sk_function_parms; p = p->level_chain) p->more_cleanups_ok = 0; --- 2398,2416 ---- } /* Find the condition on which this switch statement depends. */ ! cond = SWITCH_STMT_COND (switch_stack->switch_stmt); if (cond && TREE_CODE (cond) == TREE_LIST) cond = TREE_VALUE (cond); ! r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond), ! low_value, high_value); check_switch_goto (switch_stack->level); /* After labels, make any new cleanups in the function go into their own new (temporary) binding contour. */ ! for (p = current_binding_level; ! p->kind != sk_function_parms; p = p->level_chain) p->more_cleanups_ok = 0; *************** typename_hash (const void* k) *** 2526,2608 **** return hash; } /* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */ static int typename_compare (const void * k1, const void * k2) { tree t1; ! tree t2; ! tree d1; ! tree d2; t1 = (tree) k1; ! t2 = (tree) k2; ! d1 = TYPE_NAME (t1); ! d2 = TYPE_NAME (t2); ! return (DECL_NAME (d1) == DECL_NAME (d2) ! && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2) ! && ((TREE_TYPE (t1) != NULL_TREE) ! == (TREE_TYPE (t2) != NULL_TREE)) ! && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) ! && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2)); } /* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is ! the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE ! is non-NULL, this type is being created by the implicit typename ! extension, and BASE_TYPE is a type named `t' in some base class of ! `T' which depends on template parameters. ! Returns the new TYPENAME_TYPE. */ static GTY ((param_is (union tree_node))) htab_t typename_htab; static tree ! build_typename_type (tree context, tree name, tree fullname) { tree t; tree d; void **e; if (typename_htab == NULL) ! { ! typename_htab = htab_create_ggc (61, &typename_hash, ! &typename_compare, NULL); ! } ! ! /* Build the TYPENAME_TYPE. */ ! t = make_aggr_type (TYPENAME_TYPE); ! TYPE_CONTEXT (t) = FROB_CONTEXT (context); ! TYPENAME_TYPE_FULLNAME (t) = fullname; ! /* Build the corresponding TYPE_DECL. */ ! d = build_decl (TYPE_DECL, name, t); ! TYPE_NAME (TREE_TYPE (d)) = d; ! TYPE_STUB_DECL (TREE_TYPE (d)) = d; ! DECL_CONTEXT (d) = FROB_CONTEXT (context); ! DECL_ARTIFICIAL (d) = 1; /* See if we already have this type. */ ! e = htab_find_slot (typename_htab, t, INSERT); if (*e) t = (tree) *e; else ! *e = t; return t; } ! /* Resolve `typename CONTEXT::NAME'. Returns an appropriate type, ! unless an error occurs, in which case error_mark_node is returned. ! If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is ! set, we return that, rather than the _TYPE it corresponds to, in ! other cases we look through the type decl. If TF_ERROR is set, ! complain about errors, otherwise be quiet. */ tree ! make_typename_type (tree context, tree name, tsubst_flags_t complain) { tree fullname; --- 2431,2531 ---- return hash; } + typedef struct typename_info { + tree scope; + tree name; + tree template_id; + bool enum_p; + bool class_p; + } typename_info; + /* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */ static int typename_compare (const void * k1, const void * k2) { tree t1; ! const typename_info *t2; t1 = (tree) k1; ! t2 = (const typename_info *) k2; ! return (DECL_NAME (TYPE_NAME (t1)) == t2->name ! && TYPE_CONTEXT (t1) == t2->scope ! && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id ! && TYPENAME_IS_ENUM_P (t1) == t2->enum_p ! && TYPENAME_IS_CLASS_P (t1) == t2->class_p); } /* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is ! the type of `T', NAME is the IDENTIFIER_NODE for `t'. ! Returns the new TYPENAME_TYPE. */ static GTY ((param_is (union tree_node))) htab_t typename_htab; static tree ! build_typename_type (tree context, tree name, tree fullname, ! enum tag_types tag_type) { tree t; tree d; + typename_info ti; void **e; + hashval_t hash; if (typename_htab == NULL) ! typename_htab = htab_create_ggc (61, &typename_hash, ! &typename_compare, NULL); ! ti.scope = FROB_CONTEXT (context); ! ti.name = name; ! ti.template_id = fullname; ! ti.enum_p = tag_type == enum_type; ! ti.class_p = (tag_type == class_type ! || tag_type == record_type ! || tag_type == union_type); ! hash = (htab_hash_pointer (ti.scope) ! ^ htab_hash_pointer (ti.name)); /* See if we already have this type. */ ! e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT); if (*e) t = (tree) *e; else ! { ! /* Build the TYPENAME_TYPE. */ ! t = make_aggr_type (TYPENAME_TYPE); ! TYPE_CONTEXT (t) = ti.scope; ! TYPENAME_TYPE_FULLNAME (t) = ti.template_id; ! TYPENAME_IS_ENUM_P (t) = ti.enum_p; ! TYPENAME_IS_CLASS_P (t) = ti.class_p; ! ! /* Build the corresponding TYPE_DECL. */ ! d = build_decl (TYPE_DECL, name, t); ! TYPE_NAME (TREE_TYPE (d)) = d; ! TYPE_STUB_DECL (TREE_TYPE (d)) = d; ! DECL_CONTEXT (d) = FROB_CONTEXT (context); ! DECL_ARTIFICIAL (d) = 1; + /* Store it in the hash table. */ + *e = t; + } + return t; } ! /* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag ! provided to name the type. Returns an appropriate type, unless an ! error occurs, in which case error_mark_node is returned. If we ! locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we ! return that, rather than the _TYPE it corresponds to, in other ! cases we look through the type decl. If TF_ERROR is set, complain ! about errors, otherwise be quiet. */ tree ! make_typename_type (tree context, tree name, enum tag_types tag_type, ! tsubst_flags_t complain) { tree fullname; *************** make_typename_type (tree context, tree n *** 2636,2655 **** } if (TREE_CODE (name) == TEMPLATE_DECL) { ! error ("`%D' used without template parameters", name); ! return error_mark_node; ! } ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802); ! ! if (TREE_CODE (context) == NAMESPACE_DECL) ! { ! /* We can get here from typename_sub0 in the explicit_template_type ! expansion. Just fail. */ ! if (complain & tf_error) ! error ("no class template named `%#T' in `%#T'", ! name, context); return error_mark_node; } if (!dependent_type_p (context) || currently_open_class (context)) --- 2559,2569 ---- } if (TREE_CODE (name) == TEMPLATE_DECL) { ! error ("%qD used without template parameters", name); return error_mark_node; } + gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); + gcc_assert (TYPE_P (context)); if (!dependent_type_p (context) || currently_open_class (context)) *************** make_typename_type (tree context, tree n *** 2662,2669 **** if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { if (complain & tf_error) ! error ("no class template named `%#T' in `%#T'", ! name, context); return error_mark_node; } --- 2576,2583 ---- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { if (complain & tf_error) ! error ("no class template named %q#T in %q#T", ! name, context); return error_mark_node; } *************** make_typename_type (tree context, tree n *** 2683,2689 **** if (!IS_AGGR_TYPE (context)) { if (complain & tf_error) ! error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } --- 2597,2603 ---- if (!IS_AGGR_TYPE (context)) { if (complain & tf_error) ! error ("no type named %q#T in %q#T", name, context); return error_mark_node; } *************** make_typename_type (tree context, tree n *** 2693,2699 **** if (TREE_CODE (t) != TYPE_DECL) { if (complain & tf_error) ! error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } --- 2607,2613 ---- if (TREE_CODE (t) != TYPE_DECL) { if (complain & tf_error) ! error ("no type named %q#T in %q#T", name, context); return error_mark_node; } *************** make_typename_type (tree context, tree n *** 2702,2708 **** if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl)) t = TREE_TYPE (t); ! return t; } } --- 2616,2622 ---- if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl)) t = TREE_TYPE (t); ! return t; } } *************** make_typename_type (tree context, tree n *** 2713,2733 **** if (!dependent_type_p (context)) { if (complain & tf_error) ! error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } ! return build_typename_type (context, name, fullname); } ! /* Resolve `CONTEXT::template NAME'. Returns an appropriate type, ! unless an error occurs, in which case error_mark_node is returned. ! If we locate a TYPE_DECL, we return that, rather than the _TYPE it ! corresponds to. If COMPLAIN zero, don't complain about any errors ! that occur. */ tree ! make_unbound_class_template (tree context, tree name, tsubst_flags_t complain) { tree t; tree d; --- 2627,2651 ---- if (!dependent_type_p (context)) { if (complain & tf_error) ! error ("no type named %q#T in %q#T", name, context); return error_mark_node; } ! return build_typename_type (context, name, fullname, tag_type); } ! /* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name ! can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs, ! in which case error_mark_node is returned. ! ! If PARM_LIST is non-NULL, also make sure that the template parameter ! list of TEMPLATE_DECL matches. ! ! If COMPLAIN zero, don't complain about any errors that occur. */ tree ! make_unbound_class_template (tree context, tree name, tree parm_list, ! tsubst_flags_t complain) { tree t; tree d; *************** make_unbound_class_template (tree contex *** 2736,2743 **** name = TYPE_IDENTIFIER (name); else if (DECL_P (name)) name = DECL_NAME (name); ! if (TREE_CODE (name) != IDENTIFIER_NODE) ! abort (); if (!dependent_type_p (context) || currently_open_class (context)) --- 2654,2660 ---- name = TYPE_IDENTIFIER (name); else if (DECL_P (name)) name = DECL_NAME (name); ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); if (!dependent_type_p (context) || currently_open_class (context)) *************** make_unbound_class_template (tree contex *** 2750,2759 **** if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { if (complain & tf_error) ! error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; } ! if (complain & tf_error) perform_or_defer_access_check (TYPE_BINFO (context), tmpl); --- 2667,2687 ---- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { if (complain & tf_error) ! error ("no class template named %q#T in %q#T", name, context); return error_mark_node; } ! ! if (parm_list ! && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list)) ! { ! if (complain & tf_error) ! { ! error ("template parameters do not match template"); ! cp_error_at ("%qD declared here", tmpl); ! } ! return error_mark_node; ! } ! if (complain & tf_error) perform_or_defer_access_check (TYPE_BINFO (context), tmpl); *************** make_unbound_class_template (tree contex *** 2771,2802 **** TYPE_STUB_DECL (TREE_TYPE (d)) = d; DECL_CONTEXT (d) = FROB_CONTEXT (context); DECL_ARTIFICIAL (d) = 1; return t; } - /* A chain of TYPE_DECLs for the builtin types. */ - - static GTY(()) tree builtin_type_decls; - - /* Return a chain of TYPE_DECLs for the builtin types. */ - - tree - cxx_builtin_type_decls (void) - { - return builtin_type_decls; - } - /* Push the declarations of builtin types into the namespace. RID_INDEX is the index of the builtin type in the array RID_POINTERS. NAME is the name used when looking up the builtin type. TYPE is the _TYPE node for the builtin type. */ void ! record_builtin_type (enum rid rid_index, ! const char* name, tree type) { tree rname = NULL_TREE, tname = NULL_TREE; --- 2699,2719 ---- TYPE_STUB_DECL (TREE_TYPE (d)) = d; DECL_CONTEXT (d) = FROB_CONTEXT (context); DECL_ARTIFICIAL (d) = 1; + DECL_TEMPLATE_PARMS (d) = parm_list; return t; } /* Push the declarations of builtin types into the namespace. RID_INDEX is the index of the builtin type in the array RID_POINTERS. NAME is the name used when looking up the builtin type. TYPE is the _TYPE node for the builtin type. */ void ! record_builtin_type (enum rid rid_index, ! const char* name, tree type) { tree rname = NULL_TREE, tname = NULL_TREE; *************** record_builtin_type (enum rid rid_index, *** 2832,2841 **** TYPE_NAME (type) = tdecl; if (tdecl) ! { ! TREE_CHAIN (tdecl) = builtin_type_decls; ! builtin_type_decls = tdecl; ! } } /* Record one of the standard Java types. --- 2749,2755 ---- TYPE_NAME (type) = tdecl; if (tdecl) ! debug_hooks->type_decl (tdecl, 0); } /* Record one of the standard Java types. *************** initialize_predefined_identifiers (void) *** 2912,2924 **** { "C++", &lang_name_cplusplus, 0 }, { "C", &lang_name_c, 0 }, { "Java", &lang_name_java, 0 }, ! { CTOR_NAME, &ctor_identifier, 1 }, ! { "__base_ctor", &base_ctor_identifier, 1 }, ! { "__comp_ctor", &complete_ctor_identifier, 1 }, ! { DTOR_NAME, &dtor_identifier, 1 }, ! { "__comp_dtor", &complete_dtor_identifier, 1 }, ! { "__base_dtor", &base_dtor_identifier, 1 }, ! { "__deleting_dtor", &deleting_dtor_identifier, 1 }, { IN_CHARGE_NAME, &in_charge_identifier, 0 }, { "nelts", &nelts_identifier, 0 }, { THIS_NAME, &this_identifier, 0 }, --- 2826,2840 ---- { "C++", &lang_name_cplusplus, 0 }, { "C", &lang_name_c, 0 }, { "Java", &lang_name_java, 0 }, ! /* Some of these names have a trailing space so that it is ! impossible for them to conflict with names written by users. */ ! { "__ct ", &ctor_identifier, 1 }, ! { "__base_ctor ", &base_ctor_identifier, 1 }, ! { "__comp_ctor ", &complete_ctor_identifier, 1 }, ! { "__dt ", &dtor_identifier, 1 }, ! { "__comp_dtor ", &complete_dtor_identifier, 1 }, ! { "__base_dtor ", &base_dtor_identifier, 1 }, ! { "__deleting_dtor ", &deleting_dtor_identifier, 1 }, { IN_CHARGE_NAME, &in_charge_identifier, 0 }, { "nelts", &nelts_identifier, 0 }, { THIS_NAME, &this_identifier, 0 }, *************** cxx_init_decl_processing (void) *** 2950,2968 **** tree void_ftype; tree void_ftype_ptr; /* Create all the identifiers we need. */ initialize_predefined_identifiers (); - /* Fill in back-end hooks. */ - lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p; - /* Create the global variables. */ push_to_top_level (); current_function_decl = NULL_TREE; current_binding_level = NULL; /* Enter the global namespace. */ ! my_friendly_assert (global_namespace == NULL_TREE, 375); global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name, void_type_node); begin_scope (sk_namespace, global_namespace); --- 2866,2883 ---- tree void_ftype; tree void_ftype_ptr; + build_common_tree_nodes (flag_signed_char, false); + /* Create all the identifiers we need. */ initialize_predefined_identifiers (); /* Create the global variables. */ push_to_top_level (); current_function_decl = NULL_TREE; current_binding_level = NULL; /* Enter the global namespace. */ ! gcc_assert (global_namespace == NULL_TREE); global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name, void_type_node); begin_scope (sk_namespace, global_namespace); *************** cxx_init_decl_processing (void) *** 2978,2987 **** flag_no_inline = 1; } if (flag_inline_functions) ! { ! flag_inline_trees = 2; ! flag_inline_functions = 0; ! } /* Force minimum function alignment if using the least significant bit of function pointers to store the virtual bit. */ --- 2893,2899 ---- flag_no_inline = 1; } if (flag_inline_functions) ! flag_inline_trees = 2; /* Force minimum function alignment if using the least significant bit of function pointers to store the virtual bit. */ *************** cxx_init_decl_processing (void) *** 2992,2999 **** /* Initially, C. */ current_lang_name = lang_name_c; - build_common_tree_nodes (flag_signed_char); - error_mark_list = build_tree_list (error_mark_node, error_mark_node); TREE_TYPE (error_mark_list) = error_mark_node; --- 2904,2909 ---- *************** cxx_init_decl_processing (void) *** 3013,3022 **** java_char_type_node = record_builtin_java_type ("__java_char", -16); java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1); ! integer_two_node = build_int_2 (2, 0); ! TREE_TYPE (integer_two_node) = integer_type_node; ! integer_three_node = build_int_2 (3, 0); ! TREE_TYPE (integer_three_node) = integer_type_node; record_builtin_type (RID_BOOL, "bool", boolean_type_node); truthvalue_type_node = boolean_type_node; --- 2923,2930 ---- java_char_type_node = record_builtin_java_type ("__java_char", -16); java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1); ! integer_two_node = build_int_cst (NULL_TREE, 2); ! integer_three_node = build_int_cst (NULL_TREE, 3); record_builtin_type (RID_BOOL, "bool", boolean_type_node); truthvalue_type_node = boolean_type_node; *************** cxx_init_decl_processing (void) *** 3036,3042 **** void_ftype = build_function_type (void_type_node, void_list_node); void_ftype_ptr = build_function_type (void_type_node, tree_cons (NULL_TREE, ! ptr_type_node, void_list_node)); void_ftype_ptr = build_exception_variant (void_ftype_ptr, empty_except_spec); --- 2944,2950 ---- void_ftype = build_function_type (void_type_node, void_list_node); void_ftype_ptr = build_function_type (void_type_node, tree_cons (NULL_TREE, ! ptr_type_node, void_list_node)); void_ftype_ptr = build_exception_variant (void_ftype_ptr, empty_except_spec); *************** cxx_init_decl_processing (void) *** 3096,3108 **** bad_alloc_id = get_identifier ("bad_alloc"); bad_alloc_type_node = make_aggr_type (RECORD_TYPE); TYPE_CONTEXT (bad_alloc_type_node) = current_namespace; ! bad_alloc_decl = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node); DECL_CONTEXT (bad_alloc_decl) = current_namespace; TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl; pop_namespace (); ! ! ptr_ftype_sizetype = build_function_type (ptr_type_node, tree_cons (NULL_TREE, size_type_node, --- 3004,3016 ---- bad_alloc_id = get_identifier ("bad_alloc"); bad_alloc_type_node = make_aggr_type (RECORD_TYPE); TYPE_CONTEXT (bad_alloc_type_node) = current_namespace; ! bad_alloc_decl = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node); DECL_CONTEXT (bad_alloc_decl) = current_namespace; TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl; pop_namespace (); ! ! ptr_ftype_sizetype = build_function_type (ptr_type_node, tree_cons (NULL_TREE, size_type_node, *************** cxx_init_decl_processing (void) *** 3122,3128 **** /* Perform other language dependent initializations. */ init_class_processing (); - init_search_processing (); init_rtti_processing (); if (flag_exceptions) --- 3030,3035 ---- *************** cxx_init_decl_processing (void) *** 3135,3146 **** start_fname_decls (); /* Show we use EH for cleanups. */ ! using_eh_for_cleanups (); ! ! /* Maintain consistency. Perhaps we should just complain if they ! say -fwritable-strings? */ ! if (flag_writable_strings) ! flag_const_strings = 0; } /* Generate an initializer for a function naming variable from --- 3042,3049 ---- start_fname_decls (); /* Show we use EH for cleanups. */ ! if (flag_exceptions) ! using_eh_for_cleanups (); } /* Generate an initializer for a function naming variable from *************** cp_fname_init (const char* name, tree *t *** 3161,3177 **** domain = build_index_type (size_int (length)); init = build_string (length + 1, name); } ! type = build_qualified_type (char_type_node, TYPE_QUAL_CONST); type = build_cplus_array_type (type, domain); *type_p = type; ! if (init) TREE_TYPE (init) = type; else init = error_mark_node; ! return init; } --- 3064,3080 ---- domain = build_index_type (size_int (length)); init = build_string (length + 1, name); } ! type = build_qualified_type (char_type_node, TYPE_QUAL_CONST); type = build_cplus_array_type (type, domain); *type_p = type; ! if (init) TREE_TYPE (init) = type; else init = error_mark_node; ! return init; } *************** cp_fname_init (const char* name, tree *t *** 3179,3185 **** decl, NAME is the initialization string and TYPE_DEP indicates whether NAME depended on the type of the function. We make use of that to detect __PRETTY_FUNCTION__ inside a template fn. This is being done ! lazily at the point of first use, so we musn't push the decl now. */ static tree cp_make_fname_decl (tree id, int type_dep) --- 3082,3088 ---- decl, NAME is the initialization string and TYPE_DEP indicates whether NAME depended on the type of the function. We make use of that to detect __PRETTY_FUNCTION__ inside a template fn. This is being done ! lazily at the point of first use, so we mustn't push the decl now. */ static tree cp_make_fname_decl (tree id, int type_dep) *************** cp_make_fname_decl (tree id, int type_de *** 3190,3204 **** tree init = cp_fname_init (name, &type); tree decl = build_decl (VAR_DECL, id, type); /* As we're using pushdecl_with_scope, we must set the context. */ DECL_CONTEXT (decl) = current_function_decl; DECL_PRETTY_FUNCTION_P (decl) = type_dep; ! TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_INITIAL (decl) = init; ! TREE_USED (decl) = 1; if (current_function_decl) --- 3093,3110 ---- tree init = cp_fname_init (name, &type); tree decl = build_decl (VAR_DECL, id, type); + if (name) + free ((char *) name); + /* As we're using pushdecl_with_scope, we must set the context. */ DECL_CONTEXT (decl) = current_function_decl; DECL_PRETTY_FUNCTION_P (decl) = type_dep; ! TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_INITIAL (decl) = init; ! TREE_USED (decl) = 1; if (current_function_decl) *************** cp_make_fname_decl (tree id, int type_de *** 3211,3217 **** } else pushdecl_top_level_and_finish (decl, init); ! return decl; } --- 3117,3123 ---- } else pushdecl_top_level_and_finish (decl, init); ! return decl; } *************** static tree *** 3231,3237 **** builtin_function_1 (const char* name, tree type, tree context, ! int code, enum built_in_class class, const char* libname, tree attrs) --- 3137,3143 ---- builtin_function_1 (const char* name, tree type, tree context, ! enum built_in_function code, enum built_in_class class, const char* libname, tree attrs) *************** builtin_function_1 (const char* name, *** 3248,3254 **** function in the namespace. */ if (libname) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname)); - make_decl_rtl (decl, NULL); /* Warn if a function in the namespace for users is used without an occasion to consider it declared. */ --- 3154,3159 ---- *************** tree *** 3284,3290 **** builtin_function (const char* name, tree type, int code, ! enum built_in_class class, const char* libname, tree attrs) { --- 3189,3195 ---- builtin_function (const char* name, tree type, int code, ! enum built_in_class cl, const char* libname, tree attrs) { *************** builtin_function (const char* name, *** 3293,3304 **** if (name[0] != '_') { push_namespace (std_identifier); ! builtin_function_1 (name, type, std_node, code, class, libname, attrs); pop_namespace (); } return builtin_function_1 (name, type, NULL_TREE, code, ! class, libname, attrs); } /* Generate a FUNCTION_DECL with the typical flags for a runtime library --- 3198,3209 ---- if (name[0] != '_') { push_namespace (std_identifier); ! builtin_function_1 (name, type, std_node, code, cl, libname, attrs); pop_namespace (); } return builtin_function_1 (name, type, NULL_TREE, code, ! cl, libname, attrs); } /* Generate a FUNCTION_DECL with the typical flags for a runtime library *************** build_library_fn_1 (tree name, enum tree *** 3314,3319 **** --- 3219,3228 ---- TREE_NOTHROW (fn) = 1; SET_OVERLOADED_OPERATOR_CODE (fn, operator_code); SET_DECL_LANGUAGE (fn, lang_c); + /* Runtime library routines are, by definition, available in an + external shared object. */ + DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (fn) = 1; return fn; } *************** build_cp_library_fn (tree name, enum tre *** 3336,3342 **** TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type); DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace); SET_DECL_LANGUAGE (fn, lang_cplusplus); - set_mangled_name_for_decl (fn); return fn; } --- 3245,3250 ---- *************** fixup_anonymous_aggr (tree t) *** 3458,3470 **** if (CLASS_TYPE_P (type)) { if (TYPE_NEEDS_CONSTRUCTING (type)) ! cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate", field); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate", field); if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) ! cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate", field); } } --- 3366,3381 ---- if (CLASS_TYPE_P (type)) { if (TYPE_NEEDS_CONSTRUCTING (type)) ! cp_error_at ("member %q#D with constructor not allowed " ! "in anonymous aggregate", field); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) ! cp_error_at ("member %q#D with destructor not allowed " ! "in anonymous aggregate", field); if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) ! cp_error_at ("member %q#D with copy assignment operator " ! "not allowed in anonymous aggregate", field); } } *************** fixup_anonymous_aggr (tree t) *** 3477,3489 **** Returns the type declared; or NULL_TREE if none. */ tree ! check_tag_decl (tree declspecs) { ! int found_type = 0; ! int saw_friend = 0; ! int saw_typedef = 0; ! tree ob_modifier = NULL_TREE; ! tree link; /* If a class, struct, or enum type is declared by the DECLSPECS (i.e, if a class-specifier, enum-specifier, or non-typename elaborated-type-specifier appears in the DECLSPECS), --- 3388,3397 ---- Returns the type declared; or NULL_TREE if none. */ tree ! check_tag_decl (cp_decl_specifier_seq *declspecs) { ! int saw_friend = declspecs->specs[(int)ds_friend] != 0; ! int saw_typedef = declspecs->specs[(int)ds_typedef] != 0; /* If a class, struct, or enum type is declared by the DECLSPECS (i.e, if a class-specifier, enum-specifier, or non-typename elaborated-type-specifier appears in the DECLSPECS), *************** check_tag_decl (tree declspecs) *** 3491,3549 **** tree declared_type = NULL_TREE; bool error_p = false; ! for (link = declspecs; link; link = TREE_CHAIN (link)) { ! tree value = TREE_VALUE (link); ! ! if (TYPE_P (value) || TREE_CODE (value) == TYPE_DECL ! || (TREE_CODE (value) == IDENTIFIER_NODE ! && is_typename_at_global_scope (value))) ! { ! ++found_type; ! ! if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE) ! { ! if (! in_system_header) ! pedwarn ("redeclaration of C++ built-in type `%T'", value); ! return NULL_TREE; ! } ! ! if (TYPE_P (value) ! && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value)) ! || TREE_CODE (value) == ENUMERAL_TYPE)) ! { ! my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); ! declared_type = value; ! } ! } ! else if (value == ridpointers[(int) RID_TYPEDEF]) ! saw_typedef = 1; ! else if (value == ridpointers[(int) RID_FRIEND]) ! { ! if (current_class_type == NULL_TREE ! || current_scope () != current_class_type) ! ob_modifier = value; ! else ! saw_friend = 1; ! } ! else if (value == ridpointers[(int) RID_STATIC] ! || value == ridpointers[(int) RID_EXTERN] ! || value == ridpointers[(int) RID_AUTO] ! || value == ridpointers[(int) RID_REGISTER] ! || value == ridpointers[(int) RID_INLINE] ! || value == ridpointers[(int) RID_VIRTUAL] ! || value == ridpointers[(int) RID_CONST] ! || value == ridpointers[(int) RID_VOLATILE] ! || value == ridpointers[(int) RID_EXPLICIT] ! || value == ridpointers[(int) RID_THREAD]) ! ob_modifier = value; ! else if (value == error_mark_node) ! error_p = true; } ! if (found_type > 1) ! error ("multiple types in one declaration"); ! if (declared_type == NULL_TREE && ! saw_friend && !error_p) pedwarn ("declaration does not declare anything"); /* Check for an anonymous union. */ --- 3399,3422 ---- tree declared_type = NULL_TREE; bool error_p = false; ! if (declspecs->multiple_types_p) ! error ("multiple types in one declaration"); ! else if (declspecs->redefined_builtin_type) { ! if (!in_system_header) ! pedwarn ("redeclaration of C++ built-in type %qT", ! declspecs->redefined_builtin_type); ! return NULL_TREE; } ! if (declspecs->type ! && TYPE_P (declspecs->type) ! && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE ! && IS_AGGR_TYPE (declspecs->type)) ! || TREE_CODE (declspecs->type) == ENUMERAL_TYPE)) ! declared_type = declspecs->type; ! else if (declspecs->type == error_mark_node) ! error_p = true; if (declared_type == NULL_TREE && ! saw_friend && !error_p) pedwarn ("declaration does not declare anything"); /* Check for an anonymous union. */ *************** check_tag_decl (tree declspecs) *** 3574,3597 **** /* Anonymous unions are objects, so they can have specifiers. */; SET_ANON_AGGR_TYPE_P (declared_type); ! if (TREE_CODE (declared_type) != UNION_TYPE && pedantic && !in_system_header) pedwarn ("ISO C++ prohibits anonymous structs"); } ! else if (ob_modifier) { ! if (ob_modifier == ridpointers[(int) RID_INLINE] ! || ob_modifier == ridpointers[(int) RID_VIRTUAL]) ! error ("`%D' can only be specified for functions", ob_modifier); ! else if (ob_modifier == ridpointers[(int) RID_FRIEND]) ! error ("`%D' can only be specified inside a class", ob_modifier); ! else if (ob_modifier == ridpointers[(int) RID_EXPLICIT]) ! error ("`%D' can only be specified for constructors", ! ob_modifier); ! else ! error ("`%D' can only be specified for objects and functions", ! ob_modifier); } return declared_type; --- 3447,3479 ---- /* Anonymous unions are objects, so they can have specifiers. */; SET_ANON_AGGR_TYPE_P (declared_type); ! if (TREE_CODE (declared_type) != UNION_TYPE && pedantic && !in_system_header) pedwarn ("ISO C++ prohibits anonymous structs"); } ! else { ! if (declspecs->specs[(int)ds_inline] ! || declspecs->specs[(int)ds_virtual]) ! error ("%qs can only be specified for functions", ! declspecs->specs[(int)ds_inline] ! ? "inline" : "virtual"); ! else if (saw_friend ! && (!current_class_type ! || current_scope () != current_class_type)) ! error ("% can only be specified inside a class"); ! else if (declspecs->specs[(int)ds_explicit]) ! error ("% can only be specified for constructors"); ! else if (declspecs->storage_class) ! error ("a storage class can only be specified for objects " ! "and functions"); ! else if (declspecs->specs[(int)ds_const] ! || declspecs->specs[(int)ds_volatile] ! || declspecs->specs[(int)ds_restrict] ! || declspecs->specs[(int)ds_thread]) ! error ("qualifiers can only be specified for objects " ! "and functions"); } return declared_type; *************** check_tag_decl (tree declspecs) *** 3606,3623 **** Otherwise, it is an error. C++: may have to grok the declspecs to learn about static, ! complain for anonymous unions. Returns the TYPE declared -- or NULL_TREE if none. */ tree ! shadow_tag (tree declspecs) { tree t = check_tag_decl (declspecs); if (!t) return NULL_TREE; maybe_process_partial_specialization (t); /* This is where the variables in an anonymous union are --- 3488,3514 ---- Otherwise, it is an error. C++: may have to grok the declspecs to learn about static, ! complain for anonymous unions. Returns the TYPE declared -- or NULL_TREE if none. */ tree ! shadow_tag (cp_decl_specifier_seq *declspecs) { tree t = check_tag_decl (declspecs); if (!t) return NULL_TREE; + if (declspecs->attributes) + { + cp_warning_at ("attribute ignored in declaration of %q#T", t); + cp_warning_at ("attribute for %q#T must follow the %qs keyword", + t, + class_key_or_enum_as_string (t)); + + } + maybe_process_partial_specialization (t); /* This is where the variables in an anonymous union are *************** shadow_tag (tree declspecs) *** 3631,3638 **** if (TYPE_FIELDS (t)) { ! tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, ! NULL); finish_anon_union (decl); } } --- 3522,3529 ---- if (TYPE_FIELDS (t)) { ! tree decl = grokdeclarator (/*declarator=*/NULL, ! declspecs, NORMAL, 0, NULL); finish_anon_union (decl); } } *************** shadow_tag (tree declspecs) *** 3643,3657 **** /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree ! groktypename (tree typename) { ! tree specs, attrs; tree type; ! if (TREE_CODE (typename) != TREE_LIST) ! return typename; ! split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs); ! type = grokdeclarator (TREE_VALUE (typename), specs, ! TYPENAME, 0, &attrs); if (attrs) cplus_decl_attributes (&type, attrs, 0); return type; --- 3534,3547 ---- /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree ! groktypename (cp_decl_specifier_seq *type_specifiers, ! const cp_declarator *declarator) { ! tree attrs; tree type; ! attrs = type_specifiers->attributes; ! type_specifiers->attributes = NULL_TREE; ! type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs); if (attrs) cplus_decl_attributes (&type, attrs, 0); return type; *************** groktypename (tree typename) *** 3673,3693 **** grokfield and not through here. */ tree ! start_decl (tree declarator, ! tree declspecs, ! int initialized, ! tree attributes, ! tree prefix_attributes) { tree decl; tree type, tem; tree context; /* This should only be done once on the top most decl. */ if (have_extern_spec) { ! declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), ! declspecs); have_extern_spec = false; } --- 3563,3585 ---- grokfield and not through here. */ tree ! start_decl (const cp_declarator *declarator, ! cp_decl_specifier_seq *declspecs, ! int initialized, ! tree attributes, ! tree prefix_attributes, ! tree *pushed_scope_p) { tree decl; tree type, tem; tree context; + *pushed_scope_p = NULL_TREE; + /* This should only be done once on the top most decl. */ if (have_extern_spec) { ! declspecs->storage_class = sc_extern; have_extern_spec = false; } *************** start_decl (tree declarator, *** 3704,3730 **** deprecated_state = DEPRECATED_NORMAL; if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) ! return NULL_TREE; type = TREE_TYPE (decl); if (type == error_mark_node) ! return NULL_TREE; context = DECL_CONTEXT (decl); ! if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL ! && context != current_namespace && TREE_CODE (decl) == VAR_DECL) { ! /* When parsing the initializer, lookup should use the object's ! namespace. */ ! push_decl_namespace (context); } - /* We are only interested in class contexts, later. */ - if (context && TREE_CODE (context) == NAMESPACE_DECL) - context = NULL_TREE; - if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly --- 3596,3619 ---- deprecated_state = DEPRECATED_NORMAL; if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) ! return error_mark_node; type = TREE_TYPE (decl); if (type == error_mark_node) ! return error_mark_node; context = DECL_CONTEXT (decl); ! if (context) { ! *pushed_scope_p = push_scope (context); ! ! /* We are only interested in class contexts, later. */ ! if (TREE_CODE (context) == NAMESPACE_DECL) ! context = NULL_TREE; } if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly *************** start_decl (tree declarator, *** 3732,3743 **** switch (TREE_CODE (decl)) { case TYPE_DECL: ! error ("typedef `%D' is initialized (use __typeof__ instead)", decl); initialized = 0; break; case FUNCTION_DECL: ! error ("function `%#D' is initialized like a variable", decl); initialized = 0; break; --- 3621,3632 ---- switch (TREE_CODE (decl)) { case TYPE_DECL: ! error ("typedef %qD is initialized (use __typeof__ instead)", decl); initialized = 0; break; case FUNCTION_DECL: ! error ("function %q#D is initialized like a variable", decl); initialized = 0; break; *************** start_decl (tree declarator, *** 3749,3756 **** { if (! toplevel_bindings_p () && DECL_EXTERNAL (decl)) ! warning ("declaration of `%#D' has `extern' and is initialized", ! decl); DECL_EXTERNAL (decl) = 0; if (toplevel_bindings_p ()) TREE_STATIC (decl) = 1; --- 3638,3645 ---- { if (! toplevel_bindings_p () && DECL_EXTERNAL (decl)) ! warning ("declaration of %q#D has % and is initialized", ! decl); DECL_EXTERNAL (decl) = 0; if (toplevel_bindings_p ()) TREE_STATIC (decl) = 1; *************** start_decl (tree declarator, *** 3765,3805 **** cplus_decl_attributes (&decl, attributes, 0); /* If #pragma weak was used, mark the decl weak now. */ ! if (global_scope_p (current_binding_level)) ! maybe_apply_pragma_weak (decl); if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) ! warning ("%Jinline function '%D' given attribute noinline", decl, decl); if (context && COMPLETE_TYPE_P (complete_type (context))) { - push_nested_class (context); - if (TREE_CODE (decl) == VAR_DECL) { tree field = lookup_field (context, DECL_NAME (decl), 0, false); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) ! error ("`%#D' is not a static member of `%#T'", decl, context); else { if (DECL_CONTEXT (field) != context) { if (!same_type_p (DECL_CONTEXT (field), context)) ! pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl)); DECL_CONTEXT (decl) = DECL_CONTEXT (field); } /* Static data member are tricky; an in-class initialization still doesn't provide a definition, so the in-class declaration will have DECL_EXTERNAL set, but will have an initialization. Thus, duplicate_decls won't warn about this situation, and so we check here. */ if (DECL_INITIAL (decl) && DECL_INITIAL (field)) ! error ("duplicate initialization of %D", decl); if (duplicate_decls (decl, field)) decl = field; } --- 3654,3697 ---- cplus_decl_attributes (&decl, attributes, 0); /* If #pragma weak was used, mark the decl weak now. */ ! maybe_apply_pragma_weak (decl); if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) ! warning ("%Jinline function %qD given attribute noinline", decl, decl); if (context && COMPLETE_TYPE_P (complete_type (context))) { if (TREE_CODE (decl) == VAR_DECL) { tree field = lookup_field (context, DECL_NAME (decl), 0, false); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) ! error ("%q#D is not a static member of %q#T", decl, context); else { if (DECL_CONTEXT (field) != context) { if (!same_type_p (DECL_CONTEXT (field), context)) ! pedwarn ("ISO C++ does not permit %<%T::%D%> " ! "to be defined as %<%T::%D%>", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl)); DECL_CONTEXT (decl) = DECL_CONTEXT (field); } + if (processing_specialization + && template_class_depth (context) == 0 + && CLASSTYPE_TEMPLATE_SPECIALIZATION (context)) + error ("template header not allowed in member definition " + "of explicitly specialized class"); /* Static data member are tricky; an in-class initialization still doesn't provide a definition, so the in-class declaration will have DECL_EXTERNAL set, but will have an initialization. Thus, duplicate_decls won't warn about this situation, and so we check here. */ if (DECL_INITIAL (decl) && DECL_INITIAL (field)) ! error ("duplicate initialization of %qD", decl); if (duplicate_decls (decl, field)) decl = field; } *************** start_decl (tree declarator, *** 3807,3814 **** else { tree field = check_classfn (context, decl, ! processing_template_decl ! > template_class_depth (context)); if (field && duplicate_decls (decl, field)) decl = field; } --- 3699,3708 ---- else { tree field = check_classfn (context, decl, ! (processing_template_decl ! > template_class_depth (context)) ! ? current_template_parms ! : NULL_TREE); if (field && duplicate_decls (decl, field)) decl = field; } *************** start_decl (tree declarator, *** 3818,3824 **** if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) || CLASSTYPE_TEMPLATE_INSTANTIATION (context)) { ! SET_DECL_TEMPLATE_SPECIALIZATION (decl); /* [temp.expl.spec] An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. --- 3712,3723 ---- if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) || CLASSTYPE_TEMPLATE_INSTANTIATION (context)) { ! /* Do not mark DECL as an explicit specialization if it was ! not already marked as an instantiation; a declaration ! should never be marked as a specialization unless we know ! what template is being specialized. */ ! if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) ! SET_DECL_TEMPLATE_SPECIALIZATION (decl); /* [temp.expl.spec] An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. *************** start_decl (tree declarator, *** 3830,3837 **** } if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)) ! pedwarn ("declaration of `%#D' outside of class is not definition", ! decl); } /* Enter this declaration into the symbol table. */ --- 3729,3736 ---- } if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)) ! pedwarn ("declaration of %q#D outside of class is not definition", ! decl); } /* Enter this declaration into the symbol table. */ *************** start_decl_1 (tree decl) *** 3879,3893 **** ; /* A complete type is ok. */ else if (TREE_CODE (type) != ARRAY_TYPE) { ! error ("variable `%#D' has initializer but incomplete type", ! decl); initialized = 0; type = TREE_TYPE (decl) = error_mark_node; } else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type)))) { if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) ! error ("elements of array `%#D' have incomplete type", decl); /* else we already gave an error in start_decl. */ initialized = 0; } --- 3778,3791 ---- ; /* A complete type is ok. */ else if (TREE_CODE (type) != ARRAY_TYPE) { ! error ("variable %q#D has initializer but incomplete type", decl); initialized = 0; type = TREE_TYPE (decl) = error_mark_node; } else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type)))) { if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) ! error ("elements of array %q#D have incomplete type", decl); /* else we already gave an error in start_decl. */ initialized = 0; } *************** start_decl_1 (tree decl) *** 3903,3909 **** if ((! processing_template_decl || ! uses_template_parms (type)) && !COMPLETE_TYPE_P (complete_type (type))) { ! error ("aggregate `%#D' has incomplete type and cannot be defined", decl); /* Change the type so that assemble_variable will give DECL an rtl we can live with: (mem (const_int 0)). */ --- 3801,3807 ---- if ((! processing_template_decl || ! uses_template_parms (type)) && !COMPLETE_TYPE_P (complete_type (type))) { ! error ("aggregate %q#D has incomplete type and cannot be defined", decl); /* Change the type so that assemble_variable will give DECL an rtl we can live with: (mem (const_int 0)). */ *************** grok_reference_init (tree decl, tree typ *** 3953,3974 **** if ((DECL_LANG_SPECIFIC (decl) == 0 || DECL_IN_AGGR_P (decl) == 0) && ! DECL_THIS_EXTERN (decl)) ! error ("`%D' declared as reference but not initialized", decl); return NULL_TREE; } if (TREE_CODE (init) == CONSTRUCTOR) { ! error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl); return NULL_TREE; } if (TREE_CODE (init) == TREE_LIST) init = build_x_compound_expr_from_list (init, "initializer"); - if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) - init = convert_from_reference (init); - if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) /* Note: default conversion is only called in very special cases. */ --- 3851,3870 ---- if ((DECL_LANG_SPECIFIC (decl) == 0 || DECL_IN_AGGR_P (decl) == 0) && ! DECL_THIS_EXTERN (decl)) ! error ("%qD declared as reference but not initialized", decl); return NULL_TREE; } if (TREE_CODE (init) == CONSTRUCTOR) { ! error ("ISO C++ forbids use of initializer list to " ! "initialize reference %qD", decl); return NULL_TREE; } if (TREE_CODE (init) == TREE_LIST) init = build_x_compound_expr_from_list (init, "initializer"); if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) /* Note: default conversion is only called in very special cases. */ *************** grok_reference_init (tree decl, tree typ *** 3976,3983 **** /* Convert INIT to the reference type TYPE. This may involve the creation of a temporary, whose lifetime must be the same as that ! of the reference. If so, a DECL_STMT for the temporary will be ! added just after the DECL_STMT for DECL. That's why we don't set DECL_INITIAL for local references (instead assigning to them explicitly); we need to allow the temporary to be initialized first. */ --- 3872,3879 ---- /* Convert INIT to the reference type TYPE. This may involve the creation of a temporary, whose lifetime must be the same as that ! of the reference. If so, a DECL_EXPR for the temporary will be ! added just after the DECL_EXPR for DECL. That's why we don't set DECL_INITIAL for local references (instead assigning to them explicitly); we need to allow the temporary to be initialized first. */ *************** grok_reference_init (tree decl, tree typ *** 3987,3993 **** return NULL_TREE; else if (tmp == NULL_TREE) { ! error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init)); return NULL_TREE; } --- 3883,3889 ---- return NULL_TREE; else if (tmp == NULL_TREE) { ! error ("cannot initialize %qT from %qT", type, TREE_TYPE (init)); return NULL_TREE; } *************** maybe_deduce_size_from_array_init (tree *** 4016,4030 **** But let's leave it here to ease the eventual merge. */ int do_default = !DECL_EXTERNAL (decl); tree initializer = init ? init : DECL_INITIAL (decl); ! int failure = complete_array_type (type, initializer, do_default); if (failure == 1) ! error ("initializer fails to determine size of `%D'", decl); if (failure == 2) { if (do_default) ! error ("array size missing in `%D'", decl); /* If a `static' var's size isn't known, make it extern as well as static, so it does not get allocated. If it's not `static', then don't mark it extern; finish_incomplete_decl --- 3912,3927 ---- But let's leave it here to ease the eventual merge. */ int do_default = !DECL_EXTERNAL (decl); tree initializer = init ? init : DECL_INITIAL (decl); ! int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer, ! do_default); if (failure == 1) ! error ("initializer fails to determine size of %qD", decl); if (failure == 2) { if (do_default) ! error ("array size missing in %qD", decl); /* If a `static' var's size isn't known, make it extern as well as static, so it does not get allocated. If it's not `static', then don't mark it extern; finish_incomplete_decl *************** maybe_deduce_size_from_array_init (tree *** 4033,4042 **** DECL_EXTERNAL (decl) = 1; } ! if (pedantic && TYPE_DOMAIN (type) != NULL_TREE ! && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), ! integer_zero_node)) ! error ("zero-size array `%D'", decl); layout_decl (decl, 0); } --- 3930,3937 ---- DECL_EXTERNAL (decl) = 1; } ! if (failure == 3) ! error ("zero-size array %qD", decl); layout_decl (decl, 0); } *************** layout_var_decl (tree decl) *** 4060,4069 **** `extern X x' for some incomplete type `X'.) */ if (!DECL_EXTERNAL (decl)) complete_type (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); --- 3955,3964 ---- `extern X x' for some incomplete type `X'.) */ if (!DECL_EXTERNAL (decl)) complete_type (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); *************** layout_var_decl (tree decl) *** 4073,4079 **** /* An automatic variable with an incomplete type: that is an error. Don't talk about array types here, since we took care of that message in grokdeclarator. */ ! error ("storage size of `%D' isn't known", decl); TREE_TYPE (decl) = error_mark_node; } #if 0 --- 3968,3974 ---- /* An automatic variable with an incomplete type: that is an error. Don't talk about array types here, since we took care of that message in grokdeclarator. */ ! error ("storage size of %qD isn't known", decl); TREE_TYPE (decl) = error_mark_node; } #if 0 *************** layout_var_decl (tree decl) *** 4095,4101 **** if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) constant_expression_warning (DECL_SIZE (decl)); else ! error ("storage size of `%D' isn't constant", decl); } if (TREE_STATIC (decl) --- 3990,3996 ---- if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) constant_expression_warning (DECL_SIZE (decl)); else ! error ("storage size of %qD isn't constant", decl); } if (TREE_STATIC (decl) *************** maybe_commonize_var (tree decl) *** 4120,4126 **** && 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))) --- 4015,4021 ---- && 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))) *************** maybe_commonize_var (tree decl) *** 4150,4157 **** 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); ! warning ("%J you can work around this by removing the initializer", decl); } } --- 4045,4055 ---- be merged. */ TREE_PUBLIC (decl) = 0; DECL_COMMON (decl) = 0; ! cp_warning_at ("sorry: semantics of inline function static " ! "data %q#D are wrong (you'll wind up " ! "with multiple copies)", decl); ! warning ("%J you can work around this by removing " ! "the initializer", decl); } } *************** check_for_uninitialized_const_var (tree *** 4177,4183 **** && CP_TYPE_CONST_P (type) && !TYPE_NEEDS_CONSTRUCTING (type) && !DECL_INITIAL (decl)) ! error ("uninitialized const `%D'", decl); } /* FIELD is a FIELD_DECL or NULL. In the former case, the value --- 4075,4081 ---- && CP_TYPE_CONST_P (type) && !TYPE_NEEDS_CONSTRUCTING (type) && !DECL_INITIAL (decl)) ! error ("uninitialized const %qD", decl); } /* FIELD is a FIELD_DECL or NULL. In the former case, the value *************** reshape_init_array (tree elt_type, tree *** 4210,4222 **** tree *initp, tree new_init) { bool sized_array_p = (max_index != NULL_TREE); ! HOST_WIDE_INT max_index_cst = 0; ! HOST_WIDE_INT index; if (sized_array_p) ! /* HWI is either 32bit or 64bit, so it must be enough to represent the ! array size. */ ! max_index_cst = tree_low_cst (max_index, 1); /* Loop until there are no more initializers. */ for (index = 0; --- 4108,4125 ---- tree *initp, tree new_init) { bool sized_array_p = (max_index != NULL_TREE); ! unsigned HOST_WIDE_INT max_index_cst = 0; ! unsigned HOST_WIDE_INT index; if (sized_array_p) ! { ! if (host_integerp (max_index, 1)) ! max_index_cst = tree_low_cst (max_index, 1); ! /* sizetype is sign extended, not zero extended. */ ! else ! max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index), ! 1); ! } /* Loop until there are no more initializers. */ for (index = 0; *************** reshape_init_array (tree elt_type, tree *** 4237,4260 **** /* Handle array designated initializers (GNU extension). */ if (TREE_CODE (designated_index) == IDENTIFIER_NODE) { ! error ("name `%D' used in a GNU-style designated " ! "initializer for an array", designated_index); TREE_PURPOSE (element_init) = NULL_TREE; } else ! { ! if (TREE_CODE (designated_index) != INTEGER_CST) ! abort (); ! if (sized_array_p ! && tree_int_cst_lt (max_index, designated_index)) ! { ! error ("Designated initializer `%E' larger than array " ! "size", designated_index); ! TREE_PURPOSE (element_init) = NULL_TREE; ! } ! else ! index = tree_low_cst (designated_index, 1); ! } } } --- 4140,4151 ---- /* Handle array designated initializers (GNU extension). */ if (TREE_CODE (designated_index) == IDENTIFIER_NODE) { ! error ("name %qD used in a GNU-style designated " ! "initializer for an array", designated_index); TREE_PURPOSE (element_init) = NULL_TREE; } else ! gcc_unreachable (); } } *************** reshape_init_array (tree elt_type, tree *** 4267,4273 **** *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 }; --- 4158,4164 ---- *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 }; *************** reshape_init (tree type, tree *initp) *** 4284,4302 **** 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); ! my_friendly_assert (old_init_value, 20030723); /* 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_TYPE (old_init_value) == NULL_TREE ! && TREE_HAS_CONSTRUCTOR (old_init_value)) { *initp = TREE_CHAIN (old_init); TREE_CHAIN (old_init) = NULL_TREE; --- 4175,4193 ---- tree old_init_value; tree new_init; bool brace_enclosed_p; + bool string_init_p; old_init = *initp; old_init_value = (TREE_CODE (*initp) == TREE_LIST ? TREE_VALUE (*initp) : old_init); ! gcc_assert (old_init_value); /* 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 ! && BRACE_ENCLOSED_INITIALIZER_P (old_init_value)) { *initp = TREE_CHAIN (old_init); TREE_CHAIN (old_init) = NULL_TREE; *************** reshape_init (tree type, tree *initp) *** 4320,4333 **** 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; } --- 4211,4224 ---- brace-enclosed initializer. */ if (brace_enclosed_p) { ! error ("brace-enclosed initializer used to initialize %qT", type); if (TREE_CODE (old_init) == TREE_LIST) TREE_VALUE (old_init) = error_mark_node; else old_init = error_mark_node; } ! return old_init; } *************** reshape_init (tree type, tree *initp) *** 4348,4353 **** --- 4239,4245 ---- return old_init; } + string_init_p = false; if (TREE_CODE (old_init_value) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) *************** reshape_init (tree type, tree *initp) *** 4362,4373 **** /* 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); ! TREE_HAS_CONSTRUCTOR (new_init) = 1; if (CLASS_TYPE_P (type)) { --- 4254,4265 ---- /* Move past the initializer. */ *initp = TREE_CHAIN (old_init); TREE_CHAIN (old_init) = NULL_TREE; + string_init_p = true; } else { ! /* Build a CONSTRUCTOR to hold the contents of the aggregate. */ ! new_init = build_constructor (NULL_TREE, NULL_TREE); if (CLASS_TYPE_P (type)) { *************** reshape_init (tree type, tree *initp) *** 4378,4391 **** 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); return error_mark_node; } } --- 4270,4282 ---- 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 %qT must be brace-enclosed", type); return error_mark_node; } } *************** reshape_init (tree type, tree *initp) *** 4405,4411 **** 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) --- 4296,4302 ---- field = lookup_field_1 (type, TREE_PURPOSE (*initp), /*want_type=*/false); if (!field || TREE_CODE (field) != FIELD_DECL) ! error ("%qT has no non-static data member named %qD", type, TREE_PURPOSE (*initp)); } if (!field) *************** reshape_init (tree type, tree *initp) *** 4416,4422 **** return error_mark_node; 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 --- 4307,4313 ---- return error_mark_node; 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 *************** reshape_init (tree type, tree *initp) *** 4427,4446 **** } } } ! else if ((TREE_CODE (type) == ARRAY_TYPE)|| (TREE_CODE (type) == VECTOR_TYPE)) { ! tree max_index; - /* If the bound of the array is known, take no more initializers - than are allowed. */ - max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE)) - ? array_type_nelts (type) : NULL_TREE); if (!reshape_init_array (TREE_TYPE (type), max_index, initp, new_init)) return error_mark_node; } else ! abort (); /* The initializers were placed in reverse order in the CONSTRUCTOR. */ --- 4318,4351 ---- } } } ! else if (TREE_CODE (type) == ARRAY_TYPE ! || TREE_CODE (type) == VECTOR_TYPE) { ! /* If the bound of the array is known, take no more initializers ! than are allowed. */ ! tree max_index = NULL_TREE; ! if (TREE_CODE (type) == ARRAY_TYPE) ! { ! if (TYPE_DOMAIN (type)) ! max_index = array_type_nelts (type); ! } ! else ! { ! /* For a vector, the representation type is a struct ! containing a single member which is an array of the ! appropriate size. */ ! tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type); ! if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype)))) ! max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS ! (rtype))); ! } if (!reshape_init_array (TREE_TYPE (type), max_index, initp, new_init)) return error_mark_node; } else ! gcc_unreachable (); /* The initializers were placed in reverse order in the CONSTRUCTOR. */ *************** reshape_init (tree type, tree *initp) *** 4450,4459 **** 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; } --- 4355,4369 ---- new_init = build_tree_list (TREE_PURPOSE (old_init), new_init); } ! /* If there are more initializers than necessary, issue a ! diagnostic. */ ! if (*initp) ! { ! if (brace_enclosed_p) ! error ("too many initializers for %qT", type); ! else if (warn_missing_braces && !string_init_p) ! warning ("missing braces around initializer"); ! } return new_init; } *************** check_initializer (tree decl, tree init, *** 4488,4533 **** 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) { ! my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148); DECL_INITIAL (decl) = init; ! my_friendly_assert (init != NULL_TREE, 149); init = NULL_TREE; } else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE) init = grok_reference_init (decl, type, init, cleanup); else if (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. */ --- 4398,4444 ---- 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 %qD 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 %q#D have incomplete type", decl); init = NULL_TREE; } else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type)) { ! error ("%qD has incomplete type", decl); TREE_TYPE (decl) = error_mark_node; init = NULL_TREE; } if (TREE_CODE (decl) == CONST_DECL) { ! gcc_assert (TREE_CODE (decl) != REFERENCE_TYPE); DECL_INITIAL (decl) = init; ! gcc_assert (init != NULL_TREE); init = NULL_TREE; } else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE) init = grok_reference_init (decl, type, init, cleanup); else if (init) { ! if (TREE_CODE (init) == CONSTRUCTOR ! && BRACE_ENCLOSED_INITIALIZER_P (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. */ *************** check_initializer (tree decl, tree init, *** 4545,4563 **** 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) 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); init = error_mark_node; } --- 4456,4473 ---- array size from the initializer. */ maybe_deduce_size_from_array_init (decl, init); type = TREE_TYPE (decl); if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) { if (TREE_CODE (type) == ARRAY_TYPE) goto initialize_aggr; else if (TREE_CODE (init) == CONSTRUCTOR ! && BRACE_ENCLOSED_INITIALIZER_P (init)) { if (TYPE_NON_AGGREGATE_CLASS (type)) { ! error ("%qD must be initialized by constructor, " ! "not by %<{...}%>", decl); init = error_mark_node; } *************** check_initializer (tree decl, tree init, *** 4588,4593 **** --- 4498,4509 ---- if (TREE_CODE (init) != TREE_VEC) { init_code = store_init_value (decl, init); + if (pedantic && TREE_CODE (type) == ARRAY_TYPE + && DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST + && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl))) + warning ("array %qD initialized by parenthesized string literal %qE", + decl, DECL_INITIAL (decl)); init = NULL; } } *************** check_initializer (tree decl, tree init, *** 4601,4610 **** tree core_type = strip_array_types (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); check_for_uninitialized_const_var (decl); } --- 4517,4525 ---- tree core_type = strip_array_types (type); if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)) ! error ("structure %qD with uninitialized const members", decl); if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)) ! error ("structure %qD with uninitialized reference members", decl); check_for_uninitialized_const_var (decl); } *************** check_initializer (tree decl, tree init, *** 4612,4618 **** check_for_uninitialized_const_var (decl); if (init && init != error_mark_node) ! init_code = build (INIT_EXPR, type, decl, init); return init_code; } --- 4527,4533 ---- check_for_uninitialized_const_var (decl); if (init && init != error_mark_node) ! init_code = build2 (INIT_EXPR, type, decl, init); return init_code; } *************** make_rtl_for_nonlocal_decl (tree decl, t *** 4625,4634 **** int toplev = toplevel_bindings_p (); int defer_p; /* Handle non-variables up front. */ if (TREE_CODE (decl) != VAR_DECL) { ! rest_of_decl_compilation (decl, asmspec, toplev, at_eof); return; } --- 4540,4569 ---- int toplev = toplevel_bindings_p (); int defer_p; + /* Set the DECL_ASSEMBLER_NAME for the object. */ + if (asmspec) + { + /* The `register' keyword, when used together with an + asm-specification, indicates that the variable should be + placed in a particular register. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) + { + change_decl_assembler_name (decl, get_identifier (asmspec)); + DECL_HARD_REGISTER (decl) = 1; + } + else + { + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) + set_builtin_user_assembler_name (decl, asmspec); + set_user_assembler_name (decl, asmspec); + } + } + /* Handle non-variables up front. */ if (TREE_CODE (decl) != VAR_DECL) { ! rest_of_decl_compilation (decl, toplev, at_eof); return; } *************** make_rtl_for_nonlocal_decl (tree decl, t *** 4636,4657 **** member. */ if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl)) { ! my_friendly_assert (TREE_STATIC (decl), 19990828); /* An in-class declaration of a static data member should be external; it is only a declaration, and not a definition. */ if (init == NULL_TREE) ! my_friendly_assert (DECL_EXTERNAL (decl), 20000723); ! } ! ! /* Set the DECL_ASSEMBLER_NAME for the variable. */ ! if (asmspec) ! { ! change_decl_assembler_name (decl, get_identifier (asmspec)); ! /* The `register' keyword, when used together with an ! asm-specification, indicates that the variable should be ! placed in a particular register. */ ! if (DECL_REGISTER (decl)) ! DECL_C_HARD_REGISTER (decl) = 1; } /* We don't create any RTL for local variables. */ --- 4571,4581 ---- member. */ if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl)) { ! gcc_assert (TREE_STATIC (decl)); /* An in-class declaration of a static data member should be external; it is only a declaration, and not a definition. */ if (init == NULL_TREE) ! gcc_assert (DECL_EXTERNAL (decl)); } /* We don't create any RTL for local variables. */ *************** make_rtl_for_nonlocal_decl (tree decl, t *** 4659,4665 **** return; /* We defer emission of local statics until the corresponding ! DECL_STMT is expanded. */ defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl); /* We try to defer namespace-scope static constants so that they are --- 4583,4589 ---- return; /* We defer emission of local statics until the corresponding ! DECL_EXPR is expanded. */ defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl); /* We try to defer namespace-scope static constants so that they are *************** make_rtl_for_nonlocal_decl (tree decl, t *** 4674,4701 **** { /* Fool with the linkage of static consts according to #pragma interface. */ ! if (!interface_unknown && !TREE_PUBLIC (decl)) { TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = interface_only; } defer_p = 1; } /* Likewise for template instantiations. */ ! else if (DECL_COMDAT (decl)) defer_p = 1; - /* If we're deferring the variable, we only need to make RTL if - there's an ASMSPEC. Otherwise, we'll lazily create it later when - we need it. (There's no way to lazily create RTL for things that - have assembly specs because the information about the specifier - isn't stored in the tree, yet) */ - if (defer_p && asmspec) - make_decl_rtl (decl, asmspec); /* If we're not deferring, go ahead and assemble the variable. */ ! else if (!defer_p) ! rest_of_decl_compilation (decl, asmspec, toplev, at_eof); } /* Generate code to initialize DECL (a local variable). */ --- 4598,4620 ---- { /* Fool with the linkage of static consts according to #pragma interface. */ ! struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename)); ! if (!finfo->interface_unknown && !TREE_PUBLIC (decl)) { TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = finfo->interface_only; } defer_p = 1; } /* Likewise for template instantiations. */ ! else if (DECL_LANG_SPECIFIC (decl) ! && DECL_IMPLICIT_INSTANTIATION (decl)) defer_p = 1; /* If we're not deferring, go ahead and assemble the variable. */ ! if (!defer_p) ! rest_of_decl_compilation (decl, toplev, at_eof); } /* Generate code to initialize DECL (a local variable). */ *************** initialize_local_var (tree decl, tree in *** 4706,4715 **** tree type = TREE_TYPE (decl); tree cleanup; ! 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) { --- 4625,4633 ---- tree type = TREE_TYPE (decl); tree cleanup; ! gcc_assert (TREE_CODE (decl) == VAR_DECL ! || TREE_CODE (decl) == RESULT_DECL); ! gcc_assert (!TREE_STATIC (decl)); if (DECL_SIZE (decl) == NULL_TREE) { *************** initialize_local_var (tree decl, tree in *** 4730,4736 **** { 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 (init); --- 4648,4654 ---- { int saved_stmts_are_full_exprs_p; ! gcc_assert (building_stmt_tree ()); saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 1; finish_expr_stmt (init); *************** initialize_local_var (tree decl, tree in *** 4759,4764 **** --- 4677,4698 ---- finish_decl_cleanup (decl, cleanup); } + /* DECL is a VAR_DECL for a compiler-generated variable with static + storage duration (like a virtual table) whose initializer is a + compile-time constant. Initialize the variable and provide it to + the back end. */ + + void + initialize_artificial_var (tree decl, tree init) + { + DECL_INITIAL (decl) = build_constructor (NULL_TREE, init); + DECL_INITIALIZED_P (decl) = 1; + determine_visibility (decl); + layout_var_decl (decl); + maybe_commonize_var (decl); + make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL); + } + /* Finish processing of a declaration; install its line number and initial value. If the length of an array type is not known before, *************** cp_finish_decl (tree decl, tree init, tr *** 4789,4795 **** return; } ! my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619); /* Assume no cleanup is required. */ cleanup = NULL_TREE; --- 4723,4729 ---- return; } ! gcc_assert (TREE_CODE (decl) != RESULT_DECL); /* Assume no cleanup is required. */ cleanup = NULL_TREE; *************** cp_finish_decl (tree decl, tree init, tr *** 4797,4809 **** /* If a name was specified, get the string. */ 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); if (init && TREE_CODE (init) == NAMESPACE_DECL) { ! error ("cannot initialize `%D' to namespace `%D'", ! decl, init); init = NULL_TREE; } --- 4731,4742 ---- /* If a name was specified, get the string. */ 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); if (init && TREE_CODE (init) == NAMESPACE_DECL) { ! error ("cannot initialize %qD to namespace %qD", decl, init); init = NULL_TREE; } *************** cp_finish_decl (tree decl, tree init, tr *** 4813,4841 **** && (DECL_INITIAL (decl) || init)) DECL_INITIALIZED_IN_CLASS_P (decl) = 1; - if (TREE_CODE (decl) == VAR_DECL - && DECL_CONTEXT (decl) - && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL - && DECL_CONTEXT (decl) != current_namespace - && init) - { - /* Leave the namespace of the object. */ - pop_decl_namespace (); - } - type = TREE_TYPE (decl); if (type == error_mark_node) ! goto finish_end0; ! ! if (TYPE_HAS_MUTABLE_P (type)) ! TREE_READONLY (decl) = 0; if (processing_template_decl) { /* Add this declaration to the statement-tree. */ if (at_function_scope_p ()) ! add_decl_stmt (decl); if (init && DECL_INITIAL (decl)) DECL_INITIAL (decl) = init; --- 4746,4761 ---- && (DECL_INITIAL (decl) || init)) DECL_INITIALIZED_IN_CLASS_P (decl) = 1; type = TREE_TYPE (decl); if (type == error_mark_node) ! goto finish_end; if (processing_template_decl) { /* Add this declaration to the statement-tree. */ if (at_function_scope_p ()) ! add_decl_expr (decl); if (init && DECL_INITIAL (decl)) DECL_INITIAL (decl) = init; *************** cp_finish_decl (tree decl, tree init, tr *** 4843,4853 **** && !DECL_PRETTY_FUNCTION_P (decl) && !dependent_type_p (TREE_TYPE (decl))) maybe_deduce_size_from_array_init (decl, init); ! goto finish_end0; } /* Parameters are handled by store_parm_decls, not cp_finish_decl. */ ! my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828); /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) --- 4763,4774 ---- && !DECL_PRETTY_FUNCTION_P (decl) && !dependent_type_p (TREE_TYPE (decl))) maybe_deduce_size_from_array_init (decl, init); ! ! goto finish_end; } /* Parameters are handled by store_parm_decls, not cp_finish_decl. */ ! gcc_assert (TREE_CODE (decl) != PARM_DECL); /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) *************** cp_finish_decl (tree decl, tree init, tr *** 4856,4862 **** && IS_AGGR_TYPE (type) && DECL_NAME (decl)) { if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) ! warning ("shadowing previous type declaration of `%#D'", decl); set_identifier_type_value (DECL_NAME (decl), decl); } --- 4777,4783 ---- && IS_AGGR_TYPE (type) && DECL_NAME (decl)) { if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) ! warning ("shadowing previous type declaration of %q#D", decl); set_identifier_type_value (DECL_NAME (decl), decl); } *************** cp_finish_decl (tree decl, tree init, tr *** 4867,4891 **** && !COMPLETE_TYPE_P (TREE_TYPE (decl))) TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; ! rest_of_decl_compilation (decl, NULL, ! DECL_CONTEXT (decl) == NULL_TREE, at_eof); goto finish_end; } if (TREE_CODE (decl) != FUNCTION_DECL) ttype = target_type (type); ! ! /* Currently, GNU C++ puts constants in text space, making them ! impossible to initialize. In the future, one would hope for ! an operating system which understood the difference between ! initialization and the running of a program. */ ! if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)) { was_readonly = 1; ! if (TYPE_NEEDS_CONSTRUCTING (type) ! || TREE_CODE (type) == REFERENCE_TYPE) ! TREE_READONLY (decl) = 0; } if (TREE_CODE (decl) == VAR_DECL) --- 4788,4809 ---- && !COMPLETE_TYPE_P (TREE_TYPE (decl))) TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; ! rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE, ! at_eof); goto finish_end; } if (TREE_CODE (decl) != FUNCTION_DECL) ttype = target_type (type); ! ! /* A reference will be modified here, as it is initialized. */ ! if (! DECL_EXTERNAL (decl) ! && TREE_READONLY (decl) ! && TREE_CODE (type) == REFERENCE_TYPE) { was_readonly = 1; ! TREE_READONLY (decl) = 0; } if (TREE_CODE (decl) == VAR_DECL) *************** cp_finish_decl (tree decl, tree init, tr *** 4893,4899 **** /* 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. */ --- 4811,4817 ---- /* 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 ("%qD cannot be thread-local because it has non-POD type %qT", decl, TREE_TYPE (decl)); /* Convert the initializer to the type of DECL, if we have not already initialized DECL. */ *************** cp_finish_decl (tree decl, tree init, tr *** 4908,4925 **** /* 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 --- 4826,4843 ---- /* Thread-local storage cannot be dynamically initialized. */ if (DECL_THREAD_LOCAL (decl) && init) { ! error ("%qD 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 *************** cp_finish_decl (tree decl, tree init, tr *** 4936,4941 **** --- 4854,4862 ---- the class specifier. */ if (!DECL_EXTERNAL (decl)) var_definition_p = true; + /* The variable is being defined, so determine its + visibility. */ + determine_visibility (decl); } /* If the variable has an array type, lay out the type, even if there is no initializer. It is valid to index through the *************** cp_finish_decl (tree decl, tree init, tr *** 4946,4955 **** } /* Add this declaration to the statement-tree. This needs to happen ! after the call to check_initializer so that the DECL_STMT for a ! reference temp is added before the DECL_STMT for the reference itself. */ if (at_function_scope_p ()) ! add_decl_stmt (decl); if (TREE_CODE (decl) == VAR_DECL) layout_var_decl (decl); --- 4867,4876 ---- } /* Add this declaration to the statement-tree. This needs to happen ! after the call to check_initializer so that the DECL_EXPR for a ! reference temp is added before the DECL_EXPR for the reference itself. */ if (at_function_scope_p ()) ! add_decl_expr (decl); if (TREE_CODE (decl) == VAR_DECL) layout_var_decl (decl); *************** cp_finish_decl (tree decl, tree init, tr *** 4964,4988 **** make_rtl_for_nonlocal_decl (decl, init, asmspec); if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) ! abstract_virtuals_error (decl, ! strip_array_types (TREE_TYPE (type))); ! else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) ! { ! /* If it's either a pointer or an array type, strip through all ! of them but the last one. If the last is an array type, issue ! an error if the element type is abstract. */ ! while (POINTER_TYPE_P (TREE_TYPE (type)) ! || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE) ! type = TREE_TYPE (type); ! if (TREE_CODE (type) == ARRAY_TYPE) ! abstract_virtuals_error (decl, TREE_TYPE (type)); ! } else abstract_virtuals_error (decl, type); ! if (TREE_CODE (decl) == FUNCTION_DECL || TREE_TYPE (decl) == error_mark_node) /* No initialization required. */ ; --- 4885,4900 ---- make_rtl_for_nonlocal_decl (decl, init, asmspec); + /* Check for abstractness of the type. Notice that there is no + need to strip array types here since the check for those types + is already done within create_array_type_for_decl. */ if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) ! abstract_virtuals_error (decl, TREE_TYPE (type)); else abstract_virtuals_error (decl, type); ! if (TREE_CODE (decl) == FUNCTION_DECL || TREE_TYPE (decl) == error_mark_node) /* No initialization required. */ ; *************** cp_finish_decl (tree decl, tree init, tr *** 4998,5005 **** /* A variable definition. */ if (DECL_FUNCTION_SCOPE_P (decl)) { - /* This is a local declaration. */ - maybe_inject_for_scope_var (decl); /* Initialize the local variable. */ if (processing_template_decl) { --- 4910,4915 ---- *************** cp_finish_decl (tree decl, tree init, tr *** 5009,5017 **** else if (!TREE_STATIC (decl)) initialize_local_var (decl, init); } ! /* If a variable is defined, and then a subsequent ! definintion with external linkage is encountered, we will get here twice for the same variable. We want to avoid calling expand_static_init more than once. For variables that are not static data members, we can call --- 4919,4927 ---- else if (!TREE_STATIC (decl)) initialize_local_var (decl, init); } ! /* If a variable is defined, and then a subsequent ! definition with external linkage is encountered, we will get here twice for the same variable. We want to avoid calling expand_static_init more than once. For variables that are not static data members, we can call *************** cp_finish_decl (tree decl, tree init, tr *** 5020,5052 **** member, so this issue does not arise in that case. */ if (var_definition_p && TREE_STATIC (decl)) expand_static_init (decl, init); ! } ! finish_end0: ! ! /* Undo call to `pushclass' that was done in `start_decl' ! due to initialization of qualified member variable. ! I.e., Foo::x = 10; */ ! { ! tree context = CP_DECL_CONTEXT (decl); ! if (context ! && TYPE_P (context) ! && (TREE_CODE (decl) == VAR_DECL ! /* We also have a pushclass done that we need to undo here ! if we're at top level and declare a method. */ ! || TREE_CODE (decl) == FUNCTION_DECL) ! /* If size hasn't been set, we're still defining it, ! and therefore inside the class body; don't pop ! the binding level.. */ ! && COMPLETE_TYPE_P (context) ! && context == current_class_type) ! pop_nested_class (); ! } } /* If a CLEANUP_STMT was created to destroy a temporary bound to a reference, insert it in the statement-tree now. */ if (cleanup) ! add_stmt (cleanup); finish_end: --- 4930,4942 ---- member, so this issue does not arise in that case. */ if (var_definition_p && TREE_STATIC (decl)) expand_static_init (decl, init); ! } } /* If a CLEANUP_STMT was created to destroy a temporary bound to a reference, insert it in the statement-tree now. */ if (cleanup) ! push_cleanup (decl, cleanup, false); finish_end: *************** cp_finish_decl (tree decl, tree init, tr *** 5055,5061 **** /* If this was marked 'used', be sure it will be output. */ if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) ! mark_referenced (DECL_ASSEMBLER_NAME (decl)); } /* This is here for a midend callback from c-common.c. */ --- 4945,4951 ---- /* If this was marked 'used', be sure it will be output. */ if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) ! mark_decl_referenced (decl); } /* This is here for a midend callback from c-common.c. */ *************** declare_global_var (tree name, tree type *** 5083,5089 **** TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1; ! pushdecl (decl); cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0); pop_from_top_level (); --- 4973,4983 ---- TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1; ! /* If the user has explicitly declared this variable (perhaps ! because the code we are compiling is part of a low-level runtime ! library), then it is possible that our declaration will be merged ! with theirs by pushdecl. */ ! decl = pushdecl (decl); cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0); pop_from_top_level (); *************** static GTY(()) int start_cleanup_cnt; *** 5178,5185 **** static tree start_cleanup_fn (void) { - int old_interface_only = interface_only; - int old_interface_unknown = interface_unknown; char name[32]; tree parmtypes; tree fntype; --- 5072,5077 ---- *************** start_cleanup_fn (void) *** 5190,5198 **** /* No need to mangle this. */ push_lang_context (lang_name_c); - interface_only = 0; - interface_unknown = 1; - /* Build the parameter-types. */ parmtypes = void_list_node; /* Functions passed to __cxa_atexit take an additional parameter. --- 5082,5087 ---- *************** start_cleanup_fn (void) *** 5230,5239 **** } pushdecl (fndecl); ! start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED); ! ! interface_unknown = old_interface_unknown; ! interface_only = old_interface_only; pop_lang_context (); --- 5119,5125 ---- } pushdecl (fndecl); ! start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED); pop_lang_context (); *************** end_cleanup_fn (void) *** 5253,5259 **** /* Generate code to handle the destruction of DECL, an object with static storage duration. */ ! void register_dtor_fn (tree decl) { tree cleanup; --- 5139,5145 ---- /* Generate code to handle the destruction of DECL, an object with static storage duration. */ ! tree register_dtor_fn (tree decl) { tree cleanup; *************** register_dtor_fn (tree decl) *** 5262,5268 **** tree fcall; if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) ! return; /* Call build_cleanup before we enter the anonymous function so that any access checks will be done relative to the current scope, --- 5148,5154 ---- tree fcall; if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) ! return void_zero_node; /* Call build_cleanup before we enter the anonymous function so that any access checks will be done relative to the current scope, *************** register_dtor_fn (tree decl) *** 5276,5288 **** to the original function, rather than the anonymous one. That will make the back-end think that nested functions are in use, which causes confusion. */ ! push_deferring_access_checks (dk_no_check); fcall = build_cleanup (decl); pop_deferring_access_checks (); /* Create the body of the anonymous function. */ ! compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); finish_expr_stmt (fcall); finish_compound_stmt (compound_stmt); end_cleanup_fn (); --- 5162,5174 ---- to the original function, rather than the anonymous one. That will make the back-end think that nested functions are in use, which causes confusion. */ ! push_deferring_access_checks (dk_no_check); fcall = build_cleanup (decl); pop_deferring_access_checks (); /* Create the body of the anonymous function. */ ! compound_stmt = begin_compound_stmt (BCS_FN_BODY); finish_expr_stmt (fcall); finish_compound_stmt (compound_stmt); end_cleanup_fn (); *************** register_dtor_fn (tree decl) *** 5293,5299 **** cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); if (flag_use_cxa_atexit) { ! args = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0), NULL_TREE); args = tree_cons (NULL_TREE, null_pointer_node, args); --- 5179,5185 ---- cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); if (flag_use_cxa_atexit) { ! args = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0), NULL_TREE); args = tree_cons (NULL_TREE, null_pointer_node, args); *************** register_dtor_fn (tree decl) *** 5301,5307 **** } else args = tree_cons (NULL_TREE, cleanup, NULL_TREE); ! finish_expr_stmt (build_function_call (get_atexit_node (), args)); } /* DECL is a VAR_DECL with static storage duration. INIT, if present, --- 5187,5193 ---- } else args = tree_cons (NULL_TREE, cleanup, NULL_TREE); ! return build_function_call (get_atexit_node (), args); } /* DECL is a VAR_DECL with static storage duration. INIT, if present, *************** register_dtor_fn (tree decl) *** 5311,5414 **** static void expand_static_init (tree decl, tree init) { ! 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; ! if (! toplevel_bindings_p ()) { /* Emit code to perform this initialization but once. */ ! tree if_stmt; ! tree then_clause; ! tree assignment; ! tree guard; ! tree guard_init; /* Emit code to perform this initialization but once. This code looks like: ! static int guard = 0; ! if (!guard) { ! // Do initialization. ! guard = 1; ! // Register variable for destruction at end of program. } ! Note that the `temp' variable is only set to 1 *after* the initialization is complete. This ensures that an exception, thrown during the construction, will cause the variable to reinitialized when we pass through this code again, as per: [stmt.dcl] ! If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. ! In theory, this process should be thread-safe, too; multiple ! threads should not be able to initialize the variable more ! than once. We don't yet attempt to ensure thread-safety. */ /* Create the guard variable. */ guard = get_guard (decl); ! /* Begin the conditional initialization. */ ! if_stmt = begin_if_stmt (); ! finish_if_stmt_cond (get_guard_cond (guard), if_stmt); ! then_clause = begin_compound_stmt (/*has_no_scope=*/false); ! /* Do the initialization itself. */ ! 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, ! we want to make sure TEMP is set to 1 even if a temporary ! constructed during the initialization throws an exception ! when it is destroyed. So, we combine the initialization and ! the assignment to TEMP into a single expression, ensuring ! that when we call finish_expr_stmt the cleanups will not be ! run until after TEMP is set to 1. */ ! guard_init = set_guard (guard); ! if (assignment) ! assignment = build_compound_expr (assignment, guard_init); else ! assignment = guard_init; ! finish_expr_stmt (assignment); /* Use atexit to register a function for destroying this static variable. */ ! register_dtor_fn (decl); ! finish_compound_stmt (then_clause); ! finish_then_clause (if_stmt); ! finish_if_stmt (); ! } ! else ! static_aggregates = tree_cons (init, decl, static_aggregates); ! } ! /* Finish the declaration of a catch-parameter. */ ! tree ! start_handler_parms (tree declspecs, tree declarator) ! { ! tree decl; ! if (declspecs) ! { ! decl = grokdeclarator (declarator, declspecs, CATCHPARM, ! 1, NULL); ! if (decl == NULL_TREE) ! error ("invalid catch parameter"); } else ! decl = NULL_TREE; ! ! return decl; } --- 5197,5335 ---- static void expand_static_init (tree decl, tree init) { ! gcc_assert (TREE_CODE (decl) == VAR_DECL); ! gcc_assert (TREE_STATIC (decl)); /* Some variables require no initialization. */ ! if (!init && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) return; ! if (DECL_FUNCTION_SCOPE_P (decl)) { /* Emit code to perform this initialization but once. */ ! tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE; ! tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE; ! tree guard, guard_addr, guard_addr_list; ! tree acquire_fn, release_fn, abort_fn; ! tree flag, begin; /* Emit code to perform this initialization but once. This code looks like: ! static guard; ! if (!guard.first_byte) { ! if (__cxa_guard_acquire (&guard)) { ! bool flag = false; ! try { ! // Do initialization. ! flag = true; __cxa_guard_release (&guard); ! // Register variable for destruction at end of program. ! } catch { ! if (!flag) __cxa_guard_abort (&guard); ! } } ! Note that the `flag' variable is only set to 1 *after* the initialization is complete. This ensures that an exception, thrown during the construction, will cause the variable to reinitialized when we pass through this code again, as per: [stmt.dcl] ! If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. ! This process should be thread-safe, too; multiple threads ! should not be able to initialize the variable more than ! once. */ /* Create the guard variable. */ guard = get_guard (decl); ! /* This optimization isn't safe on targets with relaxed memory ! consistency. On such targets we force synchronization in ! __cxa_guard_acquire. */ ! if (!targetm.relaxed_ordering || !flag_threadsafe_statics) ! { ! /* Begin the conditional initialization. */ ! if_stmt = begin_if_stmt (); ! finish_if_stmt_cond (get_guard_cond (guard), if_stmt); ! then_clause = begin_compound_stmt (BCS_NO_SCOPE); ! } ! if (flag_threadsafe_statics) ! { ! guard_addr = build_address (guard); ! guard_addr_list = build_tree_list (NULL_TREE, guard_addr); ! acquire_fn = get_identifier ("__cxa_guard_acquire"); ! release_fn = get_identifier ("__cxa_guard_release"); ! abort_fn = get_identifier ("__cxa_guard_abort"); ! if (!get_global_value_if_present (acquire_fn, &acquire_fn)) ! { ! tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr), ! void_list_node); ! tree vfntype = build_function_type (void_type_node, argtypes); ! acquire_fn = push_library_fn ! (acquire_fn, build_function_type (integer_type_node, argtypes)); ! release_fn = push_library_fn (release_fn, vfntype); ! abort_fn = push_library_fn (abort_fn, vfntype); ! } ! else ! { ! release_fn = identifier_global_value (release_fn); ! abort_fn = identifier_global_value (abort_fn); ! } ! ! inner_if_stmt = begin_if_stmt (); ! finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list), ! inner_if_stmt); ! ! inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE); ! begin = get_target_expr (boolean_false_node); ! flag = TARGET_EXPR_SLOT (begin); ! ! TARGET_EXPR_CLEANUP (begin) ! = build (COND_EXPR, void_type_node, flag, ! void_zero_node, ! build_call (abort_fn, guard_addr_list)); ! CLEANUP_EH_ONLY (begin) = 1; ! ! /* Do the initialization itself. */ ! init = add_stmt_to_compound (begin, init); ! init = add_stmt_to_compound ! (init, build (MODIFY_EXPR, void_type_node, flag, boolean_true_node)); ! init = add_stmt_to_compound ! (init, build_call (release_fn, guard_addr_list)); ! } else ! init = add_stmt_to_compound (init, set_guard (guard)); /* Use atexit to register a function for destroying this static variable. */ ! init = add_stmt_to_compound (init, register_dtor_fn (decl)); ! finish_expr_stmt (init); ! if (flag_threadsafe_statics) ! { ! finish_compound_stmt (inner_then_clause); ! finish_then_clause (inner_if_stmt); ! finish_if_stmt (inner_if_stmt); ! } ! if (!targetm.relaxed_ordering || !flag_threadsafe_statics) ! { ! finish_compound_stmt (then_clause); ! finish_then_clause (if_stmt); ! finish_if_stmt (if_stmt); ! } } else ! static_aggregates = tree_cons (init, decl, static_aggregates); } *************** start_handler_parms (tree declspecs, tre *** 5417,5510 **** 2 if there was no information (in which case assume 0 if DO_DEFAULT). */ int ! complete_array_type (tree type, tree initial_value, int do_default) { ! tree maxindex = NULL_TREE; ! int value = 0; if (initial_value) { /* An array of character type can be initialized from a brace-enclosed string constant. */ ! if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))) && TREE_CODE (initial_value) == CONSTRUCTOR && CONSTRUCTOR_ELTS (initial_value) && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value))) == STRING_CST) && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE) initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)); - - /* Note MAXINDEX is really the maximum index, one less than the - size. */ - if (TREE_CODE (initial_value) == STRING_CST) - { - int eltsize - = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); - maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value) - / eltsize) - 1, 0); - } - else if (TREE_CODE (initial_value) == CONSTRUCTOR) - { - tree elts = CONSTRUCTOR_ELTS (initial_value); - - maxindex = ssize_int (-1); - for (; elts; elts = TREE_CHAIN (elts)) - { - if (TREE_PURPOSE (elts)) - maxindex = TREE_PURPOSE (elts); - else - maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1)); - } - maxindex = copy_node (maxindex); - } - else - { - /* Make an error message unless that happened already. */ - if (initial_value != error_mark_node) - value = 1; - else - initial_value = NULL_TREE; - - /* Prevent further error messages. */ - maxindex = build_int_2 (0, 0); - } - } - - if (!maxindex) - { - if (do_default) - maxindex = build_int_2 (0, 0); - value = 2; } ! ! if (maxindex) { ! tree itype; ! tree domain; ! ! domain = build_index_type (maxindex); ! TYPE_DOMAIN (type) = domain; ! ! if (! TREE_TYPE (maxindex)) ! TREE_TYPE (maxindex) = domain; ! if (initial_value) ! itype = TREE_TYPE (initial_value); ! else ! itype = NULL; ! if (itype && !TYPE_DOMAIN (itype)) ! TYPE_DOMAIN (itype) = domain; ! /* The type of the main variant should never be used for arrays ! of different sizes. It should only ever be completed with the ! size of the array. */ ! if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type))) ! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain; } ! /* Lay out the type now that we can get the real answer. */ ! ! layout_type (type); ! ! return value; } /* Return zero if something is declared to be a member of type --- 5338,5378 ---- 2 if there was no information (in which case assume 0 if DO_DEFAULT). */ int ! cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) { ! int failure; ! tree type, elt_type; if (initial_value) { /* An array of character type can be initialized from a brace-enclosed string constant. */ ! if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) && TREE_CODE (initial_value) == CONSTRUCTOR && CONSTRUCTOR_ELTS (initial_value) && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value))) == STRING_CST) && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE) initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)); } ! ! failure = complete_array_type (ptype, initial_value, do_default); ! ! /* We can create the array before the element type is complete, which ! means that we didn't have these two bits set in the original type ! either. In completing the type, we are expected to propagate these ! bits. See also complete_type which does the same thing for arrays ! of fixed size. */ ! type = *ptype; ! if (TYPE_DOMAIN (type)) { ! elt_type = TREE_TYPE (type); ! TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (elt_type); ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) ! = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (elt_type); } ! return failure; } /* Return zero if something is declared to be a member of type *************** member_function_or_else (tree ctype, tre *** 5517,5527 **** if (ctype && ctype != cur_type) { if (flags == DTOR_FLAG) ! error ("destructor for alien class `%T' cannot be a member", ! ctype); else ! error ("constructor for alien class `%T' cannot be a member", ! ctype); return 0; } return 1; --- 5385,5393 ---- if (ctype && ctype != cur_type) { if (flags == DTOR_FLAG) ! error ("destructor for alien class %qT cannot be a member", ctype); else ! error ("constructor for alien class %qT cannot be a member", ctype); return 0; } return 1; *************** bad_specifiers (tree object, *** 5542,5561 **** int raises) { if (virtualp) ! error ("`%D' declared as a `virtual' %s", object, type); if (inlinep) ! error ("`%D' declared as an `inline' %s", object, type); if (quals) ! error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", ! object, type); if (friendp) ! cp_error_at ("`%D' declared as a friend", object); if (raises && (TREE_CODE (object) == TYPE_DECL || (!TYPE_PTRFN_P (TREE_TYPE (object)) && !TYPE_REFFN_P (TREE_TYPE (object)) && !TYPE_PTRMEMFUNC_P (TREE_TYPE (object))))) ! cp_error_at ("`%D' declared with an exception specification", object); } /* CTYPE is class type, or null if non-class. --- 5408,5428 ---- int raises) { if (virtualp) ! error ("%qD declared as a % %s", object, type); if (inlinep) ! error ("%qD declared as an % %s", object, type); if (quals) ! error ("% and % function specifiers on " ! "%qD invalid in %s declaration", ! object, type); if (friendp) ! cp_error_at ("%qD declared as a friend", object); if (raises && (TREE_CODE (object) == TYPE_DECL || (!TYPE_PTRFN_P (TREE_TYPE (object)) && !TYPE_REFFN_P (TREE_TYPE (object)) && !TYPE_PTRMEMFUNC_P (TREE_TYPE (object))))) ! cp_error_at ("%qD declared with an exception specification", object); } /* CTYPE is class type, or null if non-class. *************** bad_specifiers (tree object, *** 5571,5596 **** CHECK is 1 if we must find this method in CTYPE, 0 if we should not look, and -1 if we should not call `grokclassfn' at all. Returns `NULL_TREE' if something goes wrong, after issuing applicable error messages. */ static tree ! grokfndecl (tree ctype, tree type, tree declarator, tree parms, tree orig_declarator, int virtualp, enum overload_flags flags, ! tree quals, tree raises, ! int check, ! int friendp, ! int publicp, ! int inlinep, ! int funcdef_flag, int template_count, ! tree in_namespace) { tree decl; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; --- 5438,5467 ---- CHECK is 1 if we must find this method in CTYPE, 0 if we should not look, and -1 if we should not call `grokclassfn' at all. + SFK is the kind of special function (if any) for the new function. + Returns `NULL_TREE' if something goes wrong, after issuing applicable error messages. */ static tree ! grokfndecl (tree ctype, tree type, tree declarator, tree parms, tree orig_declarator, int virtualp, enum overload_flags flags, ! cp_cv_quals quals, tree raises, ! int check, ! int friendp, ! int publicp, ! int inlinep, ! special_function_kind sfk, ! int funcdef_flag, int template_count, ! tree in_namespace, ! tree* attrlist) { tree decl; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; *************** grokfndecl (tree ctype, *** 5637,5657 **** if (ctype == NULL_TREE && DECL_MAIN_P (decl)) { if (processing_template_decl) ! error ("cannot declare `::main' to be a template"); if (inlinep) ! error ("cannot declare `::main' to be inline"); if (!publicp) ! error ("cannot declare `::main' to be static"); if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)), integer_type_node)) ! error ("`main' must return `int'"); inlinep = 0; publicp = 1; } /* Members of anonymous types and local classes have no linkage; make ! them internal. */ ! /* FIXME what if it gets a name from typedef? */ if (ctype && (TYPE_ANONYMOUS_P (ctype) || decl_function_context (TYPE_MAIN_DECL (ctype)))) publicp = 0; --- 5508,5530 ---- if (ctype == NULL_TREE && DECL_MAIN_P (decl)) { if (processing_template_decl) ! error ("cannot declare %<::main%> to be a template"); if (inlinep) ! error ("cannot declare %<::main%> to be inline"); if (!publicp) ! error ("cannot declare %<::main%> to be static"); if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)), integer_type_node)) ! { ! error ("%<::main%> must return %"); ! TREE_TYPE (TREE_TYPE (decl)) = integer_type_node; ! } inlinep = 0; publicp = 1; } /* Members of anonymous types and local classes have no linkage; make ! them internal. If a typedef is made later, this will be changed. */ if (ctype && (TYPE_ANONYMOUS_P (ctype) || decl_function_context (TYPE_MAIN_DECL (ctype)))) publicp = 0; *************** grokfndecl (tree ctype, *** 5663,5669 **** declare an entity with linkage. Only check this for public decls for now. See core 319, 389. */ ! t = no_linkage_check (TREE_TYPE (decl)); if (t) { if (TYPE_ANONYMOUS_P (t)) --- 5536,5543 ---- declare an entity with linkage. Only check this for public decls for now. See core 319, 389. */ ! t = no_linkage_check (TREE_TYPE (decl), ! /*relaxed_p=*/false); if (t) { if (TYPE_ANONYMOUS_P (t)) *************** grokfndecl (tree ctype, *** 5672,5688 **** /* Allow this; it's pretty common in C. */; else { ! pedwarn ("non-local function `%#D' uses anonymous type", decl); if (DECL_ORIGINAL_TYPE (TYPE_NAME (t))) ! cp_pedwarn_at ("\ ! `%#D' does not refer to the unqualified type, so it is not used for linkage", ! TYPE_NAME (t)); } } else ! pedwarn ("non-local function `%#D' uses local type `%T'", ! decl, t); } } --- 5546,5561 ---- /* Allow this; it's pretty common in C. */; else { ! pedwarn ("non-local function %q#D uses anonymous type", decl); if (DECL_ORIGINAL_TYPE (TYPE_NAME (t))) ! cp_pedwarn_at ("%q#D does not refer to the unqualified " ! "type, so it is not used for linkage", ! TYPE_NAME (t)); } } else ! pedwarn ("non-local function %q#D uses local type %qT", decl, t); } } *************** grokfndecl (tree ctype, *** 5703,5713 **** DECL_INLINE (decl) = 1; DECL_EXTERNAL (decl) = 1; ! if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) { ! error ("%smember function `%D' cannot have `%T' method qualifier", ! (ctype ? "static " : "non-"), decl, TREE_VALUE (quals)); ! quals = NULL_TREE; } if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) --- 5576,5586 ---- DECL_INLINE (decl) = 1; DECL_EXTERNAL (decl) = 1; ! if (quals && TREE_CODE (type) == FUNCTION_TYPE) { ! error ("%smember function %qD cannot have cv-qualifier", ! (ctype ? "static " : "non-"), decl); ! quals = TYPE_UNQUALIFIED; } if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) *************** grokfndecl (tree ctype, *** 5729,5735 **** { if (funcdef_flag) error ! ("defining explicit specialization `%D' in friend declaration", orig_declarator); else { --- 5602,5608 ---- { if (funcdef_flag) error ! ("defining explicit specialization %qD in friend declaration", orig_declarator); else { *************** grokfndecl (tree ctype, *** 5739,5746 **** if (PROCESSING_REAL_TEMPLATE_DECL_P ()) { /* Something like `template friend void f()'. */ ! error ("invalid use of template-id `%D' in declaration of primary template", ! orig_declarator); return NULL_TREE; } --- 5612,5620 ---- if (PROCESSING_REAL_TEMPLATE_DECL_P ()) { /* Something like `template friend void f()'. */ ! error ("invalid use of template-id %qD in declaration " ! "of primary template", ! orig_declarator); return NULL_TREE; } *************** grokfndecl (tree ctype, *** 5756,5780 **** (see template_id in parse.y). If the current class contains 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); fns = TREE_OPERAND (fns, 1); } ! my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE ! || TREE_CODE (fns) == OVERLOAD, 20001120); DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE); if (has_default_arg) { ! error ("default arguments are not allowed in declaration of friend template specialization `%D'", ! decl); return NULL_TREE; } if (inlinep) { ! error ("`inline' is not allowed in declaration of friend template specialization `%D'", ! decl); return NULL_TREE; } } --- 5630,5656 ---- (see template_id in parse.y). If the current class contains such a name, we'll get a COMPONENT_REF here. Undo that. */ ! gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0)) ! == current_class_type); fns = TREE_OPERAND (fns, 1); } ! gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE ! || TREE_CODE (fns) == OVERLOAD); DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE); if (has_default_arg) { ! error ("default arguments are not allowed in declaration " ! "of friend template specialization %qD", ! decl); return NULL_TREE; } if (inlinep) { ! error ("% is not allowed in declaration of friend " ! "template specialization %qD", ! decl); return NULL_TREE; } } *************** grokfndecl (tree ctype, *** 5792,5805 **** if (check < 0) return decl; - if (flags == NO_SPECIAL && ctype && constructor_name_p (declarator, ctype)) - DECL_CONSTRUCTOR_P (decl) = 1; - - /* Function gets the ugly name, field gets the nice one. This call - may change the type of the function (because of default - parameters)! */ if (ctype != NULL_TREE) ! grokclassfn (ctype, decl, flags, quals); decl = check_explicit_specialization (orig_declarator, decl, template_count, --- 5668,5680 ---- if (check < 0) return decl; if (ctype != NULL_TREE) ! { ! if (sfk == sfk_constructor) ! DECL_CONSTRUCTOR_P (decl) = 1; ! ! grokclassfn (ctype, decl, flags, quals); ! } decl = check_explicit_specialization (orig_declarator, decl, template_count, *************** grokfndecl (tree ctype, *** 5808,5813 **** --- 5683,5694 ---- if (decl == error_mark_node) return NULL_TREE; + if (attrlist) + { + cplus_decl_attributes (&decl, *attrlist, 0); + *attrlist = NULL_TREE; + } + if (ctype != NULL_TREE && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl)) && check) *************** grokfndecl (tree ctype, *** 5815,5822 **** tree old_decl; old_decl = check_classfn (ctype, decl, ! processing_template_decl ! > template_class_depth (ctype)); if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL) /* Because grokfndecl is always supposed to return a --- 5696,5705 ---- tree old_decl; old_decl = check_classfn (ctype, decl, ! (processing_template_decl ! > template_class_depth (ctype)) ! ? current_template_parms ! : NULL_TREE); if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL) /* Because grokfndecl is always supposed to return a *************** grokfndecl (tree ctype, *** 5831,5842 **** XXX Isn't this done in start_function, too? */ revert_static_member_fn (decl); if (old_decl && DECL_ARTIFICIAL (old_decl)) ! error ("definition of implicitly-declared `%D'", old_decl); if (old_decl) { tree ok; ! bool pop_p; /* Since we've smashed OLD_DECL to its DECL_TEMPLATE_RESULT, we must do the same to DECL. */ --- 5714,5725 ---- XXX Isn't this done in start_function, too? */ revert_static_member_fn (decl); if (old_decl && DECL_ARTIFICIAL (old_decl)) ! error ("definition of implicitly-declared %qD", old_decl); if (old_decl) { tree ok; ! tree pushed_scope; /* Since we've smashed OLD_DECL to its DECL_TEMPLATE_RESULT, we must do the same to DECL. */ *************** grokfndecl (tree ctype, *** 5845,5857 **** /* Attempt to merge the declarations. This can fail, in the case of some invalid specialization declarations. */ ! pop_p = push_scope (ctype); ok = duplicate_decls (decl, old_decl); ! if (pop_p) ! pop_scope (ctype); if (!ok) { ! error ("no `%#D' member function declared in class `%T'", decl, ctype); return NULL_TREE; } --- 5728,5740 ---- /* Attempt to merge the declarations. This can fail, in the case of some invalid specialization declarations. */ ! pushed_scope = push_scope (ctype); ok = duplicate_decls (decl, old_decl); ! if (pushed_scope) ! pop_scope (pushed_scope); if (!ok) { ! error ("no %q#D member function declared in class %qT", decl, ctype); return NULL_TREE; } *************** grokfndecl (tree ctype, *** 5871,5877 **** 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 --- 5754,5779 ---- return decl; } ! /* DECL is a VAR_DECL for a static data member. Set flags to reflect ! the linkage that DECL will receive in the object file. */ ! ! static void ! set_linkage_for_static_data_member (tree decl) ! { ! /* A static data member always has static storage duration and ! external linkage. Note that static data members are forbidden in ! local classes -- the only situation in which a class has ! non-external linkage. */ ! TREE_PUBLIC (decl) = 1; ! TREE_STATIC (decl) = 1; ! /* For non-template classes, static data members are always put ! out in exactly those files where they are defined, just as ! with ordinary namespace-scope variables. */ ! if (!processing_template_decl) ! DECL_INTERFACE_KNOWN (decl) = 1; ! } ! ! /* 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 *************** grokfndecl (tree ctype, *** 5880,5911 **** static tree grokvardecl (tree type, tree name, ! RID_BIT_TYPE * specbits_in, int initialized, int constp, tree scope) { tree decl; ! RID_BIT_TYPE specbits; ! ! my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE, ! 20020808); ! specbits = *specbits_in; ! /* Compute the scope in which to place the variable. */ if (!scope) { /* 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 --- 5782,5808 ---- static tree grokvardecl (tree type, tree name, ! const cp_decl_specifier_seq *declspecs, int initialized, int constp, tree scope) { tree decl; ! tree explicit_scope; ! gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE); ! /* Compute the scope in which to place the variable, but remember ! whether or not that scope was explicitly specified by the user. */ ! explicit_scope = scope; if (!scope) { /* An explicit "extern" specifier indicates a namespace-scope variable. */ ! if (declspecs->storage_class == sc_extern) scope = current_namespace; else if (!at_function_scope_p ()) ! scope = current_scope (); } if (scope *************** grokvardecl (tree type, *** 5914,5920 **** (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))) --- 5811,5817 ---- (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))) *************** grokvardecl (tree type, *** 5922,5968 **** else decl = build_decl (VAR_DECL, name, type); ! if (scope && TREE_CODE (scope) == NAMESPACE_DECL) ! set_decl_namespace (decl, scope, 0); else DECL_CONTEXT (decl) = scope; ! 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)) { DECL_THIS_EXTERN (decl) = 1; DECL_EXTERNAL (decl) = !initialized; } - /* In class context, static means one per class, - public access, and static storage. */ if (DECL_CLASS_SCOPE_P (decl)) { ! TREE_PUBLIC (decl) = 1; ! TREE_STATIC (decl) = 1; DECL_EXTERNAL (decl) = 0; } /* At top level, either `static' or no s.c. makes a definition (perhaps tentative), and absence of `static' makes it public. */ else if (toplevel_bindings_p ()) { ! TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits) && (DECL_THIS_EXTERN (decl) || ! constp)); TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ else { ! TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits); TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); } ! if (RIDBIT_SETP (RID_THREAD, specbits)) { if (targetm.have_tls) DECL_THREAD_LOCAL (decl) = 1; --- 5819,5857 ---- else decl = build_decl (VAR_DECL, name, type); ! if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL) ! set_decl_namespace (decl, explicit_scope, 0); else DECL_CONTEXT (decl) = scope; ! if (declspecs->storage_class == sc_extern) { DECL_THIS_EXTERN (decl) = 1; DECL_EXTERNAL (decl) = !initialized; } if (DECL_CLASS_SCOPE_P (decl)) { ! set_linkage_for_static_data_member (decl); ! /* This function is only called with out-of-class definitions. */ DECL_EXTERNAL (decl) = 0; } /* At top level, either `static' or no s.c. makes a definition (perhaps tentative), and absence of `static' makes it public. */ else if (toplevel_bindings_p ()) { ! TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static && (DECL_THIS_EXTERN (decl) || ! constp)); TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ else { ! TREE_STATIC (decl) = declspecs->storage_class == sc_static; TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); } ! if (declspecs->specs[(int)ds_thread]) { if (targetm.have_tls) DECL_THREAD_LOCAL (decl) = 1; *************** grokvardecl (tree type, *** 5979,5994 **** declare an entity with linkage. Only check this for public decls for now. */ ! tree t = no_linkage_check (TREE_TYPE (decl)); if (t) { if (TYPE_ANONYMOUS_P (t)) ! /* Ignore for now; `enum { foo } e' is pretty common. */; else ! pedwarn ("non-local variable `%#D' uses local type `%T'", ! decl, t); } } return decl; } --- 5868,5901 ---- declare an entity with linkage. Only check this for public decls for now. */ ! tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false); if (t) { if (TYPE_ANONYMOUS_P (t)) ! { ! if (DECL_EXTERN_C_P (decl)) ! /* Allow this; it's pretty common in C. */ ! ; ! else ! { ! /* DRs 132, 319 and 389 seem to indicate types with ! no linkage can only be used to declare extern "C" ! entities. Since it's not always an error in the ! ISO C++ 90 Standard, we only issue a warning. */ ! warning ("non-local variable %q#D uses anonymous type", ! decl); ! if (DECL_ORIGINAL_TYPE (TYPE_NAME (t))) ! cp_warning_at ("%q#D does not refer to the unqualified " ! "type, so it is not used for linkage", ! TYPE_NAME (t)); ! } ! } else ! warning ("non-local variable %q#D uses local type %qT", decl, t); } } + else + DECL_INTERFACE_KNOWN (decl) = 1; return decl; } *************** build_ptrmemfunc_type (tree type) *** 6020,6025 **** --- 5927,5934 ---- = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type)); t = make_aggr_type (RECORD_TYPE); + xref_basetypes (t, NULL_TREE); + /* Let the front-end know this is a pointer to member function... */ TYPE_PTRMEMFUNC_FLAG (t) = 1; /* ... and not really an aggregate. */ *************** build_ptrmemfunc_type (tree type) *** 6027,6037 **** field = build_decl (FIELD_DECL, pfn_identifier, type); fields = field; ! field = build_decl (FIELD_DECL, delta_identifier, delta_type_node); TREE_CHAIN (field) = fields; fields = field; ! finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node); /* Zap out the name so that the back-end will give us the debugging --- 5936,5946 ---- field = build_decl (FIELD_DECL, pfn_identifier, type); fields = field; ! field = build_decl (FIELD_DECL, delta_identifier, delta_type_node); TREE_CHAIN (field) = fields; fields = field; ! finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node); /* Zap out the name so that the back-end will give us the debugging *************** build_ptrmem_type (tree class_type, tree *** 6067,6085 **** tree arg_types; arg_types = TYPE_ARG_TYPES (member_type); ! class_type = (cp_build_qualified_type (class_type, cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types))))); ! member_type ! = build_method_type_directly (class_type, TREE_TYPE (member_type), TREE_CHAIN (arg_types)); return build_ptrmemfunc_type (build_pointer_type (member_type)); } else { ! my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE, ! 20030716); return build_offset_type (class_type, member_type); } } --- 5976,5993 ---- tree arg_types; arg_types = TYPE_ARG_TYPES (member_type); ! class_type = (cp_build_qualified_type (class_type, cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types))))); ! member_type ! = build_method_type_directly (class_type, TREE_TYPE (member_type), TREE_CHAIN (arg_types)); return build_ptrmemfunc_type (build_pointer_type (member_type)); } else { ! gcc_assert (TREE_CODE (member_type) != FUNCTION_TYPE); return build_offset_type (class_type, member_type); } } *************** check_static_variable_definition (tree d *** 6100,6118 **** required. */ if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE) { ! error ("invalid in-class initialization of static data member of non-integral type `%T'", type); /* If we just return the declaration, crashes will sometimes ! occur. We therefore return void_type_node, as if this was a friend declaration, to cause callers to completely ignore this declaration. */ return 1; } else if (!CP_TYPE_CONST_P (type)) ! error ("ISO C++ forbids in-class initialization of non-const static member `%D'", ! decl); else if (pedantic && !INTEGRAL_TYPE_P (type)) ! pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type); return 0; } --- 6008,6029 ---- required. */ if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE) { ! error ("invalid in-class initialization of static data member " ! "of non-integral type %qT", type); /* If we just return the declaration, crashes will sometimes ! occur. We therefore return void_type_node, as if this were a friend declaration, to cause callers to completely ignore this declaration. */ return 1; } else if (!CP_TYPE_CONST_P (type)) ! error ("ISO C++ forbids in-class initialization of non-const " ! "static member %qD", ! decl); else if (pedantic && !INTEGRAL_TYPE_P (type)) ! pedwarn ("ISO C++ forbids initialization of member constant " ! "%qD of non-integral type %qT", decl, type); return 0; } *************** compute_array_index_type (tree name, tre *** 6131,6139 **** if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type)) { if (name) ! error ("size of array `%D' has non-integral type `%T'", name, type); else ! error ("size of array has non-integral type `%T'", type); size = integer_one_node; type = TREE_TYPE (size); } --- 6042,6050 ---- if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type)) { if (name) ! error ("size of array %qD has non-integral type %qT", name, type); else ! error ("size of array has non-integral type %qT", type); size = integer_one_node; type = TREE_TYPE (size); } *************** compute_array_index_type (tree name, tre *** 6151,6157 **** STRIP_TYPE_NOPS (size); /* It might be a const variable or enumeration constant. */ ! size = decl_constant_value (size); /* Normally, the array-bound will be a constant. */ if (TREE_CODE (size) == INTEGER_CST) --- 6062,6068 ---- STRIP_TYPE_NOPS (size); /* It might be a const variable or enumeration constant. */ ! size = integral_constant_value (size); /* Normally, the array-bound will be a constant. */ if (TREE_CODE (size) == INTEGER_CST) *************** compute_array_index_type (tree name, tre *** 6169,6175 **** if (INT_CST_LT (size, integer_zero_node)) { if (name) ! error ("size of array `%D' is negative", name); else error ("size of array is negative"); size = integer_one_node; --- 6080,6086 ---- if (INT_CST_LT (size, integer_zero_node)) { if (name) ! error ("size of array %qD is negative", name); else error ("size of array is negative"); size = integer_one_node; *************** compute_array_index_type (tree name, tre *** 6179,6185 **** else if (integer_zerop (size) && pedantic && !in_system_header) { if (name) ! pedwarn ("ISO C++ forbids zero-size array `%D'", name); else pedwarn ("ISO C++ forbids zero-size array"); } --- 6090,6096 ---- else if (integer_zerop (size) && pedantic && !in_system_header) { if (name) ! pedwarn ("ISO C++ forbids zero-size array %qD", name); else pedwarn ("ISO C++ forbids zero-size array"); } *************** compute_array_index_type (tree name, tre *** 6188,6202 **** { /* `(int) &fn' is not a valid array bound. */ if (name) ! error ("size of array `%D' is not an integral constant-expression", ! name); else error ("size of array is not an integral constant-expression"); } else if (pedantic) { if (name) ! pedwarn ("ISO C++ forbids variable-size array `%D'", name); else pedwarn ("ISO C++ forbids variable-size array"); } --- 6099,6113 ---- { /* `(int) &fn' is not a valid array bound. */ if (name) ! error ("size of array %qD is not an integral constant-expression", ! name); else error ("size of array is not an integral constant-expression"); } else if (pedantic) { if (name) ! pedwarn ("ISO C++ forbids variable-size array %qD", name); else pedwarn ("ISO C++ forbids variable-size array"); } *************** compute_array_index_type (tree name, tre *** 6206,6217 **** itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node); else { /* Compute the index of the largest element in the array. It is ! one less than the number of elements in the array. */ ! itype ! = fold (cp_build_binary_op (MINUS_EXPR, ! cp_convert (ssizetype, size), ! cp_convert (ssizetype, integer_one_node))); if (!TREE_CONSTANT (itype)) /* A variable sized array. */ itype = variable_size (itype); --- 6117,6136 ---- itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node); else { + HOST_WIDE_INT saved_processing_template_decl; + /* Compute the index of the largest element in the array. It is ! one less than the number of elements in the array. We save ! and restore PROCESSING_TEMPLATE_DECL so that computations in ! cp_build_binary_op will be appropriately folded. */ ! saved_processing_template_decl = processing_template_decl; ! processing_template_decl = 0; ! itype = cp_build_binary_op (MINUS_EXPR, ! cp_convert (ssizetype, size), ! cp_convert (ssizetype, integer_one_node)); ! itype = fold (itype); ! processing_template_decl = saved_processing_template_decl; ! if (!TREE_CONSTANT (itype)) /* A variable sized array. */ itype = variable_size (itype); *************** compute_array_index_type (tree name, tre *** 6234,6273 **** unqualified name, NULL_TREE is returned. */ tree ! get_scope_of_declarator (tree declarator) { ! if (!declarator) ! return NULL_TREE; ! ! switch (TREE_CODE (declarator)) ! { ! case CALL_EXPR: ! case ARRAY_REF: ! case INDIRECT_REF: ! case ADDR_EXPR: ! /* For any of these, the main declarator is the first operand. */ ! return get_scope_of_declarator (TREE_OPERAND ! (declarator, 0)); ! case SCOPE_REF: ! /* For a pointer-to-member, continue descending. */ ! if (TREE_CODE (TREE_OPERAND (declarator, 1)) ! == INDIRECT_REF) ! return get_scope_of_declarator (TREE_OPERAND ! (declarator, 1)); ! /* Otherwise, if the declarator-id is a SCOPE_REF, the scope in ! which the declaration occurs is the first operand. */ ! return TREE_OPERAND (declarator, 0); ! case TREE_LIST: ! /* Attributes to be applied. The declarator is TREE_VALUE. */ ! return get_scope_of_declarator (TREE_VALUE (declarator)); ! ! default: ! /* Otherwise, we have a declarator-id which is not a qualified ! name; the entity will be declared in the current scope. */ ! return NULL_TREE; ! } } /* Returns an ARRAY_TYPE for an array with SIZE elements of the --- 6153,6172 ---- unqualified name, NULL_TREE is returned. */ tree ! get_scope_of_declarator (const cp_declarator *declarator) { ! while (declarator && declarator->kind != cdk_id) ! declarator = declarator->declarator; ! /* If the declarator-id is a SCOPE_REF, the scope in which the ! declaration occurs is the first operand. */ ! if (declarator ! && declarator->u.id.qualifying_scope) ! return declarator->u.id.qualifying_scope; ! /* Otherwise, the declarator is not a qualified name; the entity will ! be declared in the current scope. */ ! return NULL_TREE; } /* Returns an ARRAY_TYPE for an array with SIZE elements of the *************** create_array_type_for_decl (tree name, t *** 6314,6320 **** if (error_msg) { if (name) ! error ("declaration of `%D' as %s", name, error_msg); else error ("creating %s", error_msg); --- 6213,6219 ---- if (error_msg) { if (name) ! error ("declaration of %qD as %s", name, error_msg); else error ("creating %s", error_msg); *************** create_array_type_for_decl (tree name, t *** 6328,6337 **** if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) { if (name) ! error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first", ! name); else ! error ("multidimensional array must have bounds for all dimensions except the first"); return error_mark_node; } --- 6227,6238 ---- if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) { if (name) ! error ("declaration of %qD as multidimensional array must " ! "have bounds for all dimensions except the first", ! name); else ! error ("multidimensional array must have bounds for all " ! "dimensions except the first"); return error_mark_node; } *************** create_array_type_for_decl (tree name, t *** 6340,6352 **** if (size) itype = compute_array_index_type (name, size); return build_cplus_array_type (type, itype); } /* Check that it's OK to declare a function with the indicated TYPE. SFK indicates the kind of special function (if any) that this function is. OPTYPE is the type given in a conversion operator ! declaration. Returns the actual return type of the function; that may be different than TYPE if an error occurs, or for certain special functions. */ --- 6241,6259 ---- if (size) itype = compute_array_index_type (name, size); + /* [dcl.array] + T is called the array element type; this type shall not be [...] an + abstract class type. */ + abstract_virtuals_error (name, type); + return build_cplus_array_type (type, itype); } /* Check that it's OK to declare a function with the indicated TYPE. SFK indicates the kind of special function (if any) that this function is. OPTYPE is the type given in a conversion operator ! declaration, or the class type for a constructor/destructor. ! Returns the actual return type of the function; that may be different than TYPE if an error occurs, or for certain special functions. */ *************** check_special_function_return_type (spec *** 6361,6386 **** if (type) error ("return type specification for constructor invalid"); ! type = void_type_node; break; case sfk_destructor: if (type) error ("return type specification for destructor invalid"); ! type = void_type_node; break; case sfk_conversion: if (type && !same_type_p (type, optype)) ! error ("operator `%T' declared to return `%T'", optype, type); else if (type) ! pedwarn ("return type specified for `operator %T'", optype); type = optype; break; default: ! abort (); ! break; } return type; --- 6268,6302 ---- if (type) error ("return type specification for constructor invalid"); ! if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype)) ! type = build_pointer_type (optype); ! else ! type = void_type_node; break; case sfk_destructor: if (type) error ("return type specification for destructor invalid"); ! /* We can't use the proper return type here because we run into ! problems with ambiguous bases and covariant returns. ! Java classes are left unchanged because (void *) isn't a valid ! Java type, and we don't want to change the Java ABI. */ ! if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype)) ! type = build_pointer_type (void_type_node); ! else ! type = void_type_node; break; case sfk_conversion: if (type && !same_type_p (type, optype)) ! error ("operator %qT declared to return %qT", optype, type); else if (type) ! pedwarn ("return type specified for %", optype); type = optype; break; default: ! gcc_unreachable (); } return type; *************** check_special_function_return_type (spec *** 6389,6395 **** /* A variable or data member (whose unqualified name is IDENTIFIER) has been declared with the indicated TYPE. If the TYPE is not acceptable, issue an error message and return a type to use for ! error-recovery purposes. */ tree check_var_type (tree identifier, tree type) --- 6305,6311 ---- /* A variable or data member (whose unqualified name is IDENTIFIER) has been declared with the indicated TYPE. If the TYPE is not acceptable, issue an error message and return a type to use for ! error-recovery purposes. */ tree check_var_type (tree identifier, tree type) *************** check_var_type (tree identifier, tree ty *** 6400,6408 **** error ("unnamed variable or field declared void"); else if (TREE_CODE (identifier) == IDENTIFIER_NODE) { ! if (IDENTIFIER_OPNAME_P (identifier)) ! abort (); ! error ("variable or field `%E' declared void", identifier); } else error ("variable or field declared void"); --- 6316,6323 ---- error ("unnamed variable or field declared void"); else if (TREE_CODE (identifier) == IDENTIFIER_NODE) { ! gcc_assert (!IDENTIFIER_OPNAME_P (identifier)); ! error ("variable or field %qE declared void", identifier); } else error ("variable or field declared void"); *************** check_var_type (tree identifier, tree ty *** 6452,6466 **** should not be `S'. */ tree ! grokdeclarator (tree declarator, ! tree declspecs, enum decl_context decl_context, int initialized, tree* attrlist) { - RID_BIT_TYPE specbits; - int nclasses = 0; - tree spec; tree type = NULL_TREE; int longlong = 0; int type_quals; --- 6367,6378 ---- should not be `S'. */ tree ! grokdeclarator (const cp_declarator *declarator, ! const cp_decl_specifier_seq *declspecs, enum decl_context decl_context, int initialized, tree* attrlist) { tree type = NULL_TREE; int longlong = 0; int type_quals; *************** grokdeclarator (tree declarator, *** 6468,6481 **** int explicit_int = 0; int explicit_char = 0; int defaulted_int = 0; - int extern_langp = 0; tree dependant_name = NULL_TREE; ! tree typedef_decl = NULL_TREE; ! const char *name; tree typedef_type = NULL_TREE; int funcdef_flag = 0; ! enum tree_code innermost_code = ERROR_MARK; int bitfield = 0; #if 0 /* See the code below that used this. */ --- 6380,6392 ---- int explicit_int = 0; int explicit_char = 0; int defaulted_int = 0; tree dependant_name = NULL_TREE; ! tree typedef_decl = NULL_TREE; ! const char *name = NULL; tree typedef_type = NULL_TREE; int funcdef_flag = 0; ! cp_declarator_kind innermost_code = cdk_error; int bitfield = 0; #if 0 /* See the code below that used this. */ *************** grokdeclarator (tree declarator, *** 6488,6505 **** special_function_kind sfk = sfk_none; tree dname = NULL_TREE; - tree ctype = current_class_type; tree ctor_return_type = NULL_TREE; enum overload_flags flags = NO_SPECIAL; ! tree quals = NULL_TREE; tree raises = NULL_TREE; int template_count = 0; - tree in_namespace = NULL_TREE; tree returned_attrs = NULL_TREE; - tree scope = NULL_TREE; tree parms = NULL_TREE; - RIDBIT_RESET_ALL (specbits); if (decl_context == FUNCDEF) funcdef_flag = 1, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) --- 6399,6436 ---- special_function_kind sfk = sfk_none; tree dname = NULL_TREE; tree ctor_return_type = NULL_TREE; enum overload_flags flags = NO_SPECIAL; ! cp_cv_quals quals = TYPE_UNQUALIFIED; tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; tree parms = NULL_TREE; + const cp_declarator *id_declarator; + /* The unqualified name of the declarator; either an + IDENTIFIER_NODE, BIT_NOT_EXPR, or TEMPLATE_ID_EXPR. */ + tree unqualified_id; + /* The class type, if any, in which this entity is located, + or NULL_TREE if none. Note that this value may be different from + the current class type; for example if an attempt is made to declare + "A::f" inside "B", this value will be "A". */ + tree ctype = current_class_type; + /* The NAMESPACE_DECL for the namespace in which this entity is + located. If an unqualified name is used to declare the entity, + this value will be NULL_TREE, even if the entity is located at + namespace scope. */ + tree in_namespace = NULL_TREE; + cp_decl_spec ds; + cp_storage_class storage_class; + bool unsigned_p, signed_p, short_p, long_p, thread_p; + bool type_was_error_mark_node = false; + + signed_p = declspecs->specs[(int)ds_signed]; + unsigned_p = declspecs->specs[(int)ds_unsigned]; + short_p = declspecs->specs[(int)ds_short]; + long_p = declspecs->specs[(int)ds_long]; + thread_p = declspecs->specs[(int)ds_thread]; if (decl_context == FUNCDEF) funcdef_flag = 1, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) *************** grokdeclarator (tree declarator, *** 6509,6794 **** /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ ! { ! tree *next = &declarator; ! tree decl; ! name = NULL; ! ! while (next && *next) ! { ! decl = *next; ! switch (TREE_CODE (decl)) ! { ! case TREE_LIST: ! /* For attributes. */ ! next = &TREE_VALUE (decl); ! break; ! ! case COND_EXPR: ! ctype = NULL_TREE; ! next = &TREE_OPERAND (decl, 0); ! break; ! case BIT_NOT_EXPR: /* For C++ destructors! */ { ! tree name = TREE_OPERAND (decl, 0); ! tree rename = NULL_TREE; ! ! my_friendly_assert (flags == NO_SPECIAL, 152); ! flags = DTOR_FLAG; ! sfk = sfk_destructor; ! if (TYPE_P (name)) ! TREE_OPERAND (decl, 0) = name = constructor_name (name); ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); ! if (ctype == NULL_TREE) ! { ! if (current_class_type == NULL_TREE) ! { ! error ("destructors must be member functions"); ! flags = NO_SPECIAL; ! } ! else ! { ! tree t = constructor_name (current_class_type); ! if (t != name) ! rename = t; ! } ! } ! else ! { ! tree t = constructor_name (ctype); ! if (t != name) ! rename = t; ! } ! ! if (rename) ! { ! error ("destructor `%T' must match class name `%T'", ! name, rename); ! TREE_OPERAND (decl, 0) = rename; ! } ! next = &name; } ! break; ! ! case ADDR_EXPR: /* C++ reference declaration */ ! /* Fall through. */ ! case ARRAY_REF: ! case INDIRECT_REF: ! ctype = NULL_TREE; ! innermost_code = TREE_CODE (decl); ! next = &TREE_OPERAND (decl, 0); ! break; ! ! case CALL_EXPR: ! innermost_code = TREE_CODE (decl); ! if (decl_context == FIELD && ctype == NULL_TREE) ! ctype = current_class_type; ! if (ctype ! && TREE_OPERAND (decl, 0) ! && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL ! && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)), ! ctype))) ! TREE_OPERAND (decl, 0) = constructor_name (ctype); ! next = &TREE_OPERAND (decl, 0); ! decl = *next; ! if (ctype != NULL_TREE ! && decl != NULL_TREE && flags != DTOR_FLAG ! && constructor_name_p (decl, ctype)) ! { ! sfk = sfk_constructor; ! ctor_return_type = ctype; ! } ! ctype = NULL_TREE; ! break; ! case TEMPLATE_ID_EXPR: { ! tree fns = TREE_OPERAND (decl, 0); ! ! dname = fns; ! if (TREE_CODE (dname) == COMPONENT_REF) ! dname = TREE_OPERAND (dname, 1); ! if (TREE_CODE (dname) != IDENTIFIER_NODE) { ! my_friendly_assert (is_overloaded_fn (dname), ! 19990331); ! dname = DECL_NAME (get_first_fn (dname)); } } ! /* Fall through. */ ! ! case IDENTIFIER_NODE: ! if (TREE_CODE (decl) == IDENTIFIER_NODE) ! dname = decl; ! ! next = 0; ! ! if (C_IS_RESERVED_WORD (dname)) ! { ! error ("declarator-id missing; using reserved word `%D'", ! dname); ! name = IDENTIFIER_POINTER (dname); ! } ! else if (!IDENTIFIER_TYPENAME_P (dname)) ! name = IDENTIFIER_POINTER (dname); ! else { ! my_friendly_assert (flags == NO_SPECIAL, 154); ! flags = TYPENAME_FLAG; ! ctor_return_type = TREE_TYPE (dname); ! sfk = sfk_conversion; ! if (is_typename_at_global_scope (dname)) ! name = IDENTIFIER_POINTER (dname); ! else ! name = ""; ! } ! break; ! ! /* C++ extension */ ! case SCOPE_REF: ! { ! /* Perform error checking, and decide on a ctype. */ ! tree cname = TREE_OPERAND (decl, 0); ! if (cname == NULL_TREE) ! ctype = NULL_TREE; ! else if (TREE_CODE (cname) == NAMESPACE_DECL) ! { ! ctype = NULL_TREE; ! in_namespace = TREE_OPERAND (decl, 0); ! } ! else if (! is_aggr_type (cname, 1)) ! ctype = NULL_TREE; ! /* Must test TREE_OPERAND (decl, 1), in case user gives ! us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ ! else if (TREE_OPERAND (decl, 1) ! && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) ! ctype = cname; ! else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM ! || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM) ! { ! /* This might be declaring a member of a template ! parm to be a friend. */ ! ctype = cname; ! dependant_name = TREE_OPERAND (decl, 1); ! } ! else if (ctype == NULL_TREE) ! ctype = cname; ! else if (TREE_COMPLEXITY (decl) == current_class_depth) ! ; ! else { ! if (! UNIQUELY_DERIVED_FROM_P (cname, ctype)) { ! error ("type `%T' is not derived from type `%T'", ! cname, ctype); ! ctype = NULL_TREE; } ! else ! ctype = cname; } ! /* It is valid to write: ! ! class C { void f(); }; ! typedef C D; ! void D::f(); ! ! The standard is not clear about whether `typedef const C D' is ! legal; as of 2002-09-15 the committee is considering ! that question. EDG 3.0 allows that syntax. ! Therefore, we do as well. */ ! if (ctype) ! ctype = TYPE_MAIN_VARIANT (ctype); ! /* Update the declarator so that when we process it ! again the correct type is present. */ ! TREE_OPERAND (decl, 0) = ctype; ! ! if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL ! && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)), ! ctype)) ! TREE_OPERAND (decl, 1) = constructor_name (ctype); ! next = &TREE_OPERAND (decl, 1); ! decl = *next; ! if (ctype) { ! tree name = decl; ! ! if (TREE_CODE (name) == BIT_NOT_EXPR) ! name = TREE_OPERAND (name, 0); ! if (!constructor_name_p (decl, ctype)) ! ; ! else if (decl == name) ! { ! sfk = sfk_constructor; ! ctor_return_type = ctype; ! } ! else { ! sfk = sfk_destructor; ! ctor_return_type = ctype; ! flags = DTOR_FLAG; ! TREE_OPERAND (decl, 0) = constructor_name (ctype); ! next = &TREE_OPERAND (decl, 0); } } ! } ! break; ! case ERROR_MARK: ! next = 0; ! break; ! case TYPE_DECL: ! /* Parse error puts this typespec where ! a declarator should go. */ ! error ("`%T' specified as declarator-id", DECL_NAME (decl)); ! if (TREE_TYPE (decl) == current_class_type) ! error (" perhaps you want `%T' for a constructor", ! current_class_name); ! dname = DECL_NAME (decl); ! name = IDENTIFIER_POINTER (dname); ! /* Avoid giving two errors for this. */ ! IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE; ! declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs); ! *next = dname; ! 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); ! return error_mark_node; break; ! default: ! my_friendly_assert (0, 20020917); } ! } ! } /* A function definition's declarator must have the form of a function declarator. */ ! if (funcdef_flag && innermost_code != CALL_EXPR) return 0; if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG) ! && innermost_code != CALL_EXPR ! && ! (ctype && declspecs == NULL_TREE)) { ! error ("declaration of `%D' as non-function", dname); ! return void_type_node; } /* Anything declared one level down from the top level --- 6440,6594 ---- /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ ! for (id_declarator = declarator; ! id_declarator; ! id_declarator = id_declarator->declarator) ! { ! if (id_declarator->kind != cdk_id) ! innermost_code = id_declarator->kind; ! switch (id_declarator->kind) ! { ! case cdk_function: ! if (id_declarator->declarator ! && id_declarator->declarator->kind == cdk_id) { ! sfk = id_declarator->declarator->u.id.sfk; ! if (sfk == sfk_destructor) ! flags = DTOR_FLAG; } ! break; ! case cdk_id: ! { ! tree qualifying_scope = id_declarator->u.id.qualifying_scope; ! tree decl = id_declarator->u.id.unqualified_name; ! if (!decl) ! break; ! if (qualifying_scope) { ! if (TYPE_P (qualifying_scope)) { ! ctype = qualifying_scope; ! if (innermost_code != cdk_function ! && current_class_type ! && !UNIQUELY_DERIVED_FROM_P (ctype, ! current_class_type)) ! { ! error ("type %qT is not derived from type %qT", ! ctype, current_class_type); ! return error_mark_node; ! } } + else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL) + in_namespace = qualifying_scope; } ! if (TREE_CODE (decl) == BASELINK) ! decl = BASELINK_FUNCTIONS (decl); ! if (decl == error_mark_node) ! return error_mark_node; ! switch (TREE_CODE (decl)) { ! case BIT_NOT_EXPR: { ! tree type; ! ! if (innermost_code != cdk_function) { ! error ("declaration of %qD as non-function", decl); ! return error_mark_node; } ! else if (!qualifying_scope ! && !(current_class_type && at_class_scope_p ())) ! { ! error ("declaration of %qD as non-member", decl); ! return error_mark_node; ! } ! ! type = TREE_OPERAND (decl, 0); ! name = IDENTIFIER_POINTER (constructor_name (type)); } + break; ! case TEMPLATE_ID_EXPR: { ! tree fns = TREE_OPERAND (decl, 0); ! dname = fns; ! if (TREE_CODE (dname) == COMPONENT_REF) ! dname = TREE_OPERAND (dname, 1); ! if (TREE_CODE (dname) != IDENTIFIER_NODE) { ! gcc_assert (is_overloaded_fn (dname)); ! dname = DECL_NAME (get_first_fn (dname)); } } ! /* Fall through. */ ! case IDENTIFIER_NODE: ! if (TREE_CODE (decl) == IDENTIFIER_NODE) ! dname = decl; ! if (C_IS_RESERVED_WORD (dname)) ! { ! error ("declarator-id missing; using reserved word %qD", ! dname); ! name = IDENTIFIER_POINTER (dname); ! } ! else if (!IDENTIFIER_TYPENAME_P (dname)) ! name = IDENTIFIER_POINTER (dname); ! else ! { ! gcc_assert (flags == NO_SPECIAL); ! flags = TYPENAME_FLAG; ! ctor_return_type = TREE_TYPE (dname); ! sfk = sfk_conversion; ! if (is_typename_at_global_scope (dname)) ! name = IDENTIFIER_POINTER (dname); ! else ! name = ""; ! } ! break; ! case TYPE_DECL: ! dname = constructor_name (TREE_TYPE (decl)); ! name = IDENTIFIER_POINTER (dname); ! break; ! default: ! gcc_unreachable (); ! } break; ! case cdk_array: ! case cdk_pointer: ! case cdk_reference: ! case cdk_ptrmem: break; ! case cdk_error: break; ! default: ! gcc_unreachable (); } ! } ! if (id_declarator->kind == cdk_id) ! break; ! } /* A function definition's declarator must have the form of a function declarator. */ ! if (funcdef_flag && innermost_code != cdk_function) return 0; if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG) ! && innermost_code != cdk_function ! && ! (ctype && !declspecs->any_specifiers_p)) { ! error ("declaration of %qD as non-function", dname); ! return error_mark_node; } /* Anything declared one level down from the top level *************** grokdeclarator (tree declarator, *** 6817,6960 **** if (name == NULL) name = decl_context == PARM ? "parameter" : "type name"; ! /* Look through the decl specs and record which ones appear. ! Some typespecs are defined as built-in typenames. ! Others, the ones that are modifiers of other types, ! are represented by bits in SPECBITS: set the bits for ! the modifiers that appear. Storage class keywords are also in SPECBITS. ! ! If there is a typedef name or a type, store the type in TYPE. ! This includes builtin typedefs such as `int'. ! ! Set EXPLICIT_INT if the type is `int' or `char' and did not ! come from a user typedef. ! ! Set LONGLONG if `long' is mentioned twice. ! ! For C++, constructors and destructors have their own fast treatment. */ ! ! for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) { ! int i; ! tree id; ! ! /* Certain parse errors slip through. For example, ! `int class;' is not caught by the parser. Try ! weakly to recover here. */ ! if (TREE_CODE (spec) != TREE_LIST) ! return 0; ! ! id = TREE_VALUE (spec); ! ! /* If the entire declaration is itself tagged as deprecated then ! suppress reports of deprecated items. */ ! if (!adding_implicit_members && id && TREE_DEPRECATED (id)) ! { ! if (deprecated_state != DEPRECATED_SUPPRESS) ! warn_deprecated_use (id); ! } ! ! if (TREE_CODE (id) == IDENTIFIER_NODE) ! { ! if (id == ridpointers[(int) RID_INT] ! || id == ridpointers[(int) RID_CHAR] ! || id == ridpointers[(int) RID_BOOL] ! || id == ridpointers[(int) RID_WCHAR]) ! { ! if (type) ! { ! if (id == ridpointers[(int) RID_BOOL]) ! error ("`bool' is now a keyword"); ! else ! error ("extraneous `%T' ignored", id); ! } ! else ! { ! if (id == ridpointers[(int) RID_INT]) ! explicit_int = 1; ! else if (id == ridpointers[(int) RID_CHAR]) ! explicit_char = 1; ! type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id)); ! } ! goto found; ! } ! /* C++ aggregate types. */ ! if (IDENTIFIER_HAS_TYPE_VALUE (id)) ! { ! if (type) ! error ("multiple declarations `%T' and `%T'", type, id); ! else ! type = IDENTIFIER_TYPE_VALUE (id); ! goto found; ! } ! ! for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++) ! { ! if (ridpointers[i] == id) ! { ! if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits)) ! { ! if (pedantic && ! in_system_header && warn_long_long) ! pedwarn ("ISO C++ does not support `long long'"); ! if (longlong) ! error ("`long long long' is too long for GCC"); ! else ! longlong = 1; ! } ! else if (RIDBIT_SETP (i, specbits)) ! pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); ! ! /* Diagnose "__thread extern" or "__thread static". */ ! if (RIDBIT_SETP (RID_THREAD, specbits)) ! { ! if (i == (int)RID_EXTERN) ! error ("`__thread' before `extern'"); ! else if (i == (int)RID_STATIC) ! 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; ! } ! } ! } ! else if (TREE_CODE (id) == TYPE_DECL) { ! if (type) ! error ("multiple declarations `%T' and `%T'", type, ! TREE_TYPE (id)); else ! { ! type = TREE_TYPE (id); ! TREE_VALUE (spec) = type; ! typedef_decl = id; ! } ! goto found; } ! if (type) ! error ("two or more data types in declaration of `%s'", name); ! else if (TREE_CODE (id) == IDENTIFIER_NODE) { ! tree t = lookup_name (id, 1); ! if (!t || TREE_CODE (t) != TYPE_DECL) ! error ("`%s' fails to be a typedef or built in type", ! IDENTIFIER_POINTER (id)); ! else ! { ! type = TREE_TYPE (t); ! typedef_decl = t; ! } } - else if (id != error_mark_node) - /* Can't change CLASS nodes into RECORD nodes here! */ - type = id; - - found: ; } #if 0 --- 6617,6692 ---- if (name == NULL) name = decl_context == PARM ? "parameter" : "type name"; ! /* If there were multiple types specified in the decl-specifier-seq, ! issue an error message. */ ! if (declspecs->multiple_types_p) ! error ("two or more data types in declaration of %qs", name); ! /* Extract the basic type from the decl-specifier-seq. */ ! type = declspecs->type; ! if (type == error_mark_node) { ! type = NULL_TREE; ! type_was_error_mark_node = true; ! } ! /* If the entire declaration is itself tagged as deprecated then ! suppress reports of deprecated items. */ ! if (type && TREE_DEPRECATED (type) ! && deprecated_state != DEPRECATED_SUPPRESS) ! warn_deprecated_use (type); ! if (type && TREE_CODE (type) == TYPE_DECL) ! { ! typedef_decl = type; ! type = TREE_TYPE (typedef_decl); ! } ! /* No type at all: default to `int', and set DEFAULTED_INT ! because it was not a user-defined typedef. */ ! if (type == NULL_TREE && (signed_p || unsigned_p || long_p || short_p)) ! { ! /* These imply 'int'. */ ! type = integer_type_node; ! defaulted_int = 1; ! } ! /* Gather flags. */ ! explicit_int = declspecs->explicit_int_p; ! explicit_char = declspecs->explicit_char_p; ! /* Check for repeated decl-specifiers. */ ! for (ds = ds_first; ds != ds_last; ++ds) ! { ! unsigned count = declspecs->specs[(int)ds]; ! if (count < 2) ! continue; ! /* The "long" specifier is a special case because of ! "long long". */ ! if (ds == ds_long) { ! if (count > 2) ! error ("% is too long for GCC"); ! else if (pedantic && !in_system_header && warn_long_long) ! pedwarn ("ISO C++ does not support %"); else ! longlong = 1; } ! else if (declspecs->specs[(int)ds] > 1) { ! static const char *const decl_spec_names[] = { ! "signed", ! "unsigned", ! "short", ! "long", ! "const", ! "volatile", ! "restrict", ! "inline", ! "virtual", ! "explicit", ! "friend", ! "typedef", ! "__complex", ! "__thread" ! }; ! error ("duplicate %qs", decl_spec_names[(int)ds]); } } #if 0 *************** grokdeclarator (tree declarator, *** 6964,6982 **** #endif typedef_type = type; - /* No type at all: default to `int', and set DEFAULTED_INT - because it was not a user-defined typedef. */ ! if (type == NULL_TREE ! && (RIDBIT_SETP (RID_SIGNED, specbits) ! || RIDBIT_SETP (RID_UNSIGNED, specbits) ! || RIDBIT_SETP (RID_LONG, specbits) ! || RIDBIT_SETP (RID_SHORT, specbits))) ! { ! /* These imply 'int'. */ ! type = integer_type_node; ! defaulted_int = 1; ! } if (sfk != sfk_none) type = check_special_function_return_type (sfk, type, --- 6696,6704 ---- #endif typedef_type = type; ! if (sfk != sfk_conversion) ! ctor_return_type = ctype; if (sfk != sfk_none) type = check_special_function_return_type (sfk, type, *************** grokdeclarator (tree declarator, *** 6996,7061 **** && in_namespace == NULL_TREE && current_namespace == global_namespace); ! if (in_system_header || flag_ms_extensions) /* Allow it, sigh. */; else if (pedantic || ! is_main) ! pedwarn ("ISO C++ forbids declaration of `%s' with no type", ! name); else if (warn_return_type) ! warning ("ISO C++ forbids declaration of `%s' with no type", ! name); type = integer_type_node; } ! ctype = NULL_TREE; /* Now process the modifiers that were specified and check for invalid combinations. */ /* Long double is a special combination. */ ! ! if (RIDBIT_SETP (RID_LONG, specbits) ! && TYPE_MAIN_VARIANT (type) == double_type_node) { ! RIDBIT_RESET (RID_LONG, specbits); type = build_qualified_type (long_double_type_node, cp_type_quals (type)); } /* Check all other uses of type modifiers. */ ! if (RIDBIT_SETP (RID_UNSIGNED, specbits) ! || RIDBIT_SETP (RID_SIGNED, specbits) ! || RIDBIT_SETP (RID_LONG, specbits) ! || RIDBIT_SETP (RID_SHORT, specbits)) { int ok = 0; if (TREE_CODE (type) == REAL_TYPE) ! error ("short, signed or unsigned invalid for `%s'", name); else if (TREE_CODE (type) != INTEGER_TYPE) ! error ("long, short, signed or unsigned invalid for `%s'", name); ! else if (RIDBIT_SETP (RID_LONG, specbits) ! && RIDBIT_SETP (RID_SHORT, specbits)) ! error ("long and short specified together for `%s'", name); ! else if ((RIDBIT_SETP (RID_LONG, specbits) ! || RIDBIT_SETP (RID_SHORT, specbits)) ! && explicit_char) ! error ("long or short specified with char for `%s'", name); ! else if ((RIDBIT_SETP (RID_LONG, specbits) ! || RIDBIT_SETP (RID_SHORT, specbits)) ! && TREE_CODE (type) == REAL_TYPE) ! error ("long or short specified with floating type for `%s'", name); ! else if (RIDBIT_SETP (RID_SIGNED, specbits) ! && RIDBIT_SETP (RID_UNSIGNED, specbits)) ! error ("signed and unsigned given together for `%s'", name); else { ok = 1; if (!explicit_int && !defaulted_int && !explicit_char && pedantic) { ! pedwarn ("long, short, signed or unsigned used invalidly for `%s'", name); if (flag_pedantic_errors) ok = 0; --- 6718,6772 ---- && in_namespace == NULL_TREE && current_namespace == global_namespace); ! if (type_was_error_mark_node) ! /* We've already issued an error, don't complain more. */; ! else if (in_system_header || flag_ms_extensions) /* Allow it, sigh. */; else if (pedantic || ! is_main) ! pedwarn ("ISO C++ forbids declaration of %qs with no type", name); else if (warn_return_type) ! warning ("ISO C++ forbids declaration of %qs with no type", name); type = integer_type_node; } ! ctype = NULL_TREE; /* Now process the modifiers that were specified and check for invalid combinations. */ /* Long double is a special combination. */ ! if (long_p && TYPE_MAIN_VARIANT (type) == double_type_node) { ! long_p = false; type = build_qualified_type (long_double_type_node, cp_type_quals (type)); } /* Check all other uses of type modifiers. */ ! if (unsigned_p || signed_p || long_p || short_p) { int ok = 0; if (TREE_CODE (type) == REAL_TYPE) ! error ("short, signed or unsigned invalid for %qs", name); else if (TREE_CODE (type) != INTEGER_TYPE) ! error ("long, short, signed or unsigned invalid for %qs", name); ! else if (long_p && short_p) ! error ("long and short specified together for %qs", name); ! else if ((long_p || short_p) && explicit_char) ! error ("long or short specified with char for %qs", name); ! else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE) ! error ("long or short specified with floating type for %qs", name); ! else if (signed_p && unsigned_p) ! error ("signed and unsigned given together for %qs", name); else { ok = 1; if (!explicit_int && !defaulted_int && !explicit_char && pedantic) { ! pedwarn ("long, short, signed or unsigned used invalidly for %qs", name); if (flag_pedantic_errors) ok = 0; *************** grokdeclarator (tree declarator, *** 7065,7088 **** /* Discard the type modifiers if they are invalid. */ if (! ok) { ! RIDBIT_RESET (RID_UNSIGNED, specbits); ! RIDBIT_RESET (RID_SIGNED, specbits); ! RIDBIT_RESET (RID_LONG, specbits); ! RIDBIT_RESET (RID_SHORT, specbits); longlong = 0; } } - if (RIDBIT_SETP (RID_COMPLEX, specbits) - && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) - { - error ("complex invalid for `%s'", name); - RIDBIT_RESET (RID_COMPLEX, specbits); - } - /* Decide whether an integer type is signed or not. Optionally treat bitfields as signed by default. */ ! if (RIDBIT_SETP (RID_UNSIGNED, specbits) /* [class.bit] It is implementation-defined whether a plain (neither --- 6776,6792 ---- /* Discard the type modifiers if they are invalid. */ if (! ok) { ! unsigned_p = false; ! signed_p = false; ! long_p = false; ! short_p = false; longlong = 0; } } /* Decide whether an integer type is signed or not. Optionally treat bitfields as signed by default. */ ! if (unsigned_p /* [class.bit] It is implementation-defined whether a plain (neither *************** grokdeclarator (tree declarator, *** 7092,7098 **** Naturally, we extend this to long long as well. Note that this does not include wchar_t. */ || (bitfield && !flag_signed_bitfields ! && RIDBIT_NOTSETP (RID_SIGNED, specbits) /* A typedef for plain `int' without `signed' can be controlled just like plain `int', but a typedef for `signed int' cannot be so controlled. */ --- 6796,6802 ---- Naturally, we extend this to long long as well. Note that this does not include wchar_t. */ || (bitfield && !flag_signed_bitfields ! && !signed_p /* A typedef for plain `int' without `signed' can be controlled just like plain `int', but a typedef for `signed int' cannot be so controlled. */ *************** grokdeclarator (tree declarator, *** 7104,7112 **** { if (longlong) type = long_long_unsigned_type_node; ! else if (RIDBIT_SETP (RID_LONG, specbits)) type = long_unsigned_type_node; ! else if (RIDBIT_SETP (RID_SHORT, specbits)) type = short_unsigned_type_node; else if (type == char_type_node) type = unsigned_char_type_node; --- 6808,6816 ---- { if (longlong) type = long_long_unsigned_type_node; ! else if (long_p) type = long_unsigned_type_node; ! else if (short_p) type = short_unsigned_type_node; else if (type == char_type_node) type = unsigned_char_type_node; *************** grokdeclarator (tree declarator, *** 7115,7142 **** else type = unsigned_type_node; } ! else if (RIDBIT_SETP (RID_SIGNED, specbits) ! && type == char_type_node) type = signed_char_type_node; else if (longlong) type = long_long_integer_type_node; ! else if (RIDBIT_SETP (RID_LONG, specbits)) type = long_integer_type_node; ! else if (RIDBIT_SETP (RID_SHORT, specbits)) type = short_integer_type_node; ! if (RIDBIT_SETP (RID_COMPLEX, specbits)) { /* If we just have "complex", it is equivalent to "complex double", but if any modifiers at all are specified it is the complex form of TYPE. E.g, "complex short" is "complex short int". */ ! if (defaulted_int && ! longlong ! && ! (RIDBIT_SETP (RID_LONG, specbits) ! || RIDBIT_SETP (RID_SHORT, specbits) ! || RIDBIT_SETP (RID_SIGNED, specbits) ! || RIDBIT_SETP (RID_UNSIGNED, specbits))) type = complex_double_type_node; else if (type == integer_type_node) type = complex_integer_type_node; --- 6819,6844 ---- else type = unsigned_type_node; } ! else if (signed_p && type == char_type_node) type = signed_char_type_node; else if (longlong) type = long_long_integer_type_node; ! else if (long_p) type = long_integer_type_node; ! else if (short_p) type = short_integer_type_node; ! if (declspecs->specs[(int)ds_complex]) { + if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) + error ("complex invalid for %qs", name); /* If we just have "complex", it is equivalent to "complex double", but if any modifiers at all are specified it is the complex form of TYPE. E.g, "complex short" is "complex short int". */ ! else if (defaulted_int && ! longlong ! && ! (long_p || short_p || signed_p || unsigned_p)) type = complex_double_type_node; else if (type == integer_type_node) type = complex_integer_type_node; *************** grokdeclarator (tree declarator, *** 7151,7217 **** } type_quals = TYPE_UNQUALIFIED; ! if (RIDBIT_SETP (RID_CONST, specbits)) type_quals |= TYPE_QUAL_CONST; ! if (RIDBIT_SETP (RID_VOLATILE, specbits)) type_quals |= TYPE_QUAL_VOLATILE; ! if (RIDBIT_SETP (RID_RESTRICT, specbits)) type_quals |= TYPE_QUAL_RESTRICT; if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED) ! error ("qualifiers are not allowed on declaration of `operator %T'", ! ctor_return_type); type_quals |= cp_type_quals (type); type = cp_build_qualified_type_real (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl) ? tf_ignore_bad_quals : 0) | tf_error | tf_warning)); /* We might have ignored or rejected some of the qualifiers. */ type_quals = cp_type_quals (type); ! staticp = 0; ! inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); ! virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); ! RIDBIT_RESET (RID_VIRTUAL, specbits); ! explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0; ! RIDBIT_RESET (RID_EXPLICIT, specbits); ! if (RIDBIT_SETP (RID_STATIC, specbits)) staticp = 1 + (decl_context == FIELD); if (virtualp && staticp == 2) { ! error ("member `%D' cannot be declared both virtual and static", ! dname); staticp = 0; } ! friendp = RIDBIT_SETP (RID_FRIEND, specbits); ! RIDBIT_RESET (RID_FRIEND, specbits); if (dependant_name && !friendp) { ! error ("`%T::%D' is not a valid declarator", ctype, dependant_name); return void_type_node; } - - /* Warn if two storage classes are given. Default to `auto'. */ ! if (RIDBIT_ANY_SET (specbits)) { ! 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)) - { - if (decl_context == PARM) - error ("typedef declaration invalid in parameter declaration"); - nclasses++; - } - if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++; - if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++; - if (!nclasses && !friendp && extern_langp) - nclasses++; } /* Give error if `virtual' is used outside of class declaration. */ --- 6853,6920 ---- } type_quals = TYPE_UNQUALIFIED; ! if (declspecs->specs[(int)ds_const]) type_quals |= TYPE_QUAL_CONST; ! if (declspecs->specs[(int)ds_volatile]) type_quals |= TYPE_QUAL_VOLATILE; ! if (declspecs->specs[(int)ds_restrict]) type_quals |= TYPE_QUAL_RESTRICT; if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED) ! error ("qualifiers are not allowed on declaration of %", ! ctor_return_type); + if (TREE_CODE (type) == FUNCTION_TYPE + && type_quals != TYPE_UNQUALIFIED) + { + /* This was an error in C++98 (cv-qualifiers cannot be added to + a function type), but DR 295 makes the code well-formed by + dropping the extra qualifiers. */ + if (pedantic) + { + tree bad_type = build_qualified_type (type, type_quals); + pedwarn ("ignoring %qV qualifiers added to function type %qT", + bad_type, type); + } + type_quals = TYPE_UNQUALIFIED; + } type_quals |= cp_type_quals (type); type = cp_build_qualified_type_real (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl) ? tf_ignore_bad_quals : 0) | tf_error | tf_warning)); /* We might have ignored or rejected some of the qualifiers. */ type_quals = cp_type_quals (type); ! staticp = 0; ! inlinep = !! declspecs->specs[(int)ds_inline]; ! virtualp = !! declspecs->specs[(int)ds_virtual]; ! explicitp = !! declspecs->specs[(int)ds_explicit]; ! storage_class = declspecs->storage_class; ! if (storage_class == sc_static) staticp = 1 + (decl_context == FIELD); if (virtualp && staticp == 2) { ! error ("member %qD cannot be declared both virtual and static", dname); staticp = 0; } ! friendp = !! declspecs->specs[(int)ds_friend]; if (dependant_name && !friendp) { ! error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name); return void_type_node; } ! /* Issue errors about use of storage classes for parameters. */ ! if (decl_context == PARM) { ! if (declspecs->specs[(int)ds_typedef]) ! error ("typedef declaration invalid in parameter declaration"); ! else if (storage_class == sc_static ! || storage_class == sc_extern ! || thread_p) error ("storage class specifiers invalid in parameter declarations"); } /* Give error if `virtual' is used outside of class declaration. */ *************** grokdeclarator (tree declarator, *** 7224,7256 **** /* Static anonymous unions are dealt with here. */ if (staticp && decl_context == TYPENAME ! && TREE_CODE (declspecs) == TREE_LIST ! && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs))) decl_context = FIELD; /* 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) { if ((decl_context == PARM || decl_context == CATCHPARM) ! && (RIDBIT_SETP (RID_REGISTER, specbits) ! || RIDBIT_SETP (RID_AUTO, specbits))) ; ! else if (RIDBIT_SETP (RID_TYPEDEF, specbits)) ; else if (decl_context == FIELD /* C++ allows static class elements. */ ! && RIDBIT_SETP (RID_STATIC, specbits)) /* C++ also allows inlines and signed and unsigned elements, but in those cases we don't come in here. */ ; --- 6927,6963 ---- /* Static anonymous unions are dealt with here. */ if (staticp && decl_context == TYPENAME ! && declspecs->type ! && ANON_AGGR_TYPE_P (declspecs->type)) decl_context = FIELD; /* Warn about storage classes that are invalid for certain kinds of declarations (parameters, typenames, etc.). */ ! if (declspecs->multiple_storage_classes_p) ! error ("multiple storage classes in declaration of %qs", name); ! else if (thread_p ! && ((storage_class ! && storage_class != sc_extern ! && storage_class != sc_static) ! || declspecs->specs[(int)ds_typedef])) ! { ! error ("multiple storage classes in declaration of %qs", name); ! thread_p = false; ! } ! else if (decl_context != NORMAL ! && ((storage_class != sc_none ! && storage_class != sc_mutable) ! || thread_p)) { if ((decl_context == PARM || decl_context == CATCHPARM) ! && (storage_class == sc_register ! || storage_class == sc_auto)) ; ! else if (declspecs->specs[(int)ds_typedef]) ; else if (decl_context == FIELD /* C++ allows static class elements. */ ! && storage_class == sc_static) /* C++ also allows inlines and signed and unsigned elements, but in those cases we don't come in here. */ ; *************** grokdeclarator (tree declarator, *** 7264,7273 **** if (declarator) { /* Avoid trying to get an operand off an identifier node. */ ! if (TREE_CODE (declarator) == IDENTIFIER_NODE) ! tmp = declarator; else ! tmp = TREE_OPERAND (declarator, 0); op = IDENTIFIER_OPNAME_P (tmp); if (IDENTIFIER_TYPENAME_P (tmp)) { --- 6971,6980 ---- if (declarator) { /* Avoid trying to get an operand off an identifier node. */ ! if (declarator->kind != cdk_id) ! tmp = declarator->declarator->u.id.unqualified_name; else ! tmp = declarator->u.id.unqualified_name; op = IDENTIFIER_OPNAME_P (tmp); if (IDENTIFIER_TYPENAME_P (tmp)) { *************** grokdeclarator (tree declarator, *** 7277,7432 **** name = ""; } } ! error ("storage class specified for %s `%s'", op ? "member operator" : "field", name); } else { if (decl_context == PARM || decl_context == CATCHPARM) ! error ("storage class specified for parameter `%s'", name); else error ("storage class specified for typename"); } ! 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) { if (toplevel_bindings_p ()) { /* It's common practice (and completely valid) to have a const be initialized and declared extern. */ if (!(type_quals & TYPE_QUAL_CONST)) ! warning ("`%s' initialized and declared `extern'", name); } else ! error ("`%s' has both `extern' and initializer", name); } ! else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag && ! toplevel_bindings_p ()) ! error ("nested function `%s' declared `extern'", name); else if (toplevel_bindings_p ()) { ! 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"); ! scope = get_scope_of_declarator (declarator); ! /* 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 abstract declarator). */ ! while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE ! && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) ! { ! /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]), ! an INDIRECT_REF (for *...), ! a CALL_EXPR (for ...(...)), ! an identifier (for the name being declared) ! or a null pointer (for the place in an absolute declarator ! where the name was omitted). ! For the last two cases, we have just exited the loop. ! For C++ it could also be ! a SCOPE_REF (for class :: ...). In this case, we have converted ! sensible names to types, and those are the values we use to ! qualify the member name. ! an ADDR_EXPR (for &...), ! a BIT_NOT_EXPR (for destructors) ! At this point, TYPE is the type of elements of an array, ! or for a function to return, or for a pointer to point to. ! After this sequence of ifs, TYPE is the type of the ! array or function or pointer, and DECLARATOR has had its ! outermost layer removed. */ if (type == error_mark_node) ! { ! if (declarator == error_mark_node) ! return error_mark_node; ! else if (TREE_CODE (declarator) == SCOPE_REF) ! declarator = TREE_OPERAND (declarator, 1); ! else ! declarator = TREE_OPERAND (declarator, 0); ! continue; ! } ! if (quals != NULL_TREE ! && (declarator == NULL_TREE ! || TREE_CODE (declarator) != SCOPE_REF)) ! { ! if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE) ! ctype = TYPE_METHOD_BASETYPE (type); ! if (ctype != NULL_TREE) ! { ! tree dummy = build_decl (TYPE_DECL, NULL_TREE, type); ! grok_method_quals (ctype, dummy, quals); ! type = TREE_TYPE (dummy); ! quals = NULL_TREE; ! } ! } ! switch (TREE_CODE (declarator)) { ! case TREE_LIST: ! { ! /* We encode a declarator with embedded attributes using ! a TREE_LIST. */ ! tree attrs = TREE_PURPOSE (declarator); ! tree inner_decl; ! int attr_flags; ! declarator = TREE_VALUE (declarator); ! inner_decl = declarator; ! while (inner_decl != NULL_TREE ! && TREE_CODE (inner_decl) == TREE_LIST) ! inner_decl = TREE_VALUE (inner_decl); ! attr_flags = 0; ! if (inner_decl == NULL_TREE ! || TREE_CODE (inner_decl) == IDENTIFIER_NODE) ! attr_flags |= (int) ATTR_FLAG_DECL_NEXT; ! if (TREE_CODE (inner_decl) == CALL_EXPR) ! attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; ! if (TREE_CODE (inner_decl) == ARRAY_REF) ! attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; ! returned_attrs = decl_attributes (&type, ! chainon (returned_attrs, attrs), ! attr_flags); ! } ! break; ! case ARRAY_REF: ! { ! tree size = TREE_OPERAND (declarator, 1); ! declarator = TREE_OPERAND (declarator, 0); ! type = create_array_type_for_decl (dname, type, size); ! ctype = NULL_TREE; ! } break; ! case CALL_EXPR: { tree arg_types; int funcdecl_p; - tree inner_parms = CALL_DECLARATOR_PARMS (declarator); - tree inner_decl = TREE_OPERAND (declarator, 0); /* Declaring a function type. Make sure we have a valid type for the function to return. */ --- 6984,7111 ---- name = ""; } } ! error ("storage class specified for %s %qs", op ? "member operator" : "field", name); } else { if (decl_context == PARM || decl_context == CATCHPARM) ! error ("storage class specified for parameter %qs", name); else error ("storage class specified for typename"); } ! if (storage_class == sc_register ! || storage_class == sc_auto ! || storage_class == sc_extern ! || thread_p) ! storage_class = sc_none; } } ! else if (storage_class == sc_extern && initialized ! && !funcdef_flag) { if (toplevel_bindings_p ()) { /* It's common practice (and completely valid) to have a const be initialized and declared extern. */ if (!(type_quals & TYPE_QUAL_CONST)) ! warning ("%qs initialized and declared %", name); } else ! error ("%qs has both % and initializer", name); } ! else if (storage_class == sc_extern && funcdef_flag && ! toplevel_bindings_p ()) ! error ("nested function %qs declared %", name); else if (toplevel_bindings_p ()) { ! if (storage_class == sc_auto) ! error ("top-level declaration of %qs specifies %", name); } ! else if (thread_p ! && storage_class != sc_extern ! && storage_class != sc_static) { ! error ("function-scope %qs implicitly auto and declared %<__thread%>", name); ! thread_p = false; } ! if (storage_class && friendp) error ("storage class specifiers invalid in friend function declarations"); ! if (!id_declarator) ! unqualified_id = NULL_TREE; ! else ! { ! unqualified_id = id_declarator->u.id.unqualified_name; ! if (TREE_CODE (unqualified_id) == BASELINK) ! unqualified_id = BASELINK_FUNCTIONS (unqualified_id); ! switch (TREE_CODE (unqualified_id)) ! { ! case BIT_NOT_EXPR: ! unqualified_id ! = constructor_name (TREE_OPERAND (unqualified_id, 0)); ! break; ! case TYPE_DECL: ! unqualified_id ! = constructor_name (TREE_TYPE (unqualified_id)); ! break; ! case IDENTIFIER_NODE: ! case TEMPLATE_ID_EXPR: ! break; ! default: ! gcc_unreachable (); ! } ! } ! /* Determine the type of the entity declared by recurring on the ! declarator. */ ! for (; declarator; declarator = declarator->declarator) ! { ! const cp_declarator *inner_declarator; ! tree attrs; if (type == error_mark_node) ! return error_mark_node; ! attrs = declarator->attributes; ! if (attrs) { ! int attr_flags; ! attr_flags = 0; ! if (declarator == NULL || declarator->kind == cdk_id) ! attr_flags |= (int) ATTR_FLAG_DECL_NEXT; ! if (declarator->kind == cdk_function) ! attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; ! if (declarator->kind == cdk_array) ! attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; ! returned_attrs = decl_attributes (&type, ! chainon (returned_attrs, attrs), ! attr_flags); ! } ! if (declarator->kind == cdk_id) ! break; ! inner_declarator = declarator->declarator; ! switch (declarator->kind) ! { ! case cdk_array: ! type = create_array_type_for_decl (dname, type, ! declarator->u.array.bounds); break; ! case cdk_function: { tree arg_types; int funcdecl_p; /* Declaring a function type. Make sure we have a valid type for the function to return. */ *************** grokdeclarator (tree declarator, *** 7439,7472 **** if (TREE_CODE (type) == FUNCTION_TYPE) { ! error ("`%s' declared as function returning a function", name); type = integer_type_node; } if (TREE_CODE (type) == ARRAY_TYPE) { ! error ("`%s' declared as function returning an array", name); type = integer_type_node; } - if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) - inner_decl = TREE_OPERAND (inner_decl, 1); - - if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR) - inner_decl = dname; - /* Pick up type qualifiers which should be applied to `this'. */ ! quals = CALL_DECLARATOR_QUALS (declarator); /* Pick up the exception specifications. */ ! raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator); /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ ! funcdecl_p ! = inner_decl ! && (TREE_CODE (inner_decl) == IDENTIFIER_NODE ! || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR ! || TREE_CODE (inner_decl) == BIT_NOT_EXPR); if (ctype == NULL_TREE && decl_context == FIELD --- 7118,7141 ---- if (TREE_CODE (type) == FUNCTION_TYPE) { ! error ("%qs declared as function returning a function", name); type = integer_type_node; } if (TREE_CODE (type) == ARRAY_TYPE) { ! error ("%qs declared as function returning an array", name); type = integer_type_node; } /* Pick up type qualifiers which should be applied to `this'. */ ! quals = declarator->u.function.qualifiers; /* Pick up the exception specifications. */ ! raises = declarator->u.function.exception_specification; /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ ! funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id; if (ctype == NULL_TREE && decl_context == FIELD *************** grokdeclarator (tree declarator, *** 7476,7482 **** if (ctype && sfk == sfk_conversion) TYPE_HAS_CONVERSION (ctype) = 1; ! if (ctype && constructor_name_p (dname, ctype)) { /* We are within a class's scope. If our declarator name is the same as the class name, and we are defining --- 7145,7152 ---- if (ctype && sfk == sfk_conversion) TYPE_HAS_CONVERSION (ctype) = 1; ! if (ctype && (sfk == sfk_constructor ! || sfk == sfk_destructor)) { /* We are within a class's scope. If our declarator name is the same as the class name, and we are defining *************** grokdeclarator (tree declarator, *** 7492,7500 **** error ("destructor cannot be static member function"); if (quals) { ! error ("destructors may not be `%s'", ! IDENTIFIER_POINTER (TREE_VALUE (quals))); ! quals = NULL_TREE; } if (decl_context == FIELD) { --- 7162,7169 ---- error ("destructor cannot be static member function"); if (quals) { ! error ("destructors may not be cv-qualified"); ! quals = TYPE_UNQUALIFIED; } if (decl_context == FIELD) { *************** grokdeclarator (tree declarator, *** 7521,7538 **** } if (quals) { ! error ("constructors may not be `%s'", ! IDENTIFIER_POINTER (TREE_VALUE (quals))); ! quals = NULL_TREE; } - { - RID_BIT_TYPE tmp_bits; - memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE)); - RIDBIT_RESET (RID_INLINE, tmp_bits); - RIDBIT_RESET (RID_STATIC, tmp_bits); - if (RIDBIT_ANY_SET (tmp_bits)) - error ("return value type specifier for constructor ignored"); - } if (decl_context == FIELD) { if (! member_function_or_else (ctype, --- 7190,7198 ---- } if (quals) { ! error ("constructors may not be cv-qualified"); ! quals = TYPE_UNQUALIFIED; } if (decl_context == FIELD) { if (! member_function_or_else (ctype, *************** grokdeclarator (tree declarator, *** 7550,7833 **** else if (friendp) { if (initialized) ! error ("can't initialize friend function `%s'", name); if (virtualp) { /* Cannot be both friend and virtual. */ error ("virtual functions cannot be friends"); - RIDBIT_RESET (RID_FRIEND, specbits); friendp = 0; } if (decl_context == NORMAL) error ("friend declaration not in class definition"); if (current_function_decl && funcdef_flag) ! error ("can't define friend function `%s' in a local class definition", ! name); } ! /* Construct the function type and go to the next ! inner layer of declarator. */ ! ! declarator = TREE_OPERAND (declarator, 0); ! ! arg_types = grokparms (inner_parms, &parms); ! if (declarator && flags == DTOR_FLAG) { ! /* A destructor declared in the body of a class will ! be represented as a BIT_NOT_EXPR. But, we just ! want the underlying IDENTIFIER. */ ! if (TREE_CODE (declarator) == BIT_NOT_EXPR) ! declarator = TREE_OPERAND (declarator, 0); ! ! if (arg_types != void_list_node) ! { ! error ("destructors may not have parameters"); ! arg_types = void_list_node; ! parms = NULL_TREE; ! } } - /* ANSI says that `const int foo ();' - does not make the function foo const. */ type = build_function_type (type, arg_types); } break; ! case ADDR_EXPR: ! case INDIRECT_REF: /* Filter out pointers-to-references and references-to-references. We can get these if a TYPE_DECL is used. */ if (TREE_CODE (type) == REFERENCE_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. */ /* We now know that the TYPE_QUALS don't apply to the decl, but to the target of the pointer. */ type_quals = TYPE_UNQUALIFIED; ! if (TREE_CODE (declarator) == ADDR_EXPR) { 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); /* Process a list of type modifier keywords (such as const or volatile) that were given inside the `*' or `&'. */ ! if (TREE_TYPE (declarator)) { ! tree typemodlist; ! int erred = 0; ! int constp = 0; ! int volatilep = 0; ! int restrictp = 0; ! ! for (typemodlist = TREE_TYPE (declarator); typemodlist; ! typemodlist = TREE_CHAIN (typemodlist)) ! { ! tree qualifier = TREE_VALUE (typemodlist); ! ! if (qualifier == ridpointers[(int) RID_CONST]) ! { ! constp++; ! type_quals |= TYPE_QUAL_CONST; ! } ! else if (qualifier == ridpointers[(int) RID_VOLATILE]) ! { ! volatilep++; ! type_quals |= TYPE_QUAL_VOLATILE; ! } ! else if (qualifier == ridpointers[(int) RID_RESTRICT]) ! { ! restrictp++; ! type_quals |= TYPE_QUAL_RESTRICT; ! } ! else if (!erred) ! { ! erred = 1; ! error ("invalid type modifier within pointer declarator"); ! } ! } ! if (constp > 1) ! pedwarn ("duplicate `const'"); ! if (volatilep > 1) ! pedwarn ("duplicate `volatile'"); ! if (restrictp > 1) ! pedwarn ("duplicate `restrict'"); ! type = cp_build_qualified_type (type, type_quals); type_quals = cp_type_quals (type); } - declarator = TREE_OPERAND (declarator, 0); ctype = NULL_TREE; break; ! case SCOPE_REF: ! { ! /* We have converted type names to NULL_TREE if the ! name was bogus, or to a _TYPE node, if not. ! ! The variable CTYPE holds the type we will ultimately ! resolve to. The code here just needs to build ! up appropriate member types. */ ! tree sname = TREE_OPERAND (declarator, 1); ! tree t; ! ! /* Destructors can have their visibilities changed as well. */ ! if (TREE_CODE (sname) == BIT_NOT_EXPR) ! sname = TREE_OPERAND (sname, 0); ! ! if (TREE_OPERAND (declarator, 0) == NULL_TREE) ! { ! /* We had a reference to a global decl, or ! perhaps we were given a non-aggregate typedef, ! in which case we cleared this out, and should just ! keep going as though it wasn't there. */ ! declarator = sname; ! continue; ! } ! ctype = TREE_OPERAND (declarator, 0); ! ! t = ctype; ! if (TREE_CODE (TREE_OPERAND (declarator, 1)) != INDIRECT_REF) ! while (t != NULL_TREE && CLASS_TYPE_P (t)) ! { ! /* You're supposed to have one `template <...>' ! for every template class, but you don't need one ! for a full specialization. For example: ! ! template struct S{}; ! template <> struct S { void f(); }; ! void S::f () {} ! ! is correct; there shouldn't be a `template <>' for ! the definition of `S::f'. */ ! if (CLASSTYPE_TEMPLATE_INFO (t) ! && (CLASSTYPE_TEMPLATE_INSTANTIATION (t) ! || uses_template_parms (CLASSTYPE_TI_ARGS (t))) ! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t))) ! template_count += 1; ! ! t = TYPE_MAIN_DECL (t); ! t = DECL_CONTEXT (t); ! } ! if (sname == NULL_TREE) ! goto done_scoping; ! if (TREE_CODE (sname) == IDENTIFIER_NODE) ! { ! /* This is the `standard' use of the scoping operator: ! basetype :: member . */ ! if (ctype == current_class_type) ! { ! /* class A { ! void A::f (); ! }; ! Is this ill-formed? */ ! if (pedantic) ! pedwarn ("extra qualification `%T::' on member `%s' ignored", ! ctype, name); ! } ! else if (TREE_CODE (type) == FUNCTION_TYPE) ! { ! if (NEW_DELETE_OPNAME_P (sname)) ! /* Overloaded operator new and operator delete ! are always static functions. */ ! ; ! else if (current_class_type == NULL_TREE || friendp) ! type ! = build_method_type_directly (ctype, ! TREE_TYPE (type), ! TYPE_ARG_TYPES (type)); ! else ! { ! error ("cannot declare member function `%T::%s' within `%T'", ! ctype, name, current_class_type); ! return error_mark_node; ! } ! } ! else if (RIDBIT_SETP (RID_TYPEDEF, specbits) ! || COMPLETE_TYPE_P (complete_type (ctype))) ! { ! /* Have to move this code elsewhere in this function. ! this code is used for i.e., typedef int A::M; M *pm; ! It is? How? jason 10/2/94 */ ! if (current_class_type) ! { ! error ("cannot declare member `%T::%s' within `%T'", ! ctype, name, current_class_type); ! return void_type_node; ! } ! } ! else ! { ! cxx_incomplete_type_error (NULL_TREE, ctype); ! return error_mark_node; ! } ! declarator = sname; ! } ! else if (TREE_CODE (sname) == SCOPE_REF) ! abort (); ! else ! { ! done_scoping: ! declarator = TREE_OPERAND (declarator, 1); ! 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_method_type_directly (ctype, ! TREE_TYPE (type), ! TYPE_ARG_TYPES (type)); ! } ! } ! break; ! case BIT_NOT_EXPR: ! declarator = TREE_OPERAND (declarator, 0); ! break; ! case BASELINK: ! declarator = BASELINK_FUNCTIONS (declarator); ! break; ! case RECORD_TYPE: ! case UNION_TYPE: ! case ENUMERAL_TYPE: ! declarator = NULL_TREE; ! break; ! case ERROR_MARK: ! declarator = NULL_TREE; ! break; ! default: ! abort (); } } --- 7210,7434 ---- else if (friendp) { if (initialized) ! error ("can't initialize friend function %qs", name); if (virtualp) { /* Cannot be both friend and virtual. */ error ("virtual functions cannot be friends"); friendp = 0; } if (decl_context == NORMAL) error ("friend declaration not in class definition"); if (current_function_decl && funcdef_flag) ! error ("can't define friend function %qs in a local " ! "class definition", ! name); } ! arg_types = grokparms (declarator->u.function.parameters, ! &parms); ! if (inner_declarator ! && inner_declarator->kind == cdk_id ! && inner_declarator->u.id.sfk == sfk_destructor ! && arg_types != void_list_node) { ! error ("destructors may not have parameters"); ! arg_types = void_list_node; ! parms = NULL_TREE; } type = build_function_type (type, arg_types); + type = cp_build_qualified_type (type, quals); } break; ! case cdk_pointer: ! case cdk_reference: ! case cdk_ptrmem: /* Filter out pointers-to-references and references-to-references. We can get these if a TYPE_DECL is used. */ if (TREE_CODE (type) == REFERENCE_TYPE) { ! error (declarator->kind == cdk_reference ! ? "cannot declare reference to %q#T" ! : "cannot declare pointer to %q#T", type); type = TREE_TYPE (type); } ! else if (VOID_TYPE_P (type)) ! { ! if (declarator->kind == cdk_reference) ! error ("cannot declare reference to %q#T", type); ! else if (declarator->kind == cdk_ptrmem) ! error ("cannot declare pointer to %q#T member", type); ! } /* We now know that the TYPE_QUALS don't apply to the decl, but to the target of the pointer. */ type_quals = TYPE_UNQUALIFIED; ! if (declarator->kind == cdk_ptrmem ! && (TREE_CODE (type) == FUNCTION_TYPE ! || (quals && TREE_CODE (type) == METHOD_TYPE))) ! { ! tree dummy; ! ! /* If the type is a FUNCTION_TYPE, pick up the ! qualifiers from that function type. No other ! qualifiers may be supplied. */ ! if (TREE_CODE (type) == FUNCTION_TYPE) ! quals = cp_type_quals (type); ! ! dummy = build_decl (TYPE_DECL, NULL_TREE, type); ! grok_method_quals (declarator->u.pointer.class_type, ! dummy, quals); ! type = TREE_TYPE (dummy); ! quals = TYPE_UNQUALIFIED; ! } ! ! if (declarator->kind == cdk_reference) { 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 (declarator->kind == cdk_ptrmem) ! { ! /* We might have parsed a namespace as the class type. */ ! if (TREE_CODE (declarator->u.pointer.class_type) ! == NAMESPACE_DECL) ! { ! error ("%qD is a namespace", ! declarator->u.pointer.class_type); ! type = build_pointer_type (type); ! } ! else if (declarator->u.pointer.class_type == error_mark_node) ! /* We will already have complained. */ ! type = error_mark_node; ! else ! type = build_ptrmem_type (declarator->u.pointer.class_type, ! type); ! } else type = build_pointer_type (type); /* Process a list of type modifier keywords (such as const or volatile) that were given inside the `*' or `&'. */ ! if (declarator->u.pointer.qualifiers) { ! type ! = cp_build_qualified_type (type, ! declarator->u.pointer.qualifiers); type_quals = cp_type_quals (type); } ctype = NULL_TREE; break; ! case cdk_error: ! break; ! default: ! gcc_unreachable (); ! } ! } ! if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR ! && TREE_CODE (type) != FUNCTION_TYPE ! && TREE_CODE (type) != METHOD_TYPE) ! { ! error ("template-id %qD used as a declarator", ! unqualified_id); ! unqualified_id = dname; ! } ! /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator; ! otherwise, we would not have exited the loop above. */ ! if (declarator ! && declarator->u.id.qualifying_scope ! && TYPE_P (declarator->u.id.qualifying_scope)) ! { ! tree t; ! ctype = declarator->u.id.qualifying_scope; ! ctype = TYPE_MAIN_VARIANT (ctype); ! t = ctype; ! while (t != NULL_TREE && CLASS_TYPE_P (t)) ! { ! /* You're supposed to have one `template <...>' for every ! template class, but you don't need one for a full ! specialization. For example: ! template struct S{}; ! template <> struct S { void f(); }; ! void S::f () {} ! is correct; there shouldn't be a `template <>' for the ! definition of `S::f'. */ ! if (CLASSTYPE_TEMPLATE_INFO (t) ! && (CLASSTYPE_TEMPLATE_INSTANTIATION (t) ! || uses_template_parms (CLASSTYPE_TI_ARGS (t))) ! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t))) ! template_count += 1; ! t = TYPE_MAIN_DECL (t); ! t = DECL_CONTEXT (t); ! } ! if (ctype == current_class_type) ! { ! /* class A { ! void A::f (); ! }; ! Is this ill-formed? */ ! if (pedantic) ! pedwarn ("extra qualification %<%T::%> on member %qs ignored", ! ctype, name); ! } ! else if (TREE_CODE (type) == FUNCTION_TYPE) ! { ! tree sname = declarator->u.id.unqualified_name; ! if (TREE_CODE (sname) == IDENTIFIER_NODE ! && NEW_DELETE_OPNAME_P (sname)) ! /* Overloaded operator new and operator delete ! are always static functions. */ ! ; ! else if (current_class_type == NULL_TREE || friendp) ! type ! = build_method_type_directly (ctype, ! TREE_TYPE (type), ! TYPE_ARG_TYPES (type)); ! else ! { ! error ("cannot declare member function %<%T::%s%> within %<%T%>", ! ctype, name, current_class_type); ! return error_mark_node; ! } ! } ! else if (declspecs->specs[(int)ds_typedef] ! || COMPLETE_TYPE_P (complete_type (ctype))) ! { ! /* Have to move this code elsewhere in this function. ! this code is used for i.e., typedef int A::M; M *pm; ! It is? How? jason 10/2/94 */ ! if (current_class_type) ! { ! error ("cannot declare member %<%T::%s%> within %qT", ! ctype, name, current_class_type); ! return void_type_node; ! } ! } ! else ! { ! cxx_incomplete_type_error (NULL_TREE, ctype); ! return error_mark_node; } } *************** grokdeclarator (tree declarator, *** 7847,7866 **** && COMPLETE_TYPE_P (type) && TREE_OVERFLOW (TYPE_SIZE (type))) { ! error ("size of array `%s' is too large", name); /* If we proceed with the array type as it is, we'll eventually crash in tree_low_cst(). */ type = error_mark_node; } if ((decl_context == FIELD || decl_context == PARM) ! && !processing_template_decl ! && variably_modified_type_p (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; } --- 7448,7467 ---- && COMPLETE_TYPE_P (type) && TREE_OVERFLOW (TYPE_SIZE (type))) { ! error ("size of array %qs is too large", name); /* If we proceed with the array type as it is, we'll eventually crash in tree_low_cst(). */ type = error_mark_node; } if ((decl_context == FIELD || decl_context == PARM) ! && !processing_template_decl ! && variably_modified_type_p (type, NULL_TREE)) { if (decl_context == FIELD) ! error ("data member may not have variably modified type %qT", type); else ! error ("parameter may not have variably modified type %qT", type); type = error_mark_node; } *************** grokdeclarator (tree declarator, *** 7868,7925 **** { /* [dcl.fct.spec] The explicit specifier shall only be used in declarations of constructors within a class definition. */ ! error ("only declarations of constructors can be `explicit'"); explicitp = 0; } ! if (RIDBIT_SETP (RID_MUTABLE, specbits)) { if (decl_context != FIELD || friendp) { ! error ("non-member `%s' cannot be declared `mutable'", name); ! RIDBIT_RESET (RID_MUTABLE, specbits); } ! else if (decl_context == TYPENAME || RIDBIT_SETP (RID_TYPEDEF, specbits)) { ! error ("non-object member `%s' cannot be declared `mutable'", name); ! RIDBIT_RESET (RID_MUTABLE, specbits); } else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) { ! error ("function `%s' cannot be declared `mutable'", name); ! RIDBIT_RESET (RID_MUTABLE, specbits); } else if (staticp) { ! error ("static `%s' cannot be declared `mutable'", name); ! RIDBIT_RESET (RID_MUTABLE, specbits); } else if (type_quals & TYPE_QUAL_CONST) { ! error ("const `%s' cannot be declared `mutable'", name); ! RIDBIT_RESET (RID_MUTABLE, specbits); } } - if (declarator == NULL_TREE - || TREE_CODE (declarator) == IDENTIFIER_NODE - || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR - && (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE))) - /* OK */; - else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) - { - error ("template-id `%D' used as a declarator", declarator); - declarator = dname; - } - else - /* Unexpected declarator format. */ - abort (); - /* If this is declaring a typedef name, return a TYPE_DECL. */ ! ! if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME) { tree decl; --- 7469,7510 ---- { /* [dcl.fct.spec] The explicit specifier shall only be used in declarations of constructors within a class definition. */ ! error ("only declarations of constructors can be %"); explicitp = 0; } ! if (storage_class == sc_mutable) { if (decl_context != FIELD || friendp) { ! error ("non-member %qs cannot be declared %", name); ! storage_class = sc_none; } ! else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef]) { ! error ("non-object member %qs cannot be declared %", name); ! storage_class = sc_none; } else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) { ! error ("function %qs cannot be declared %", name); ! storage_class = sc_none; } else if (staticp) { ! error ("static %qs cannot be declared %", name); ! storage_class = sc_none; } else if (type_quals & TYPE_QUAL_CONST) { ! error ("const %qs cannot be declared %", name); ! storage_class = sc_none; } } /* If this is declaring a typedef name, return a TYPE_DECL. */ ! if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME) { tree decl; *************** grokdeclarator (tree declarator, *** 7929,7955 **** TYPE_FOR_JAVA (type) = 1; if (decl_context == FIELD) ! { ! if (constructor_name_p (declarator, current_class_type)) ! pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class", ! declarator); ! decl = build_lang_decl (TYPE_DECL, declarator, type); ! } else { - decl = build_decl (TYPE_DECL, declarator, type); - if (in_namespace || ctype) - error ("%Jtypedef name may not be a nested-name-specifier", decl); if (!current_function_decl) DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); } ! /* If the user declares "typedef struct {...} foo" then the struct will have an anonymous name. Fill that name in now. Nothing can refer to it, so nothing needs know about the name change. */ if (type != error_mark_node ! && declarator && TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && TYPE_ANONYMOUS_P (type) --- 7514,7549 ---- TYPE_FOR_JAVA (type) = 1; if (decl_context == FIELD) ! decl = build_lang_decl (TYPE_DECL, unqualified_id, type); else + decl = build_decl (TYPE_DECL, unqualified_id, type); + if (id_declarator && declarator->u.id.qualifying_scope) + error ("%Jtypedef name may not be a nested-name-specifier", decl); + + if (decl_context != FIELD) { if (!current_function_decl) DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl) + || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P + (current_function_decl))) + /* The TYPE_DECL is "abstract" because there will be + clones of this constructor/destructor, and there will + be copies of this TYPE_DECL generated in those + clones. */ + DECL_ABSTRACT (decl) = 1; } ! else if (constructor_name_p (unqualified_id, current_class_type)) ! pedwarn ("ISO C++ forbids nested type %qD with same name " ! "as enclosing class", ! unqualified_id); ! /* If the user declares "typedef struct {...} foo" then the struct will have an anonymous name. Fill that name in now. Nothing can refer to it, so nothing needs know about the name change. */ if (type != error_mark_node ! && unqualified_id && TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && TYPE_ANONYMOUS_P (type) *************** grokdeclarator (tree declarator, *** 7961,7967 **** tree t; /* Replace the anonymous name with the real name everywhere. */ - lookup_tag_reverse (type, declarator); for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) if (TYPE_NAME (t) == oldname) TYPE_NAME (t) = decl; --- 7555,7560 ---- *************** grokdeclarator (tree declarator, *** 7984,8004 **** { if (ctype == NULL_TREE) { ! if (TREE_CODE (type) != METHOD_TYPE) ! error ("%Jinvalid type qualifier for non-member function type", ! decl); ! else ctype = TYPE_METHOD_BASETYPE (type); } if (ctype != NULL_TREE) grok_method_quals (ctype, decl, quals); } ! if (RIDBIT_SETP (RID_SIGNED, specbits) || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; ! bad_specifiers (decl, "type", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); return decl; --- 7577,7598 ---- { if (ctype == NULL_TREE) { ! if (TREE_CODE (type) == METHOD_TYPE) ctype = TYPE_METHOD_BASETYPE (type); + /* Any qualifiers on a function type typedef have + already been dealt with. */ + else if (TREE_CODE (type) == FUNCTION_TYPE) + quals = TYPE_UNQUALIFIED; } if (ctype != NULL_TREE) grok_method_quals (ctype, decl, quals); } ! if (signed_p || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; ! bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); return decl; *************** grokdeclarator (tree declarator, *** 8016,8022 **** /* Detect where we're using a typedef of function type to declare a function. PARMS will not be set, so we must create it now. */ ! if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE) { tree decls = NULL_TREE; --- 7610,7616 ---- /* Detect where we're using a typedef of function type to declare a function. PARMS will not be set, so we must create it now. */ ! if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE) { tree decls = NULL_TREE; *************** grokdeclarator (tree declarator, *** 8029,8036 **** TREE_CHAIN (decl) = decls; decls = decl; } ! parms = nreverse (decls); } /* If this is a type name (such as, in a cast or sizeof), --- 7623,7647 ---- TREE_CHAIN (decl) = decls; decls = decl; } ! parms = nreverse (decls); + + if (decl_context != TYPENAME) + { + /* A cv-qualifier-seq shall only be part of the function type + for a non-static member function. [8.3.5/4 dcl.fct] */ + if (cp_type_quals (type) != TYPE_UNQUALIFIED + && (current_class_type == NULL_TREE || staticp) ) + { + error ("qualified function types cannot be used to declare %s functions", + (staticp? "static member" : "free")); + type = TYPE_MAIN_VARIANT (type); + } + + /* The qualifiers on the function type become the qualifiers on + the non-static member function. */ + quals |= cp_type_quals (type); + } } /* If this is a type name (such as, in a cast or sizeof), *************** grokdeclarator (tree declarator, *** 8053,8059 **** } if (inlinep) { ! error ("`inline' specified for friend class declaration"); inlinep = 0; } --- 7664,7670 ---- } if (inlinep) { ! error ("% specified for friend class declaration"); inlinep = 0; } *************** grokdeclarator (tree declarator, *** 8064,8074 **** pedwarn ("template parameters cannot be friends"); else if (TREE_CODE (type) == TYPENAME_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); } --- 7675,7685 ---- pedwarn ("template parameters cannot be friends"); else if (TREE_CODE (type) == TYPENAME_TYPE) pedwarn ("friend declaration requires class-key, " ! "i.e. %", TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type)); else pedwarn ("friend declaration requires class-key, " ! "i.e. %", type); } *************** grokdeclarator (tree declarator, *** 8080,8087 **** make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type), /*complain=*/true); else ! error ("trying to make class `%T' a friend of global scope", ! type); type = void_type_node; } --- 7691,7698 ---- make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type), /*complain=*/true); else ! error ("trying to make class %qT a friend of global scope", ! type); type = void_type_node; } *************** grokdeclarator (tree declarator, *** 8097,8103 **** } if (ctype) { ! tree dummy = build_decl (TYPE_DECL, declarator, type); grok_method_quals (ctype, dummy, quals); type = TREE_TYPE (dummy); } --- 7708,7714 ---- } if (ctype) { ! tree dummy = build_decl (TYPE_DECL, unqualified_id, type); grok_method_quals (ctype, dummy, quals); type = TREE_TYPE (dummy); } *************** grokdeclarator (tree declarator, *** 8105,8134 **** return type; } ! else if (declarator == NULL_TREE && decl_context != PARM && decl_context != CATCHPARM && TREE_CODE (type) != UNION_TYPE && ! bitfield) { ! error ("abstract declarator `%T' used as declaration", type); return error_mark_node; } /* Only functions may be declared using an operator-function-id. */ ! if (declarator ! && TREE_CODE (declarator) == IDENTIFIER_NODE ! && IDENTIFIER_OPNAME_P (declarator) && TREE_CODE (type) != FUNCTION_TYPE && TREE_CODE (type) != METHOD_TYPE) { ! error ("declaration of `%D' as non-function", declarator); return error_mark_node; } /* We don't check parameter types here because we can emit a better error message later. */ if (decl_context != PARM) ! type = check_var_type (declarator, type); /* Now create the decl, which may be a VAR_DECL, a PARM_DECL or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */ --- 7716,7744 ---- return type; } ! else if (unqualified_id == NULL_TREE && decl_context != PARM && decl_context != CATCHPARM && TREE_CODE (type) != UNION_TYPE && ! bitfield) { ! error ("abstract declarator %qT used as declaration", type); return error_mark_node; } /* Only functions may be declared using an operator-function-id. */ ! if (unqualified_id ! && IDENTIFIER_OPNAME_P (unqualified_id) && TREE_CODE (type) != FUNCTION_TYPE && TREE_CODE (type) != METHOD_TYPE) { ! error ("declaration of %qD as non-function", unqualified_id); return error_mark_node; } /* We don't check parameter types here because we can emit a better error message later. */ if (decl_context != PARM) ! type = check_var_type (unqualified_id, type); /* Now create the decl, which may be a VAR_DECL, a PARM_DECL or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */ *************** grokdeclarator (tree declarator, *** 8136,8142 **** if (decl_context == PARM || decl_context == CATCHPARM) { if (ctype || in_namespace) ! error ("cannot use `::' in parameter declaration"); /* A parameter declared as an array of T is really a pointer to T. One declared as a function is really a pointer to a function. --- 7746,7752 ---- if (decl_context == PARM || decl_context == CATCHPARM) { if (ctype || in_namespace) ! error ("cannot use %<::%> in parameter declaration"); /* A parameter declared as an array of T is really a pointer to T. One declared as a function is really a pointer to a function. *************** grokdeclarator (tree declarator, *** 8157,8165 **** if (decl_context == PARM) { ! decl = cp_build_parm_decl (declarator, type); ! bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); } else if (decl_context == FIELD) --- 7767,7775 ---- if (decl_context == PARM) { ! decl = cp_build_parm_decl (unqualified_id, type); ! bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); } else if (decl_context == FIELD) *************** grokdeclarator (tree declarator, *** 8181,8187 **** else if (in_namespace && !friendp) { /* Something like struct S { int N::j; }; */ ! error ("invalid use of `::'"); decl = NULL_TREE; } else if (TREE_CODE (type) == FUNCTION_TYPE) --- 7791,7797 ---- else if (in_namespace && !friendp) { /* Something like struct S { int N::j; }; */ ! error ("invalid use of %<::%>"); decl = NULL_TREE; } else if (TREE_CODE (type) == FUNCTION_TYPE) *************** grokdeclarator (tree declarator, *** 8189,8203 **** int publicp = 0; tree function_context; - /* We catch the others as conflicts with the builtin - typedefs. */ - if (friendp && declarator == ridpointers[(int) RID_SIGNED]) - { - error ("function `%D' cannot be declared friend", - declarator); - friendp = 0; - } - if (friendp == 0) { if (ctype == NULL_TREE) --- 7799,7804 ---- *************** grokdeclarator (tree declarator, *** 8205,8212 **** if (ctype == NULL_TREE) { ! error ("can't make `%D' into a method -- not in a class", ! declarator); return void_type_node; } --- 7806,7813 ---- if (ctype == NULL_TREE) { ! error ("can't make %qD into a method -- not in a class", ! unqualified_id); return void_type_node; } *************** grokdeclarator (tree declarator, *** 8214,8252 **** ARM 9.5 */ if (virtualp && TREE_CODE (ctype) == UNION_TYPE) { ! error ("function `%D' declared virtual inside a union", ! declarator); return void_type_node; } ! if (NEW_DELETE_OPNAME_P (declarator)) { if (virtualp) { ! error ("`%D' cannot be declared virtual, since it is always static", ! declarator); virtualp = 0; } } else if (staticp < 2) ! type = build_method_type_directly (ctype, TREE_TYPE (type), TYPE_ARG_TYPES (type)); } /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ function_context = (ctype != NULL_TREE) ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE; publicp = (! friendp || ! staticp) && function_context == NULL_TREE; decl = grokfndecl (ctype, type, ! TREE_CODE (declarator) != TEMPLATE_ID_EXPR ! ? declarator : dname, parms, ! declarator, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, publicp, inlinep, ! funcdef_flag, template_count, in_namespace); if (decl == NULL_TREE) return decl; #if 0 --- 7815,7867 ---- ARM 9.5 */ if (virtualp && TREE_CODE (ctype) == UNION_TYPE) { ! error ("function %qD declared virtual inside a union", ! unqualified_id); return void_type_node; } ! if (NEW_DELETE_OPNAME_P (unqualified_id)) { if (virtualp) { ! error ("%qD cannot be declared virtual, since it " ! "is always static", ! unqualified_id); virtualp = 0; } } else if (staticp < 2) ! type = build_method_type_directly (ctype, TREE_TYPE (type), TYPE_ARG_TYPES (type)); } + /* Check that the name used for a destructor makes sense. */ + if (sfk == sfk_destructor + && !same_type_p (TREE_OPERAND + (id_declarator->u.id.unqualified_name, 0), + ctype)) + { + error ("declaration of %qD as member of %qT", + id_declarator->u.id.unqualified_name, + ctype); + return error_mark_node; + } + /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ function_context = (ctype != NULL_TREE) ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE; publicp = (! friendp || ! staticp) && function_context == NULL_TREE; decl = grokfndecl (ctype, type, ! TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR ! ? unqualified_id : dname, parms, ! unqualified_id, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, publicp, inlinep, ! sfk, ! funcdef_flag, template_count, in_namespace, attrlist); if (decl == NULL_TREE) return decl; #if 0 *************** grokdeclarator (tree declarator, *** 8287,8299 **** /* All method decls are public, so tell grokfndecl to set TREE_PUBLIC, also. */ decl = grokfndecl (ctype, type, ! TREE_CODE (declarator) != TEMPLATE_ID_EXPR ! ? declarator : dname, parms, ! declarator, virtualp, flags, quals, raises, ! friendp ? -1 : 0, friendp, 1, 0, funcdef_flag, ! template_count, in_namespace); if (decl == NULL_TREE) return NULL_TREE; } --- 7902,7915 ---- /* All method decls are public, so tell grokfndecl to set TREE_PUBLIC, also. */ decl = grokfndecl (ctype, type, ! TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR ! ? unqualified_id : dname, parms, ! unqualified_id, virtualp, flags, quals, raises, ! friendp ? -1 : 0, friendp, 1, 0, sfk, ! funcdef_flag, template_count, in_namespace, ! attrlist); if (decl == NULL_TREE) return NULL_TREE; } *************** grokdeclarator (tree declarator, *** 8301,8320 **** && !COMPLETE_TYPE_P (complete_type (type)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { ! if (declarator) ! error ("field `%D' has incomplete type", declarator); else ! error ("name `%T' has incomplete type", type); /* If we're instantiating a template, tell them which instantiation made the field's type be incomplete. */ if (current_class_type && TYPE_NAME (current_class_type) && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)) ! && declspecs && TREE_VALUE (declspecs) ! && TREE_TYPE (TREE_VALUE (declspecs)) == type) ! error (" in instantiation of template `%T'", ! current_class_type); type = error_mark_node; decl = NULL_TREE; --- 7917,7936 ---- && !COMPLETE_TYPE_P (complete_type (type)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { ! if (unqualified_id) ! error ("field %qD has incomplete type", unqualified_id); else ! error ("name %qT has incomplete type", type); /* If we're instantiating a template, tell them which instantiation made the field's type be incomplete. */ if (current_class_type && TYPE_NAME (current_class_type) && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)) ! && declspecs->type ! && declspecs->type == type) ! error (" in instantiation of template %qT", ! current_class_type); type = error_mark_node; decl = NULL_TREE; *************** grokdeclarator (tree declarator, *** 8323,8330 **** { if (friendp) { ! error ("`%s' is neither function nor member function; cannot be declared friend", ! IDENTIFIER_POINTER (declarator)); friendp = 0; } decl = NULL_TREE; --- 7939,7946 ---- { if (friendp) { ! error ("%qE is neither function nor member function; " ! "cannot be declared friend", unqualified_id); friendp = 0; } decl = NULL_TREE; *************** grokdeclarator (tree declarator, *** 8340,8352 **** if (template_class_depth (current_class_type) == 0) { decl = check_explicit_specialization ! (declarator, decl, template_count, 2 * (funcdef_flag != 0) + 4); if (decl == error_mark_node) return error_mark_node; } ! ! decl = do_friend (ctype, declarator, decl, *attrlist, flags, quals, funcdef_flag); return decl; } --- 7956,7968 ---- if (template_class_depth (current_class_type) == 0) { decl = check_explicit_specialization ! (unqualified_id, decl, template_count, 2 * (funcdef_flag != 0) + 4); if (decl == error_mark_node) return error_mark_node; } ! ! decl = do_friend (ctype, unqualified_id, decl, *attrlist, flags, quals, funcdef_flag); return decl; } *************** grokdeclarator (tree declarator, *** 8374,8389 **** the rest of the compiler does not correctly handle the initialization unless the member is static so we make it static below. */ ! pedwarn ("ISO C++ forbids initialization of member `%D'", ! declarator); ! pedwarn ("making `%D' static", declarator); staticp = 1; } if (uses_template_parms (type)) /* We'll check at instantiation time. */ ; ! else if (check_static_variable_definition (declarator, type)) /* If we just return the declaration, crashes will sometimes occur. We therefore return --- 7990,8005 ---- the rest of the compiler does not correctly handle the initialization unless the member is static so we make it static below. */ ! pedwarn ("ISO C++ forbids initialization of member %qD", ! unqualified_id); ! pedwarn ("making %qD static", unqualified_id); staticp = 1; } if (uses_template_parms (type)) /* We'll check at instantiation time. */ ; ! else if (check_static_variable_definition (unqualified_id, type)) /* If we just return the declaration, crashes will sometimes occur. We therefore return *************** grokdeclarator (tree declarator, *** 8397,8419 **** { /* C++ allows static class members. All other work for this is done by grokfield. */ ! decl = build_lang_decl (VAR_DECL, declarator, type); ! TREE_STATIC (decl) = 1; ! /* In class context, 'static' means public access. */ ! TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1; } else { ! decl = build_decl (FIELD_DECL, declarator, type); DECL_NONADDRESSABLE_P (decl) = bitfield; ! if (RIDBIT_SETP (RID_MUTABLE, specbits)) { DECL_MUTABLE_P (decl) = 1; ! RIDBIT_RESET (RID_MUTABLE, specbits); } } ! bad_specifiers (decl, "field", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); } } --- 8013,8037 ---- { /* C++ allows static class members. All other work for this is done by grokfield. */ ! decl = build_lang_decl (VAR_DECL, unqualified_id, type); ! set_linkage_for_static_data_member (decl); ! /* Even if there is an in-class initialization, DECL ! is considered undefined until an out-of-class ! definition is provided. */ ! DECL_EXTERNAL (decl) = 1; } else { ! decl = build_decl (FIELD_DECL, unqualified_id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; ! if (storage_class == sc_mutable) { DECL_MUTABLE_P (decl) = 1; ! storage_class = sc_none; } } ! bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); } } *************** grokdeclarator (tree declarator, *** 8423,8481 **** tree original_name; int publicp = 0; ! if (! declarator) return NULL_TREE; ! if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) original_name = dname; else ! original_name = declarator; ! if (RIDBIT_SETP (RID_AUTO, specbits)) ! error ("storage class `auto' invalid for function `%s'", name); ! else if (RIDBIT_SETP (RID_REGISTER, specbits)) ! 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 and `extern' makes no difference. */ if (! toplevel_bindings_p () ! && (RIDBIT_SETP (RID_STATIC, specbits) ! || RIDBIT_SETP (RID_INLINE, specbits)) && pedantic) { ! if (RIDBIT_SETP (RID_STATIC, specbits)) ! pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name); else ! pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name); } if (ctype == NULL_TREE) { if (virtualp) { ! error ("virtual non-class function `%s'", name); virtualp = 0; } } else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 && !NEW_DELETE_OPNAME_P (original_name)) ! type = build_method_type_directly (ctype, TREE_TYPE (type), TYPE_ARG_TYPES (type)); /* Record presence of `static'. */ publicp = (ctype != NULL_TREE ! || RIDBIT_SETP (RID_EXTERN, specbits) ! || !RIDBIT_SETP (RID_STATIC, specbits)); ! decl = grokfndecl (ctype, type, original_name, parms, declarator, virtualp, flags, quals, raises, 1, friendp, ! publicp, inlinep, funcdef_flag, ! template_count, in_namespace); if (decl == NULL_TREE) return NULL_TREE; --- 8041,8101 ---- tree original_name; int publicp = 0; ! if (!unqualified_id) return NULL_TREE; ! if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR) original_name = dname; else ! original_name = unqualified_id; ! if (storage_class == sc_auto) ! error ("storage class % invalid for function %qs", name); ! else if (storage_class == sc_register) ! error ("storage class % invalid for function %qs", name); ! else if (thread_p) ! error ("storage class %<__thread%> invalid for function %qs", name); /* Function declaration not at top level. Storage classes other than `extern' are not allowed and `extern' makes no difference. */ if (! toplevel_bindings_p () ! && (storage_class == sc_static ! || declspecs->specs[(int)ds_inline]) && pedantic) { ! if (storage_class == sc_static) ! pedwarn ("% specified invalid for function %qs " ! "declared out of global scope", name); else ! pedwarn ("% specifier invalid for function %qs " ! "declared out of global scope", name); } if (ctype == NULL_TREE) { if (virtualp) { ! error ("virtual non-class function %qs", name); virtualp = 0; } } else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 && !NEW_DELETE_OPNAME_P (original_name)) ! type = build_method_type_directly (ctype, TREE_TYPE (type), TYPE_ARG_TYPES (type)); /* Record presence of `static'. */ publicp = (ctype != NULL_TREE ! || storage_class == sc_extern ! || storage_class != sc_static); ! decl = grokfndecl (ctype, type, original_name, parms, unqualified_id, virtualp, flags, quals, raises, 1, friendp, ! publicp, inlinep, sfk, funcdef_flag, ! template_count, in_namespace, attrlist); if (decl == NULL_TREE) return NULL_TREE; *************** grokdeclarator (tree declarator, *** 8487,8493 **** declaring main to be static. */ if (TREE_CODE (type) == METHOD_TYPE) { ! pedwarn ("cannot declare member function `%D' to have static linkage", decl); invalid_static = 1; } else if (current_function_decl) --- 8107,8114 ---- declaring main to be static. */ if (TREE_CODE (type) == METHOD_TYPE) { ! pedwarn ("cannot declare member function %qD to have " ! "static linkage", decl); invalid_static = 1; } else if (current_function_decl) *************** grokdeclarator (tree declarator, *** 8500,8506 **** if (invalid_static) { staticp = 0; ! RIDBIT_RESET (RID_STATIC, specbits); } } } --- 8121,8127 ---- if (invalid_static) { staticp = 0; ! storage_class = sc_none; } } } *************** grokdeclarator (tree declarator, *** 8509,8519 **** /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ ! decl = grokvardecl (type, declarator, &specbits, initialized, (type_quals & TYPE_QUAL_CONST) != 0, ctype ? ctype : in_namespace); ! bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); if (ctype) --- 8130,8141 ---- /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ ! decl = grokvardecl (type, unqualified_id, ! declspecs, initialized, (type_quals & TYPE_QUAL_CONST) != 0, ctype ? ctype : in_namespace); ! bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); if (ctype) *************** grokdeclarator (tree declarator, *** 8521,8563 **** DECL_CONTEXT (decl) = ctype; if (staticp == 1) { ! pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member"); staticp = 0; ! RIDBIT_RESET (RID_STATIC, specbits); } ! if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl)) { ! error ("static member `%D' declared `register'", decl); ! RIDBIT_RESET (RID_REGISTER, specbits); } ! if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic) { ! pedwarn ("cannot explicitly declare member `%#D' to have extern linkage", ! decl); ! RIDBIT_RESET (RID_EXTERN, specbits); } } } - my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927); - /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ ! if (RIDBIT_SETP (RID_REGISTER, specbits)) DECL_REGISTER (decl) = 1; ! ! if (RIDBIT_SETP (RID_EXTERN, specbits)) DECL_THIS_EXTERN (decl) = 1; ! ! if (RIDBIT_SETP (RID_STATIC, specbits)) DECL_THIS_STATIC (decl) = 1; /* Record constancy and volatility. There's no need to do this when processing a template; we'll do this for the instantiated declaration based on the type of DECL. */ if (!processing_template_decl) ! c_apply_type_quals_to_decl (type_quals, decl); return decl; } --- 8143,8183 ---- DECL_CONTEXT (decl) = ctype; if (staticp == 1) { ! pedwarn ("% may not be used when defining " ! "(as opposed to declaring) a static data member"); staticp = 0; ! storage_class = sc_none; } ! if (storage_class == sc_register && TREE_STATIC (decl)) { ! error ("static member %qD declared %", decl); ! storage_class = sc_none; } ! if (storage_class == sc_extern && pedantic) { ! pedwarn ("cannot explicitly declare member %q#D to have " ! "extern linkage", ! decl); ! storage_class = sc_none; } } } /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ ! if (storage_class == sc_register) DECL_REGISTER (decl) = 1; ! else if (storage_class == sc_extern) DECL_THIS_EXTERN (decl) = 1; ! else if (storage_class == sc_static) DECL_THIS_STATIC (decl) = 1; /* Record constancy and volatility. There's no need to do this when processing a template; we'll do this for the instantiated declaration based on the type of DECL. */ if (!processing_template_decl) ! cp_apply_type_quals_to_decl (type_quals, decl); return decl; } *************** require_complete_types_for_parms (tree p *** 8572,8577 **** --- 8192,8199 ---- { for (; parms; parms = TREE_CHAIN (parms)) { + if (dependent_type_p (TREE_TYPE (parms))) + continue; if (VOID_TYPE_P (TREE_TYPE (parms))) /* grokparms will have already issued an error. */ TREE_TYPE (parms) = error_mark_node; *************** nonstatic_local_decl_p (tree t) *** 8616,8629 **** function. */ static tree ! local_variable_p_walkfn (tree* tp, ! int* walk_subtrees ATTRIBUTE_UNUSED , ! void* data ATTRIBUTE_UNUSED ) { ! return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp)) ! ? *tp : NULL_TREE); } /* Check that ARG, which is a default-argument expression for a parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if something goes wrong. DECL may also be a _TYPE node, rather than a --- 8238,8255 ---- function. */ static tree ! local_variable_p_walkfn (tree *tp, int *walk_subtrees, ! void *data ATTRIBUTE_UNUSED) { ! if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp)) ! return *tp; ! else if (TYPE_P (*tp)) ! *walk_subtrees = 0; ! ! return NULL_TREE; } + /* Check that ARG, which is a default-argument expression for a parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if something goes wrong. DECL may also be a _TYPE node, rather than a *************** check_default_argument (tree decl, tree *** 8672,8682 **** || !can_convert_arg (decl_type, TREE_TYPE (arg), arg)) { if (decl) ! error ("default argument for `%#D' has type `%T'", ! decl, TREE_TYPE (arg)); else ! error ("default argument for parameter of type `%T' has type `%T'", ! decl_type, TREE_TYPE (arg)); return error_mark_node; } --- 8298,8308 ---- || !can_convert_arg (decl_type, TREE_TYPE (arg), arg)) { if (decl) ! error ("default argument for %q#D has type %qT", ! decl, TREE_TYPE (arg)); else ! error ("default argument for parameter of type %qT has type %qT", ! decl_type, TREE_TYPE (arg)); return error_mark_node; } *************** check_default_argument (tree decl, tree *** 8692,8699 **** NULL); if (var) { ! error ("default argument `%E' uses local variable `%D'", ! arg, var); return error_mark_node; } --- 8318,8324 ---- NULL); if (var) { ! error ("default argument %qE uses local variable %qD", arg, var); return error_mark_node; } *************** check_default_argument (tree decl, tree *** 8705,8752 **** Given the list of things declared inside the parens, return a list of types. ! We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P ! flag. If unset, we append void_list_node. A parmlist declared ! as `(void)' is accepted as the empty parmlist. *PARMS is set to the chain of PARM_DECLs created. */ static tree ! grokparms (tree first_parm, tree *parms) { tree result = NULL_TREE; tree decls = NULL_TREE; ! int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm); ! tree parm, chain; int any_error = 0; ! my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115); ! ! for (parm = first_parm; parm != NULL_TREE; parm = chain) { tree type = NULL_TREE; ! tree decl = TREE_VALUE (parm); ! tree init = TREE_PURPOSE (parm); ! tree specs, attrs; ! ! chain = TREE_CHAIN (parm); ! /* @@ weak defense against parse errors. */ ! if (TREE_CODE (decl) != VOID_TYPE ! && TREE_CODE (decl) != TREE_LIST) ! { ! /* Give various messages as the need arises. */ ! if (TREE_CODE (decl) == STRING_CST) ! error ("invalid string constant `%E'", decl); ! else if (TREE_CODE (decl) == INTEGER_CST) ! error ("invalid integer constant in parameter list, did you forget to give parameter name?"); ! continue; ! } ! if (parm == void_list_node) break; ! split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs); ! decl = grokdeclarator (TREE_VALUE (decl), specs, PARM, init != NULL_TREE, &attrs); if (! decl || TREE_TYPE (decl) == error_mark_node) continue; --- 8330,8362 ---- Given the list of things declared inside the parens, return a list of types. ! If this parameter does not end with an ellipsis, we append ! void_list_node. *PARMS is set to the chain of PARM_DECLs created. */ static tree ! grokparms (cp_parameter_declarator *first_parm, tree *parms) { tree result = NULL_TREE; tree decls = NULL_TREE; ! int ellipsis = !first_parm || first_parm->ellipsis_p; ! cp_parameter_declarator *parm; int any_error = 0; ! for (parm = first_parm; parm != NULL; parm = parm->next) { tree type = NULL_TREE; ! tree init = parm->default_argument; ! tree attrs; ! tree decl; ! if (parm == no_parameters) break; ! attrs = parm->decl_specifiers.attributes; ! parm->decl_specifiers.attributes = NULL_TREE; ! decl = grokdeclarator (parm->declarator, &parm->decl_specifiers, PARM, init != NULL_TREE, &attrs); if (! decl || TREE_TYPE (decl) == error_mark_node) continue; *************** grokparms (tree first_parm, tree *parms) *** 8758,8764 **** if (VOID_TYPE_P (type)) { if (same_type_p (type, void_type_node) ! && !DECL_NAME (decl) && !result && !chain && !ellipsis) /* this is a parmlist of `(void)', which is ok. */ break; cxx_incomplete_type_error (decl, type); --- 8368,8374 ---- if (VOID_TYPE_P (type)) { if (same_type_p (type, void_type_node) ! && !DECL_NAME (decl) && !result && !parm->next && !ellipsis) /* this is a parmlist of `(void)', which is ok. */ break; cxx_incomplete_type_error (decl, type); *************** grokparms (tree first_parm, tree *parms) *** 8776,8782 **** type = cp_build_qualified_type (type, 0); if (TREE_CODE (type) == METHOD_TYPE) { ! error ("parameter `%D' invalidly declared method type", decl); type = build_pointer_type (type); TREE_TYPE (decl) = type; } --- 8386,8392 ---- type = cp_build_qualified_type (type, 0); if (TREE_CODE (type) == METHOD_TYPE) { ! error ("parameter %qD invalidly declared method type", decl); type = build_pointer_type (type); TREE_TYPE (decl) = type; } *************** grokparms (tree first_parm, tree *parms) *** 8800,8807 **** t = TREE_TYPE (t); } if (TREE_CODE (t) == ARRAY_TYPE) ! error ("parameter `%D' includes %s to array of unknown bound `%T'", ! decl, ptr ? "pointer" : "reference", t); } if (!any_error && init) --- 8410,8418 ---- t = TREE_TYPE (t); } if (TREE_CODE (t) == ARRAY_TYPE) ! error ("parameter %qD includes %s to array of unknown " ! "bound %qT", ! decl, ptr ? "pointer" : "reference", t); } if (!any_error && init) *************** copy_fn_p (tree d) *** 8848,8863 **** tree args; tree arg_type; int result = 1; - - my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208); ! if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d))) /* Instantiations of template member functions are never copy functions. Note that member functions of templated classes are represented as template functions internally, and we must accept those as copy functions. */ return 0; ! args = FUNCTION_FIRST_USER_PARMTYPE (d); if (!args) return 0; --- 8459,8475 ---- tree args; tree arg_type; int result = 1; ! gcc_assert (DECL_FUNCTION_MEMBER_P (d)); ! ! if (DECL_TEMPLATE_INFO (d) ! && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))) /* Instantiations of template member functions are never copy functions. Note that member functions of templated classes are represented as template functions internally, and we must accept those as copy functions. */ return 0; ! args = FUNCTION_FIRST_USER_PARMTYPE (d); if (!args) return 0; *************** copy_fn_p (tree d) *** 8877,8883 **** } else return 0; ! args = TREE_CHAIN (args); if (args && args != void_list_node && !TREE_PURPOSE (args)) --- 8489,8495 ---- } else return 0; ! args = TREE_CHAIN (args); if (args && args != void_list_node && !TREE_PURPOSE (args)) *************** void grok_special_member_properties (tre *** 8896,8906 **** else if (DECL_CONSTRUCTOR_P (decl)) { int ctor = copy_fn_p (decl); ! if (ctor > 0) { /* [class.copy] ! A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there --- 8508,8518 ---- else if (DECL_CONSTRUCTOR_P (decl)) { int ctor = copy_fn_p (decl); ! if (ctor > 0) { /* [class.copy] ! A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there *************** void grok_special_member_properties (tre *** 8916,8935 **** else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR) { /* [class.copy] ! A non-template assignment operator for class X is a copy assignment operator if its parameter is of type X, X&, const X&, volatile X& or const volatile X&. */ ! int assop = copy_fn_p (decl); ! if (assop) { TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1; if (assop != 1) TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1; - if (DECL_PURE_VIRTUAL_P (decl)) - TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1; } } } --- 8528,8545 ---- else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR) { /* [class.copy] ! A non-template assignment operator for class X is a copy assignment operator if its parameter is of type X, X&, const X&, volatile X& or const volatile X&. */ ! int assop = copy_fn_p (decl); ! if (assop) { TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1; if (assop != 1) TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1; } } } *************** grok_ctor_properties (tree ctype, tree d *** 8945,8956 **** if (ctor_parm < 0) { /* [class.copy] ! A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified) X and either there are no other parameters or else all other parameters have default arguments. ! We *don't* complain about member template instantiations that have this form, though; they can occur as we try to decide what constructor to use during overload resolution. Since --- 8555,8566 ---- if (ctor_parm < 0) { /* [class.copy] ! A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified) X and either there are no other parameters or else all other parameters have default arguments. ! We *don't* complain about member template instantiations that have this form, though; they can occur as we try to decide what constructor to use during overload resolution. Since *************** grok_ctor_properties (tree ctype, tree d *** 8959,8970 **** or implicitly defined), there's no need to worry about their existence. Theoretically, they should never even be instantiated, but that's hard to forestall. */ ! error ("invalid constructor; you probably meant `%T (const %T&)'", ctype, ctype); - SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); return 0; } ! return 1; } --- 8569,8579 ---- or implicitly defined), there's no need to worry about their existence. Theoretically, they should never even be instantiated, but that's hard to forestall. */ ! error ("invalid constructor; you probably meant %<%T (const %T&)%>", ctype, ctype); return 0; } ! return 1; } *************** grok_op_properties (tree decl, int frien *** 9040,9049 **** #include "operators.def" #undef DEF_OPERATOR ! abort (); } while (0); ! my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526); SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); if (! friendp) --- 8649,8658 ---- #include "operators.def" #undef DEF_OPERATOR ! gcc_unreachable (); } while (0); ! gcc_assert (operator_code != LAST_CPLUS_TREE_CODE); SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); if (! friendp) *************** grok_op_properties (tree decl, int frien *** 9071,9076 **** --- 8680,8704 ---- } } + /* [basic.std.dynamic.allocation]/1: + + A program is ill-formed if an allocation function is declared + in a namespace scope other than global scope or declared static + in global scope. + + The same also holds true for deallocation functions. */ + if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR + || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) + { + if (DECL_NAMESPACE_SCOPE_P (decl)) + { + if (CP_DECL_CONTEXT (decl) != global_namespace) + error ("%qD may not be declared within a namespace", decl); + else if (!TREE_PUBLIC (decl)) + error ("%qD may not be declared as static", decl); + } + } + if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR) TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) *************** grok_op_properties (tree decl, int frien *** 9087,9099 **** || operator_code == COMPONENT_REF || operator_code == ARRAY_REF || operator_code == NOP_EXPR) ! error ("`%D' must be a nonstatic member function", decl); else { tree p; if (DECL_STATIC_FUNCTION_P (decl)) ! error ("`%D' must be either a non-static member function or a non-member function", decl); for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p)) { --- 8715,8728 ---- || operator_code == COMPONENT_REF || operator_code == ARRAY_REF || operator_code == NOP_EXPR) ! error ("%qD must be a nonstatic member function", decl); else { tree p; if (DECL_STATIC_FUNCTION_P (decl)) ! error ("%qD must be either a non-static member " ! "function or a non-member function", decl); for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p)) { *************** grok_op_properties (tree decl, int frien *** 9110,9116 **** if (!complain) return false; ! error ("`%D' must have an argument of class or " "enumerated type", decl); ok = false; --- 8739,8745 ---- if (!complain) return false; ! error ("%qD must have an argument of class or " "enumerated type", decl); ok = false; *************** grok_op_properties (tree decl, int frien *** 9145,9151 **** what = "a base class"; if (what && warn_conversion) ! warning ("conversion to %s%s will never use a type conversion operator", ref ? "a reference to " : "", what); } } --- 8774,8781 ---- what = "a base class"; if (what && warn_conversion) ! warning ("conversion to %s%s will never use a type " ! "conversion operator", ref ? "a reference to " : "", what); } } *************** grok_op_properties (tree decl, int frien *** 9191,9197 **** break; default: ! abort (); } SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); --- 8821,8827 ---- break; default: ! gcc_unreachable (); } SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); *************** grok_op_properties (tree decl, int frien *** 9202,9221 **** && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node)) { if (methodp) ! error ("postfix `%D' must take `int' as its argument", decl); else error ! ("postfix `%D' must take `int' as its second argument", decl); } } else { if (methodp) ! error ("`%D' must take either zero or one argument", decl); else ! error ("`%D' must take either one or two arguments", decl); } /* More Effective C++ rule 6. */ --- 8832,8851 ---- && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node)) { if (methodp) ! error ("postfix %qD must take % as its argument", decl); else error ! ("postfix %qD must take % as its second argument", decl); } } else { if (methodp) ! error ("%qD must take either zero or one argument", decl); else ! error ("%qD must take either one or two arguments", decl); } /* More Effective C++ rule 6. */ *************** grok_op_properties (tree decl, int frien *** 9236,9248 **** if (TREE_CODE (ret) != REFERENCE_TYPE || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)), arg)) ! warning ("prefix `%D' should return `%T'", decl, ! build_reference_type (arg)); } else { if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg)) ! warning ("postfix `%D' should return `%T'", decl, arg); } } } --- 8866,8878 ---- if (TREE_CODE (ret) != REFERENCE_TYPE || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)), arg)) ! warning ("prefix %qD should return %qT", decl, ! build_reference_type (arg)); } else { if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg)) ! warning ("postfix %qD should return %qT", decl, arg); } } } *************** grok_op_properties (tree decl, int frien *** 9251,9259 **** if (arity != 1) { if (methodp) ! error ("`%D' must take `void'", decl); else ! error ("`%D' must take exactly one argument", decl); } } else /* if (binary_op_p (operator_code)) */ --- 8881,8889 ---- if (arity != 1) { if (methodp) ! error ("%qD must take %", decl); else ! error ("%qD must take exactly one argument", decl); } } else /* if (binary_op_p (operator_code)) */ *************** grok_op_properties (tree decl, int frien *** 9261,9269 **** if (arity != 2) { if (methodp) ! error ("`%D' must take exactly one argument", decl); else ! error ("`%D' must take exactly two arguments", decl); } /* More Effective C++ rule 7. */ --- 8891,8899 ---- if (arity != 2) { if (methodp) ! error ("%qD must take exactly one argument", decl); else ! error ("%qD must take exactly two arguments", decl); } /* More Effective C++ rule 7. */ *************** grok_op_properties (tree decl, int frien *** 9271,9278 **** && (operator_code == TRUTH_ANDIF_EXPR || operator_code == TRUTH_ORIF_EXPR || operator_code == COMPOUND_EXPR)) ! warning ("user-defined `%D' always evaluates both arguments", ! decl); } /* Effective C++ rule 23. */ --- 8901,8908 ---- && (operator_code == TRUTH_ANDIF_EXPR || operator_code == TRUTH_ORIF_EXPR || operator_code == COMPOUND_EXPR)) ! warning ("user-defined %qD always evaluates both arguments", ! decl); } /* Effective C++ rule 23. */ *************** grok_op_properties (tree decl, int frien *** 9285,9291 **** || operator_code == MULT_EXPR || operator_code == TRUNC_MOD_EXPR) && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE) ! warning ("`%D' should return by value", decl); /* [over.oper]/8 */ for (; argtypes && argtypes != void_list_node; --- 8915,8921 ---- || operator_code == MULT_EXPR || operator_code == TRUNC_MOD_EXPR) && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE) ! warning ("%qD should return by value", decl); /* [over.oper]/8 */ for (; argtypes && argtypes != void_list_node; *************** grok_op_properties (tree decl, int frien *** 9297,9306 **** || operator_code == POSTDECREMENT_EXPR) { if (pedantic) ! pedwarn ("`%D' cannot have default arguments", decl); } else ! error ("`%D' cannot have default arguments", decl); } } --- 8927,8936 ---- || operator_code == POSTDECREMENT_EXPR) { if (pedantic) ! pedwarn ("%qD cannot have default arguments", decl); } else ! error ("%qD cannot have default arguments", decl); } } *************** grok_op_properties (tree decl, int frien *** 9308,9313 **** --- 8938,8945 ---- return ok; } + /* Return a string giving the keyword associate with CODE. */ + static const char * tag_name (enum tag_types code) { *************** tag_name (enum tag_types code) *** 9318,9328 **** case class_type: return "class"; case union_type: ! return "union "; case enum_type: return "enum"; default: ! abort (); } } --- 8950,8962 ---- case class_type: return "class"; case union_type: ! return "union"; case enum_type: return "enum"; + case typename_type: + return "typename"; default: ! gcc_unreachable (); } } *************** check_elaborated_type_specifier (enum ta *** 9350,9356 **** type = TREE_TYPE (decl); ! /* [dcl.type.elab] If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. --- 8984,8998 ---- type = TREE_TYPE (decl); ! /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P ! is false for this case as well. */ ! if (TREE_CODE (type) == TEMPLATE_TYPE_PARM) ! { ! error ("using template type parameter %qT after %qs", ! type, tag_name (tag_code)); ! return error_mark_node; ! } ! /* [dcl.type.elab] If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. *************** check_elaborated_type_specifier (enum ta *** 9358,9386 **** In other words, the only legitimate declaration to use in the elaborated type specifier is the implicit typedef created when the type is declared. */ ! if (!DECL_IMPLICIT_TYPEDEF_P (decl)) ! { ! error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code)); ! return IS_AGGR_TYPE (type) ? type : error_mark_node; ! } ! ! if (TREE_CODE (type) == TEMPLATE_TYPE_PARM) { ! error ("using template type parameter `%T' after `%s'", ! type, tag_name (tag_code)); return error_mark_node; } else if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE ! && tag_code != enum_type) { ! error ("`%T' referred to as `%s'", type, tag_name (tag_code)); return error_mark_node; } else if (TREE_CODE (type) != ENUMERAL_TYPE ! && tag_code == enum_type) { ! error ("`%T' referred to as enum", type); return error_mark_node; } else if (!allow_template_p --- 9000,9027 ---- In other words, the only legitimate declaration to use in the elaborated type specifier is the implicit typedef created when the type is declared. */ ! else if (!DECL_IMPLICIT_TYPEDEF_P (decl) ! && tag_code != typename_type) { ! error ("using typedef-name %qD after %qs", decl, tag_name (tag_code)); ! cp_error_at ("%qD has a previous declaration here", decl); return error_mark_node; } else if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE ! && tag_code != enum_type ! && tag_code != typename_type) { ! error ("%qT referred to as %qs", type, tag_name (tag_code)); ! cp_error_at ("%qT has a previous declaration here", type); return error_mark_node; } else if (TREE_CODE (type) != ENUMERAL_TYPE ! && tag_code == enum_type ! && tag_code != typename_type) { ! error ("%qT referred to as enum", type); ! cp_error_at ("%qT has a previous declaration here", type); return error_mark_node; } else if (!allow_template_p *************** check_elaborated_type_specifier (enum ta *** 9395,9401 **** then the required template argument is missing. */ ! error ("template argument required for `%s %T'", tag_name (tag_code), DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))); return error_mark_node; --- 9036,9042 ---- then the required template argument is missing. */ ! error ("template argument required for %<%s %T%>", tag_name (tag_code), DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))); return error_mark_node; *************** check_elaborated_type_specifier (enum ta *** 9404,9434 **** return type; } /* Get the struct, enum or union (TAG_CODE says which) with tag NAME. Define the tag as a forward-reference if it is not defined. If a declaration is given, process it here, and report an error if multiple declarations are not identical. ! GLOBALIZE is false when this is also a definition. Only look in the current frame for the name (since C++ allows new names in any ! scope.) TEMPLATE_HEADER_P is true when this declaration is preceded by a set of template parameters. */ tree xref_tag (enum tag_types tag_code, tree name, ! bool globalize, bool template_header_p) { enum tree_code code; tree t; - struct cp_binding_level *b = current_binding_level; tree context = NULL_TREE; timevar_push (TV_NAME_LOOKUP); ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0); switch (tag_code) { --- 9045,9135 ---- return type; } + /* Lookup NAME in elaborate type specifier in scope according to + SCOPE and issue diagnostics if necessary. + Return *_TYPE node upon success, NULL_TREE when the NAME is not + found, and ERROR_MARK_NODE for type error. */ + + static tree + lookup_and_check_tag (enum tag_types tag_code, tree name, + tag_scope scope, bool template_header_p) + { + tree t; + tree decl; + if (scope == ts_global) + decl = lookup_name (name, 2); + else + decl = lookup_type_scope (name, scope); + + if (decl && DECL_CLASS_TEMPLATE_P (decl)) + decl = DECL_TEMPLATE_RESULT (decl); + + if (decl && TREE_CODE (decl) == TYPE_DECL) + { + /* Look for invalid nested type: + class C { + class C {}; + }; */ + if (scope == ts_current && DECL_SELF_REFERENCE_P (decl)) + { + error ("%qD has the same name as the class in which it is " + "declared", + decl); + return error_mark_node; + } + + /* Two cases we need to consider when deciding if a class + template is allowed as an elaborated type specifier: + 1. It is a self reference to its own class. + 2. It comes with a template header. + + For example: + + template class C { + class C *c1; // DECL_SELF_REFERENCE_P is true + class D; + }; + template class C; // template_header_p is true + template class C::D { + class C *c2; // DECL_SELF_REFERENCE_P is true + }; */ + + t = check_elaborated_type_specifier (tag_code, + decl, + template_header_p + | DECL_SELF_REFERENCE_P (decl)); + return t; + } + else + return NULL_TREE; + } + /* Get the struct, enum or union (TAG_CODE says which) with tag NAME. Define the tag as a forward-reference if it is not defined. If a declaration is given, process it here, and report an error if multiple declarations are not identical. ! SCOPE is TS_CURRENT when this is also a definition. Only look in the current frame for the name (since C++ allows new names in any ! scope.) It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend ! declaration. Only look beginning from the current scope outward up ! till the nearest non-class scope. Otherwise it is TS_GLOBAL. TEMPLATE_HEADER_P is true when this declaration is preceded by a set of template parameters. */ tree xref_tag (enum tag_types tag_code, tree name, ! tag_scope scope, bool template_header_p) { enum tree_code code; tree t; tree context = NULL_TREE; timevar_push (TV_NAME_LOOKUP); ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); switch (tag_code) { *************** xref_tag (enum tag_types tag_code, tree *** 9443,9535 **** code = ENUMERAL_TYPE; break; default: ! abort (); } ! if (! globalize) ! { ! /* If we know we are defining this tag, only look it up in ! this scope and don't try to find it as a type. */ ! t = lookup_tag (code, name, b, 1); ! } else ! { ! tree decl = lookup_name (name, 2); ! ! if (decl && DECL_CLASS_TEMPLATE_P (decl)) ! decl = DECL_TEMPLATE_RESULT (decl); ! ! if (decl && TREE_CODE (decl) == TYPE_DECL) ! { ! /* Two cases we need to consider when deciding if a class ! template is allowed as an elaborated type specifier: ! 1. It is a self reference to its own class. ! 2. It comes with a template header. ! ! For example: ! ! template class C { ! class C *c1; // DECL_SELF_REFERENCE_P is true ! class D; ! }; ! template class C; // template_header_p is true ! template class C::D { ! class C *c2; // DECL_SELF_REFERENCE_P is true ! }; */ ! t = check_elaborated_type_specifier (tag_code, ! decl, ! template_header_p ! | DECL_SELF_REFERENCE_P (decl)); ! if (t == error_mark_node) ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); ! } ! else ! t = NULL_TREE; ! if (t && current_class_type ! && template_class_depth (current_class_type) ! && template_header_p) ! { ! /* 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: ! template ! struct S1 ! template ! struct S2 ! { template ! friend struct S1; }; ! Here, the S2::S1 declaration should not be confused with the ! outer declaration. In particular, the inner version should ! have a template parameter of level 2, not level 1. This ! would be particularly important if the member declaration ! were instead: ! template friend struct S1; ! say, when we should tsubst into `U' when instantiating ! S2. On the other hand, when presented with: ! template ! struct S1 { ! template ! struct S2 {}; ! template ! friend struct S2; ! }; ! we must find the inner binding eventually. We ! accomplish this by making sure that the new type we ! create to represent this declaration has the right ! TYPE_CONTEXT. */ ! context = TYPE_CONTEXT (t); ! t = NULL_TREE; ! } } if (! t) --- 9144,9205 ---- code = ENUMERAL_TYPE; break; default: ! gcc_unreachable (); } ! /* In case of anonymous name, xref_tag is only called to ! make type node and push name. Name lookup is not required. */ ! if (ANON_AGGRNAME_P (name)) ! t = NULL_TREE; else ! t = lookup_and_check_tag (tag_code, name, ! scope, template_header_p); ! if (t == error_mark_node) ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); ! if (scope != ts_current && t && current_class_type ! && template_class_depth (current_class_type) ! && template_header_p) ! { ! /* Since SCOPE is not TS_CURRENT, we are not looking at a ! definition of this tag. Since, in addition, we are currently ! processing a (member) template declaration of a template ! class, we must be very careful; consider: ! template ! struct S1 ! template ! struct S2 ! { template ! friend struct S1; }; ! Here, the S2::S1 declaration should not be confused with the ! outer declaration. In particular, the inner version should ! have a template parameter of level 2, not level 1. This ! would be particularly important if the member declaration ! were instead: ! template friend struct S1; ! say, when we should tsubst into `U' when instantiating ! S2. On the other hand, when presented with: ! template ! struct S1 { ! template ! struct S2 {}; ! template ! friend struct S2; ! }; ! we must find the inner binding eventually. We ! accomplish this by making sure that the new type we ! create to represent this declaration has the right ! TYPE_CONTEXT. */ ! context = TYPE_CONTEXT (t); ! t = NULL_TREE; } if (! t) *************** xref_tag (enum tag_types tag_code, tree *** 9540,9564 **** the forward-reference will be altered into a real type. */ if (code == ENUMERAL_TYPE) { ! error ("use of enum `%#D' without previous declaration", name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } else { t = make_aggr_type (code); TYPE_CONTEXT (t) = context; ! pushtag (name, t, globalize); } } else { ! if (!globalize && processing_template_decl && IS_AGGR_TYPE (t)) redeclare_class_template (t, current_template_parms); ! else if (!processing_template_decl && CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t)) { ! error ("redeclaration of `%T' as a non-template", t); t = error_mark_node; } } --- 9210,9235 ---- the forward-reference will be altered into a real type. */ if (code == ENUMERAL_TYPE) { ! error ("use of enum %q#D without previous declaration", name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } else { t = make_aggr_type (code); TYPE_CONTEXT (t) = context; ! /* pushtag only cares whether SCOPE is zero or not. */ ! t = pushtag (name, t, scope != ts_current); } } else { ! if (template_header_p && IS_AGGR_TYPE (t)) redeclare_class_template (t, current_template_parms); ! else if (!processing_template_decl && CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t)) { ! error ("redeclaration of %qT as a non-template", t); t = error_mark_node; } } *************** xref_tag (enum tag_types tag_code, tree *** 9567,9573 **** } tree ! xref_tag_from_type (tree old, tree id, int globalize) { enum tag_types tag_kind; --- 9238,9244 ---- } tree ! xref_tag_from_type (tree old, tree id, tag_scope scope) { enum tag_types tag_kind; *************** xref_tag_from_type (tree old, tree id, i *** 9579,9773 **** if (id == NULL_TREE) id = TYPE_IDENTIFIER (old); ! return xref_tag (tag_kind, id, globalize, false); } ! /* REF is a type (named NAME), for which we have just seen some ! baseclasses. BASE_LIST is a list of those baseclasses; the ! TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of ! the base-class. TREE_VIA_VIRTUAL indicates virtual ! inheritance. CODE_TYPE_NODE indicates whether REF is a class, ! struct, or union. */ void xref_basetypes (tree ref, tree base_list) { - /* In the declaration `A : X, Y, ... Z' we mark all the types - (A, X, Y, ..., Z) so we can check for duplicates. */ tree *basep; ! int i; ! enum tag_types tag_code; if (ref == error_mark_node) return; ! if (TREE_CODE (ref) == UNION_TYPE) ! { ! error ("derived union `%T' invalid", ref); ! return; ! } ! ! tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type); /* First, make sure that any templates in base-classes are instantiated. This ensures that if we call ourselves recursively we do not get confused about which classes are marked and which are not. */ ! basep = &base_list; ! while (*basep) { tree basetype = TREE_VALUE (*basep); if (!(processing_template_decl && uses_template_parms (basetype)) && !complete_type_or_else (basetype, NULL)) /* An incomplete type. Remove it from the list. */ *basep = TREE_CHAIN (*basep); else ! basep = &TREE_CHAIN (*basep); } ! SET_CLASSTYPE_MARKED (ref); ! i = list_length (base_list); ! if (i) { ! tree binfo = TYPE_BINFO (ref); ! tree binfos = make_tree_vec (i); ! tree accesses = make_tree_vec (i); ! ! BINFO_BASETYPES (binfo) = binfos; ! BINFO_BASEACCESSES (binfo) = accesses; ! ! for (i = 0; base_list; base_list = TREE_CHAIN (base_list)) { ! tree access = TREE_PURPOSE (base_list); ! int via_virtual = TREE_VIA_VIRTUAL (base_list); ! tree basetype = TREE_VALUE (base_list); ! tree base_binfo; ! ! if (access == access_default_node) ! /* The base of a derived struct is public by default. */ ! access = (tag_code == class_type ! ? access_private_node : access_public_node); ! ! if (basetype && TREE_CODE (basetype) == TYPE_DECL) ! basetype = TREE_TYPE (basetype); ! if (!basetype ! || (TREE_CODE (basetype) != RECORD_TYPE ! && TREE_CODE (basetype) != TYPENAME_TYPE ! && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM ! && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)) ! { ! error ("base type `%T' fails to be a struct or class type", ! basetype); ! continue; ! } ! ! if (CLASSTYPE_MARKED (basetype)) ! { ! if (basetype == ref) ! error ("recursive type `%T' undefined", basetype); ! else ! error ("duplicate base type `%T' invalid", basetype); ! continue; ! } ! ! if (TYPE_FOR_JAVA (basetype) ! && (current_lang_depth () == 0)) ! TYPE_FOR_JAVA (ref) = 1; ! ! if (CLASS_TYPE_P (basetype)) ! { ! base_binfo = TYPE_BINFO (basetype); ! /* This flag will be in the binfo of the base type, we must ! clear it after copying the base binfos. */ ! BINFO_DEPENDENT_BASE_P (base_binfo) ! = dependent_type_p (basetype); ! } ! else ! base_binfo = make_binfo (size_zero_node, basetype, ! NULL_TREE, NULL_TREE); ! ! TREE_VEC_ELT (binfos, i) = base_binfo; ! TREE_VEC_ELT (accesses, i) = access; ! /* This flag will be in the binfo of the base type, we must ! clear it after copying the base binfos. */ ! TREE_VIA_VIRTUAL (base_binfo) = via_virtual; ! ! SET_CLASSTYPE_MARKED (basetype); ! ! /* We are free to modify these bits because they are meaningless ! at top level, and BASETYPE is a top-level type. */ ! if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) ! { ! TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; ! /* Converting to a virtual base class requires looking ! up the offset of the virtual base. */ ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; ! } ! ! if (CLASS_TYPE_P (basetype)) ! { ! TYPE_HAS_NEW_OPERATOR (ref) ! |= TYPE_HAS_NEW_OPERATOR (basetype); ! TYPE_HAS_ARRAY_NEW_OPERATOR (ref) ! |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype); ! TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); ! /* If the base-class uses multiple inheritance, so do we. */ ! TYPE_USES_MULTIPLE_INHERITANCE (ref) ! |= TYPE_USES_MULTIPLE_INHERITANCE (basetype); ! /* Likewise, if converting to a base of the base may require ! code, then we may need to generate code to convert to a ! base as well. */ ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) ! |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype); ! } ! i++; } - if (i) - TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i; - else - BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE; ! if (i > 1) { ! TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; ! /* If there is more than one non-empty they cannot be at the same ! address. */ ! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; } ! } ! ! /* Copy the base binfos, collect the virtual bases and set the ! inheritance order chain. */ ! copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE); ! CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref)); ! if (TYPE_FOR_JAVA (ref)) ! { ! if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) ! error ("Java class '%T' cannot have multiple bases", ref); ! if (CLASSTYPE_VBASECLASSES (ref)) ! error ("Java class '%T' cannot have virtual bases", ref); } /* Unmark all the types. */ ! while (i--) { ! tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i)); ! ! CLEAR_CLASSTYPE_MARKED (basetype); ! if (CLASS_TYPE_P (basetype)) { ! TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0; ! BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0; } } - CLEAR_CLASSTYPE_MARKED (ref); } /* Begin compiling the definition of an enumeration type. ! NAME is its name (or null if anonymous). Returns the type object, as yet incomplete. Also records info about it so that build_enumerator may be used to declare the individual values as they are read. */ --- 9250,9444 ---- if (id == NULL_TREE) id = TYPE_IDENTIFIER (old); ! return xref_tag (tag_kind, id, scope, false); } ! /* Create the binfo hierarchy for REF with (possibly NULL) base list ! BASE_LIST. For each element on BASE_LIST the TREE_PURPOSE is an ! access_* node, and the TREE_VALUE is the type of the base-class. ! Non-NULL TREE_TYPE indicates virtual inheritance. */ void xref_basetypes (tree ref, tree base_list) { tree *basep; ! tree binfo, base_binfo; ! unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases. */ ! unsigned max_bases = 0; /* Maximum direct bases. */ int i; ! tree default_access; ! tree igo_prev; /* Track Inheritance Graph Order. */ if (ref == error_mark_node) return; ! /* The base of a derived class is private by default, all others are ! public. */ ! default_access = (TREE_CODE (ref) == RECORD_TYPE ! && CLASSTYPE_DECLARED_CLASS (ref) ! ? access_private_node : access_public_node); /* First, make sure that any templates in base-classes are instantiated. This ensures that if we call ourselves recursively we do not get confused about which classes are marked and which are not. */ ! basep = &base_list; ! while (*basep) { tree basetype = TREE_VALUE (*basep); + if (!(processing_template_decl && uses_template_parms (basetype)) && !complete_type_or_else (basetype, NULL)) /* An incomplete type. Remove it from the list. */ *basep = TREE_CHAIN (*basep); else ! { ! max_bases++; ! if (TREE_TYPE (*basep)) ! max_vbases++; ! if (CLASS_TYPE_P (basetype)) ! max_vbases += VEC_length (tree, CLASSTYPE_VBASECLASSES (basetype)); ! basep = &TREE_CHAIN (*basep); ! } } ! TYPE_MARKED_P (ref) = 1; ! ! /* The binfo slot should be empty, unless this is an (ill-formed) ! redefinition. */ ! gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref)); ! gcc_assert (TYPE_MAIN_VARIANT (ref) == ref); ! ! binfo = make_tree_binfo (max_bases); ! ! TYPE_BINFO (ref) = binfo; ! BINFO_OFFSET (binfo) = size_zero_node; ! BINFO_TYPE (binfo) = ref; ! ! if (max_bases) { ! BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, max_bases); ! /* An aggregate cannot have baseclasses. */ ! CLASSTYPE_NON_AGGREGATE (ref) = 1; ! ! if (TREE_CODE (ref) == UNION_TYPE) ! error ("derived union %qT invalid", ref); ! } ! ! if (max_bases > 1) ! { ! if (TYPE_FOR_JAVA (ref)) ! error ("Java class %qT cannot have multiple bases", ref); ! } ! ! if (max_vbases) ! { ! CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases); ! ! if (TYPE_FOR_JAVA (ref)) ! error ("Java class %qT cannot have virtual bases", ref); ! } ! ! for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list)) ! { ! tree access = TREE_PURPOSE (base_list); ! int via_virtual = TREE_TYPE (base_list) != NULL_TREE; ! tree basetype = TREE_VALUE (base_list); ! ! if (access == access_default_node) ! access = default_access; ! ! if (TREE_CODE (basetype) == TYPE_DECL) ! basetype = TREE_TYPE (basetype); ! if (TREE_CODE (basetype) != RECORD_TYPE ! && TREE_CODE (basetype) != TYPENAME_TYPE ! && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM ! && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM) { ! error ("base type %qT fails to be a struct or class type", ! basetype); ! continue; ! } ! ! if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0)) ! TYPE_FOR_JAVA (ref) = 1; ! ! base_binfo = NULL_TREE; ! if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype)) ! { ! base_binfo = TYPE_BINFO (basetype); ! /* The original basetype could have been a typedef'd type. */ ! basetype = BINFO_TYPE (base_binfo); ! ! /* Inherit flags from the base. */ ! TYPE_HAS_NEW_OPERATOR (ref) ! |= TYPE_HAS_NEW_OPERATOR (basetype); ! TYPE_HAS_ARRAY_NEW_OPERATOR (ref) ! |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype); ! TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); ! TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype); ! CLASSTYPE_DIAMOND_SHAPED_P (ref) ! |= CLASSTYPE_DIAMOND_SHAPED_P (basetype); ! CLASSTYPE_REPEATED_BASE_P (ref) ! |= CLASSTYPE_REPEATED_BASE_P (basetype); } ! /* We must do this test after we've seen through a typedef ! type. */ ! if (TYPE_MARKED_P (basetype)) { ! if (basetype == ref) ! error ("recursive type %qT undefined", basetype); ! else ! error ("duplicate base type %qT invalid", basetype); ! continue; } ! TYPE_MARKED_P (basetype) = 1; ! base_binfo = copy_binfo (base_binfo, basetype, ref, ! &igo_prev, via_virtual); ! if (!BINFO_INHERITANCE_CHAIN (base_binfo)) ! BINFO_INHERITANCE_CHAIN (base_binfo) = binfo; ! ! BINFO_BASE_APPEND (binfo, base_binfo); ! BINFO_BASE_ACCESS_APPEND (binfo, access); } + if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1)) + /* If we have space in the vbase vector, we must have shared at + least one of them, and are therefore diamond shaped. */ + CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1; + /* Unmark all the types. */ ! for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) ! TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0; ! TYPE_MARKED_P (ref) = 0; ! ! /* Now see if we have a repeated base type. */ ! if (!CLASSTYPE_REPEATED_BASE_P (ref)) { ! for (base_binfo = binfo; base_binfo; ! base_binfo = TREE_CHAIN (base_binfo)) { ! if (TYPE_MARKED_P (BINFO_TYPE (base_binfo))) ! { ! CLASSTYPE_REPEATED_BASE_P (ref) = 1; ! break; ! } ! TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 1; } + for (base_binfo = binfo; base_binfo; + base_binfo = TREE_CHAIN (base_binfo)) + if (TYPE_MARKED_P (BINFO_TYPE (base_binfo))) + TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0; + else + break; } } /* Begin compiling the definition of an enumeration type. ! NAME is its name. Returns the type object, as yet incomplete. Also records info about it so that build_enumerator may be used to declare the individual values as they are read. */ *************** xref_basetypes (tree ref, tree base_list *** 9775,9801 **** tree start_enum (tree name) { ! tree enumtype = NULL_TREE; ! 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 forward reference. */ ! if (name != NULL_TREE) ! enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1); if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE) { ! error ("multiple definition of `%#T'", enumtype); error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype)); /* Clear out TYPE_VALUES, and start again. */ TYPE_VALUES (enumtype) = NULL_TREE; } else { enumtype = make_node (ENUMERAL_TYPE); ! pushtag (name, enumtype, 0); } return enumtype; --- 9446,9479 ---- tree start_enum (tree name) { ! tree enumtype; ! ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); /* If this is the real definition for a previous forward reference, fill in the contents in the same object that used to be the forward reference. */ ! enumtype = lookup_and_check_tag (enum_type, name, ! /*tag_scope=*/ts_current, ! /*template_header_p=*/false); if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE) { ! error ("multiple definition of %q#T", enumtype); error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype)); /* Clear out TYPE_VALUES, and start again. */ TYPE_VALUES (enumtype) = NULL_TREE; } else { + /* In case of error, make a dummy enum to allow parsing to + continue. */ + if (enumtype == error_mark_node) + name = make_anon_name (); + enumtype = make_node (ENUMERAL_TYPE); ! enumtype = pushtag (name, enumtype, 0); } return enumtype; *************** finish_enum (tree enumtype) *** 9815,9822 **** tree maxnode; tree t; bool unsignedp; int lowprec; ! int highprec; int precision; integer_type_kind itk; tree underlying_type = NULL_TREE; --- 9493,9501 ---- tree maxnode; tree t; bool unsignedp; + bool use_short_enum; int lowprec; ! int highprec; int precision; integer_type_kind itk; tree underlying_type = NULL_TREE; *************** finish_enum (tree enumtype) *** 9830,9837 **** works. */ if (processing_template_decl) { ! for (values = TYPE_VALUES (enumtype); ! values; values = TREE_CHAIN (values)) TREE_TYPE (TREE_VALUE (values)) = enumtype; if (at_function_scope_p ()) --- 9509,9516 ---- works. */ if (processing_template_decl) { ! for (values = TYPE_VALUES (enumtype); ! values; values = TREE_CHAIN (values)) TREE_TYPE (TREE_VALUE (values)) = enumtype; if (at_function_scope_p ()) *************** finish_enum (tree enumtype) *** 9844,9851 **** { minnode = maxnode = NULL_TREE; ! for (values = TYPE_VALUES (enumtype); ! values; values = TREE_CHAIN (values)) { decl = TREE_VALUE (values); --- 9523,9530 ---- { minnode = maxnode = NULL_TREE; ! for (values = TYPE_VALUES (enumtype); ! values; values = TREE_CHAIN (values)) { decl = TREE_VALUE (values); *************** finish_enum (tree enumtype) *** 9866,9881 **** 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; - } } } else --- 9545,9550 ---- *************** finish_enum (tree enumtype) *** 9903,9920 **** enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of ! an enumerator cannot fit in an int or unsigned int. We use "int" or an "unsigned int" as the underlying type, even if a smaller integral type would work, unless the user has ! explicitly requested that we use the smallest possible type. */ ! for (itk = (flag_short_enums ? itk_char : itk_int); ! itk != itk_none; itk++) { underlying_type = integer_types[itk]; if (TYPE_PRECISION (underlying_type) >= precision ! && TREE_UNSIGNED (underlying_type) == unsignedp) break; } if (itk == itk_none) --- 9572,9595 ---- enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of ! an enumerator cannot fit in an int or unsigned int. We use "int" or an "unsigned int" as the underlying type, even if a smaller integral type would work, unless the user has ! explicitly requested that we use the smallest possible type. The ! user can request that for all enumerations with a command line ! flag, or for just one enumeration with an attribute. */ ! ! use_short_enum = flag_short_enums ! || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype)); ! ! for (itk = (use_short_enum ? itk_char : itk_int); ! itk != itk_none; itk++) { underlying_type = integer_types[itk]; if (TYPE_PRECISION (underlying_type) >= precision ! && TYPE_UNSIGNED (underlying_type) == unsignedp) break; } if (itk == itk_none) *************** finish_enum (tree enumtype) *** 9924,9935 **** IF no integral type can represent all the enumerator values, the enumeration is ill-formed. */ error ("no integral type can represent all of the enumerator values " ! "for `%T'", enumtype); precision = TYPE_PRECISION (long_long_integer_type_node); underlying_type = integer_types[itk_unsigned_long_long]; } ! /* Compute the minium and maximum values for the type. [dcl.enum] --- 9599,9610 ---- IF no integral type can represent all the enumerator values, the enumeration is ill-formed. */ error ("no integral type can represent all of the enumerator values " ! "for %qT", enumtype); precision = TYPE_PRECISION (long_long_integer_type_node); underlying_type = integer_types[itk_unsigned_long_long]; } ! /* Compute the minium and maximum values for the type. [dcl.enum] *************** finish_enum (tree enumtype) *** 9943,9955 **** narrower than their underlying type are suitably zero or sign extended to fill their mode. g++ doesn't make these guarantees. Until the middle-end can represent such paradoxical types, we ! set the TYPE_PRECISON to the width of the underlying type. */ TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type); set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp); /* [dcl.enum] ! The value of sizeof() applied to an enumeration type, an object of an enumeration type, or an enumerator, is the value of sizeof() applied to the underlying type. */ --- 9618,9630 ---- narrower than their underlying type are suitably zero or sign extended to fill their mode. g++ doesn't make these guarantees. Until the middle-end can represent such paradoxical types, we ! set the TYPE_PRECISION to the width of the underlying type. */ TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type); set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp); /* [dcl.enum] ! The value of sizeof() applied to an enumeration type, an object of an enumeration type, or an enumerator, is the value of sizeof() applied to the underlying type. */ *************** finish_enum (tree enumtype) *** 9958,9964 **** TYPE_MODE (enumtype) = TYPE_MODE (underlying_type); TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type); TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type); ! TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (underlying_type); /* Convert each of the enumerators to the type of the underlying type of the enumeration. */ --- 9633,9639 ---- TYPE_MODE (enumtype) = TYPE_MODE (underlying_type); TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type); TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type); ! TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type); /* Convert each of the enumerators to the type of the underlying type of the enumeration. */ *************** finish_enum (tree enumtype) *** 9967,9972 **** --- 9642,9651 ---- decl = TREE_VALUE (values); value = perform_implicit_conversion (underlying_type, DECL_INITIAL (decl)); + + /* Do not clobber shared ints. */ + value = copy_node (value); + TREE_TYPE (value) = enumtype; DECL_INITIAL (decl) = value; TREE_VALUE (values) = value; *************** finish_enum (tree enumtype) *** 9984,9990 **** TYPE_PRECISION (t) = TYPE_PRECISION (enumtype); TYPE_ALIGN (t) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype); ! TREE_UNSIGNED (t) = TREE_UNSIGNED (enumtype); } /* Finish debugging output for this type. */ --- 9663,9669 ---- TYPE_PRECISION (t) = TYPE_PRECISION (enumtype); TYPE_ALIGN (t) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype); ! TYPE_UNSIGNED (t) = TYPE_UNSIGNED (enumtype); } /* Finish debugging output for this type. */ *************** build_enumerator (tree name, tree value, *** 10002,10007 **** --- 9681,9691 ---- tree context; tree type; + /* If the VALUE was erroneous, pretend it wasn't there; that will + result in the enum being assigned the next value in sequence. */ + if (value == error_mark_node) + value = NULL_TREE; + /* Remove no-op casts from the value. */ if (value) STRIP_TYPE_NOPS (value); *************** build_enumerator (tree name, tree value, *** 10011,10017 **** /* Validate and default VALUE. */ if (value != NULL_TREE) { ! value = decl_constant_value (value); if (TREE_CODE (value) == INTEGER_CST) { --- 9695,9701 ---- /* Validate and default VALUE. */ if (value != NULL_TREE) { ! value = integral_constant_value (value); if (TREE_CODE (value) == INTEGER_CST) { *************** build_enumerator (tree name, tree value, *** 10020,10026 **** } else { ! error ("enumerator value for `%D' not integer constant", name); value = NULL_TREE; } } --- 9704,9710 ---- } else { ! error ("enumerator value for %qD not integer constant", name); value = NULL_TREE; } } *************** build_enumerator (tree name, tree value, *** 10028,10046 **** /* Default based on previous value. */ if (value == NULL_TREE) { - tree prev_value; - if (TYPE_VALUES (enumtype)) { ! /* 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, ! prev_value, ! integer_one_node); ! if (tree_int_cst_lt (value, prev_value)) ! error ("overflow in enumeration values at `%D'", name); } else value = integer_zero_node; --- 9712,9737 ---- /* Default based on previous value. */ if (value == NULL_TREE) { if (TYPE_VALUES (enumtype)) { ! HOST_WIDE_INT hi; ! unsigned HOST_WIDE_INT lo; ! tree prev_value; ! bool overflowed; ! ! /* The next value is the previous value plus one. We can ! safely assume that the previous value is an INTEGER_CST. ! add_double doesn't know the type of the target expression, ! so we must check with int_fits_type_p as well. */ prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype))); ! overflowed = add_double (TREE_INT_CST_LOW (prev_value), ! TREE_INT_CST_HIGH (prev_value), ! 1, 0, &lo, &hi); ! value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi); ! overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value)); ! if (overflowed) ! error ("overflow in enumeration values at %qD", name); } else value = integer_zero_node; *************** build_enumerator (tree name, tree value, *** 10052,10059 **** /* C++ associates enums with global, function, or class declarations. */ context = current_scope (); - if (!context) - context = current_namespace; /* Build the actual enumeration constant. Note that the enumeration constants have the type of their initializers until the --- 9743,9748 ---- *************** build_enumerator (tree name, tree value, *** 10080,10086 **** decl = build_decl (CONST_DECL, name, type); DECL_CONTEXT (decl) = FROB_CONTEXT (context); ! TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1; DECL_INITIAL (decl) = value; if (context && context == current_class_type) --- 9769,9777 ---- decl = build_decl (CONST_DECL, name, type); DECL_CONTEXT (decl) = FROB_CONTEXT (context); ! TREE_CONSTANT (decl) = 1; ! TREE_INVARIANT (decl) = 1; ! TREE_READONLY (decl) = 1; DECL_INITIAL (decl) = value; if (context && context == current_class_type) *************** check_function_type (tree decl, tree cur *** 10107,10115 **** /* In a function definition, arg types must be complete. */ require_complete_types_for_parms (current_function_parms); if (!COMPLETE_OR_VOID_TYPE_P (return_type)) { ! error ("return type `%#T' is incomplete", TREE_TYPE (fntype)); /* Make it return void instead, but don't change the type of the DECL_RESULT, in case we have a named return value. */ --- 9798,9808 ---- /* In a function definition, arg types must be complete. */ require_complete_types_for_parms (current_function_parms); + if (dependent_type_p (return_type)) + return; if (!COMPLETE_OR_VOID_TYPE_P (return_type)) { ! error ("return type %q#T is incomplete", TREE_TYPE (fntype)); /* Make it return void instead, but don't change the type of the DECL_RESULT, in case we have a named return value. */ *************** check_function_type (tree decl, tree cur *** 10146,10241 **** This function creates a binding context for the function body as well as setting up the FUNCTION_DECL in current_function_decl. - Returns 1 on success. If the DECLARATOR is not suitable for a function - (it defines a datum instead), we return 0, which tells - yyparse to report a parse error. - For C++, we must first check whether that datum makes any sense. For example, "class A local_a(1,2);" means that variable local_a is an aggregate of type A, which should have a constructor applied to it with the argument list [1, 2]. */ ! int ! start_function (tree declspecs, tree declarator, tree attrs, int flags) { - tree decl1; tree ctype = NULL_TREE; tree fntype; tree restype; int doing_friend = 0; struct cp_binding_level *bl; tree current_function_parms; /* Sanity check. */ ! my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160); ! 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) ! { ! declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); ! have_extern_spec = false; ! } ! ! if (flags & SF_PRE_PARSED) ! { ! decl1 = declarator; ! ! fntype = TREE_TYPE (decl1); ! if (TREE_CODE (fntype) == METHOD_TYPE) ! ctype = TYPE_METHOD_BASETYPE (fntype); ! /* ISO C++ 11.4/5. A friend function defined in a class is in ! the (lexical) scope of the class in which it is defined. */ ! if (!ctype && DECL_FRIEND_P (decl1)) ! { ! ctype = DECL_FRIEND_CONTEXT (decl1); ! /* CTYPE could be null here if we're dealing with a template; ! for example, `inline friend float foo()' inside a template ! will have no CTYPE set. */ ! if (ctype && TREE_CODE (ctype) != RECORD_TYPE) ! ctype = NULL_TREE; ! else ! doing_friend = 1; ! } ! } ! else { ! decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs); ! /* If the declarator is not suitable for a function definition, ! cause a syntax error. */ ! if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) ! return 0; ! ! cplus_decl_attributes (&decl1, attrs, 0); ! ! /* If #pragma weak was used, mark the decl weak now. */ ! if (global_scope_p (current_binding_level)) ! maybe_apply_pragma_weak (decl1); ! ! fntype = TREE_TYPE (decl1); ! ! restype = TREE_TYPE (fntype); ! if (TREE_CODE (fntype) == METHOD_TYPE) ! ctype = TYPE_METHOD_BASETYPE (fntype); ! else if (DECL_MAIN_P (decl1)) ! { ! /* If this doesn't return integer_type, or a typedef to ! integer_type, complain. */ ! if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node)) ! { ! if (pedantic || warn_return_type) ! pedwarn ("return type for `main' changed to `int'"); ! TREE_TYPE (decl1) = fntype = default_function_type; ! } ! } } if (DECL_DECLARED_INLINE_P (decl1) && lookup_attribute ("noinline", attrs)) ! warning ("%Jinline function '%D' given attribute noinline", decl1, decl1); if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1)) /* This is a constructor, we must ensure that any default args --- 9839,9886 ---- This function creates a binding context for the function body as well as setting up the FUNCTION_DECL in current_function_decl. For C++, we must first check whether that datum makes any sense. For example, "class A local_a(1,2);" means that variable local_a is an aggregate of type A, which should have a constructor applied to it with the argument list [1, 2]. */ ! void ! start_preparsed_function (tree decl1, tree attrs, int flags) { tree ctype = NULL_TREE; tree fntype; tree restype; int doing_friend = 0; struct cp_binding_level *bl; tree current_function_parms; + struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename)); /* Sanity check. */ ! gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE); ! gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE); ! fntype = TREE_TYPE (decl1); ! if (TREE_CODE (fntype) == METHOD_TYPE) ! ctype = TYPE_METHOD_BASETYPE (fntype); ! /* ISO C++ 11.4/5. A friend function defined in a class is in ! the (lexical) scope of the class in which it is defined. */ ! if (!ctype && DECL_FRIEND_P (decl1)) { ! ctype = DECL_FRIEND_CONTEXT (decl1); ! /* CTYPE could be null here if we're dealing with a template; ! for example, `inline friend float foo()' inside a template ! will have no CTYPE set. */ ! if (ctype && TREE_CODE (ctype) != RECORD_TYPE) ! ctype = NULL_TREE; ! else ! doing_friend = 1; } if (DECL_DECLARED_INLINE_P (decl1) && lookup_attribute ("noinline", attrs)) ! warning ("%Jinline function %qD given attribute noinline", decl1, decl1); if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1)) /* This is a constructor, we must ensure that any default args *************** start_function (tree declspecs, tree dec *** 10252,10263 **** ctype = NULL_TREE; } - /* Warn if function was previously implicitly declared - (but not if we warned then). */ - if (! warn_implicit - && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE) - cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))); - /* Set up current_class_type, and enter the scope of the class, if appropriate. */ if (ctype) --- 9897,9902 ---- *************** start_function (tree declspecs, tree dec *** 10278,10284 **** if (warn_ecpp && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE) ! warning ("`operator=' should return a reference to `*this'"); /* Make the init_value nonzero so pushdecl knows this is not tentative. error_mark_node is replaced below (in poplevel) with the BLOCK. */ --- 9917,9923 ---- if (warn_ecpp && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE) ! warning ("% should return a reference to %<*this%>"); /* Make the init_value nonzero so pushdecl knows this is not tentative. error_mark_node is replaced below (in poplevel) with the BLOCK. */ *************** start_function (tree declspecs, tree dec *** 10294,10300 **** class scope, current_class_type will be NULL_TREE until set above by push_nested_class.) */ if (processing_template_decl) ! decl1 = push_template_decl (decl1); /* We are now in the scope of the function being defined. */ current_function_decl = decl1; --- 9933,9944 ---- class scope, current_class_type will be NULL_TREE until set above by push_nested_class.) */ if (processing_template_decl) ! { ! /* FIXME: Handle error_mark_node more gracefully. */ ! tree newdecl1 = push_template_decl (decl1); ! if (newdecl1 != error_mark_node) ! decl1 = newdecl1; ! } /* We are now in the scope of the function being defined. */ current_function_decl = decl1; *************** start_function (tree declspecs, tree dec *** 10306,10313 **** /* Make sure the parameter and return types are reasonable. When you declare a function, these types can be incomplete, but they must be complete when you define the function. */ ! if (! processing_template_decl) ! check_function_type (decl1, current_function_parms); /* Build the return declaration for the function. */ restype = TREE_TYPE (fntype); --- 9950,9956 ---- /* Make sure the parameter and return types are reasonable. When you declare a function, these types can be incomplete, but they must be complete when you define the function. */ ! check_function_type (decl1, current_function_parms); /* Build the return declaration for the function. */ restype = TREE_TYPE (fntype); *************** start_function (tree declspecs, tree dec *** 10316,10325 **** restype = type_promotes_to (restype); if (DECL_RESULT (decl1) == NULL_TREE) { ! DECL_RESULT (decl1) ! = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); ! c_apply_type_quals_to_decl (cp_type_quals (restype), ! DECL_RESULT (decl1)); } /* Initialize RTL machinery. We cannot do this until --- 9959,9972 ---- restype = type_promotes_to (restype); if (DECL_RESULT (decl1) == NULL_TREE) { ! tree resdecl; ! ! resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); ! DECL_ARTIFICIAL (resdecl) = 1; ! DECL_IGNORED_P (resdecl) = 1; ! DECL_RESULT (decl1) = resdecl; ! ! cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl); } /* Initialize RTL machinery. We cannot do this until *************** start_function (tree declspecs, tree dec *** 10335,10345 **** call expand_expr to calculate the size of a variable-sized array. We haven't necessarily assigned RTL to all variables yet, so it's not safe to try to expand expressions involving them. */ - immediate_size_expand = 0; cfun->x_dont_save_pending_sizes_p = 1; /* Start the statement-tree, start the tree now. */ ! begin_stmt_tree (&DECL_SAVED_TREE (decl1)); /* Let the user know we're compiling this function. */ announce_function (decl1); --- 9982,9991 ---- call expand_expr to calculate the size of a variable-sized array. We haven't necessarily assigned RTL to all variables yet, so it's not safe to try to expand expressions involving them. */ cfun->x_dont_save_pending_sizes_p = 1; /* Start the statement-tree, start the tree now. */ ! DECL_SAVED_TREE (decl1) = push_stmt_list (); /* Let the user know we're compiling this function. */ announce_function (decl1); *************** start_function (tree declspecs, tree dec *** 10351,10357 **** { /* A specialization is not used to guide overload resolution. */ if (!DECL_FUNCTION_MEMBER_P (decl1) ! && !(DECL_USE_TEMPLATE (decl1) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1)))) { tree olddecl = pushdecl (decl1); --- 9997,10003 ---- { /* A specialization is not used to guide overload resolution. */ if (!DECL_FUNCTION_MEMBER_P (decl1) ! && !(DECL_USE_TEMPLATE (decl1) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1)))) { tree olddecl = pushdecl (decl1); *************** start_function (tree declspecs, tree dec *** 10377,10382 **** --- 10023,10034 ---- fntype = TREE_TYPE (decl1); } + /* Determine the ELF visibility attribute for the function. We must + not do this before calling "pushdecl", as we must allow + "duplicate_decls" to merge any attributes appropriately. */ + if (!DECL_CLONED_FUNCTION_P (decl1)) + determine_visibility (decl1); + /* Reset these in case the call to pushdecl changed them. */ current_function_decl = decl1; cfun->decl = decl1; *************** start_function (tree declspecs, tree dec *** 10394,10403 **** between `current_class_type' and `current_class_ptr'. */ tree t = DECL_ARGUMENTS (decl1); ! my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL, ! 162); ! my_friendly_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE, ! 19990811); cp_function_chain->x_current_class_ref = build_indirect_ref (t, NULL); --- 10046,10053 ---- between `current_class_type' and `current_class_ptr'. */ tree t = DECL_ARGUMENTS (decl1); ! gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL); ! gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE); cp_function_chain->x_current_class_ref = build_indirect_ref (t, NULL); *************** start_function (tree declspecs, tree dec *** 10413,10420 **** } if (DECL_HAS_VTT_PARM_P (decl1)) { ! if (DECL_NAME (t) != vtt_parm_identifier) ! abort (); current_vtt_parm = t; } } --- 10063,10069 ---- } if (DECL_HAS_VTT_PARM_P (decl1)) { ! gcc_assert (DECL_NAME (t) == vtt_parm_identifier); current_vtt_parm = t; } } *************** start_function (tree declspecs, tree dec *** 10435,10450 **** /* If this function belongs to an interface, it is public. If it belongs to someone else's interface, it is also external. This only affects inlines and template instantiations. */ ! else if (interface_unknown == 0 && ! DECL_TEMPLATE_INSTANTIATION (decl1)) { ! if (DECL_DECLARED_INLINE_P (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1) || processing_template_decl) { DECL_EXTERNAL (decl1) ! = (interface_only ! || (DECL_DECLARED_INLINE_P (decl1) && ! flag_implement_inlines && !DECL_VINDEX (decl1))); --- 10084,10099 ---- /* If this function belongs to an interface, it is public. If it belongs to someone else's interface, it is also external. This only affects inlines and template instantiations. */ ! else if (finfo->interface_unknown == 0 && ! DECL_TEMPLATE_INSTANTIATION (decl1)) { ! if (DECL_DECLARED_INLINE_P (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1) || processing_template_decl) { DECL_EXTERNAL (decl1) ! = (finfo->interface_only ! || (DECL_DECLARED_INLINE_P (decl1) && ! flag_implement_inlines && !DECL_VINDEX (decl1))); *************** start_function (tree declspecs, tree dec *** 10455,10469 **** DECL_EXTERNAL (decl1) = 0; DECL_NOT_REALLY_EXTERN (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; } ! else if (interface_unknown && interface_only && ! DECL_TEMPLATE_INSTANTIATION (decl1)) { /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma ! interface, we will have interface_only set but not ! interface_known. In that case, we don't want to use the normal ! heuristics because someone will supply a #pragma implementation ! elsewhere, and deducing it here would produce a conflict. */ comdat_linkage (decl1); DECL_EXTERNAL (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; --- 10104,10124 ---- DECL_EXTERNAL (decl1) = 0; DECL_NOT_REALLY_EXTERN (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; + /* If this function is in an interface implemented in this file, + make sure that the backend knows to emit this function + here. */ + if (!DECL_EXTERNAL (decl1)) + mark_needed (decl1); } ! else if (finfo->interface_unknown && finfo->interface_only && ! DECL_TEMPLATE_INSTANTIATION (decl1)) { /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma ! interface, we will have both finfo->interface_unknown and ! finfo->interface_only set. In that case, we don't want to ! use the normal heuristics because someone will supply a ! #pragma implementation elsewhere, and deducing it here would ! produce a conflict. */ comdat_linkage (decl1); DECL_EXTERNAL (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; *************** start_function (tree declspecs, tree dec *** 10475,10481 **** So clear DECL_EXTERNAL. */ DECL_EXTERNAL (decl1) = 0; ! if ((DECL_DECLARED_INLINE_P (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) && ! DECL_INTERFACE_KNOWN (decl1) /* Don't try to defer nested functions for now. */ --- 10130,10136 ---- So clear DECL_EXTERNAL. */ DECL_EXTERNAL (decl1) = 0; ! if ((DECL_DECLARED_INLINE_P (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) && ! DECL_INTERFACE_KNOWN (decl1) /* Don't try to defer nested functions for now. */ *************** start_function (tree declspecs, tree dec *** 10489,10503 **** ++function_depth; ! if (DECL_DESTRUCTOR_P (decl1)) { ! dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! DECL_CONTEXT (dtor_label) = current_function_decl; } start_fname_decls (); ! store_parm_decls (current_function_parms); return 1; } --- 10144,10201 ---- ++function_depth; ! if (DECL_DESTRUCTOR_P (decl1) ! || (DECL_CONSTRUCTOR_P (decl1) ! && targetm.cxx.cdtor_returns_this ())) { ! cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! DECL_CONTEXT (cdtor_label) = current_function_decl; } start_fname_decls (); ! store_parm_decls (current_function_parms); + } + + + /* Like start_preparsed_function, except that instead of a + FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR. + + Returns 1 on success. If the DECLARATOR is not suitable for a function + (it defines a datum instead), we return 0, which tells + yyparse to report a parse error. */ + + int + start_function (cp_decl_specifier_seq *declspecs, + const cp_declarator *declarator, + tree attrs) + { + tree decl1; + + if (have_extern_spec) + { + declspecs->storage_class = sc_extern; + /* This should only be done once on the outermost decl. */ + have_extern_spec = false; + } + + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs); + /* If the declarator is not suitable for a function definition, + cause a syntax error. */ + if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) + return 0; + + /* If #pragma weak was used, mark the decl weak now. */ + if (global_scope_p (current_binding_level)) + maybe_apply_pragma_weak (decl1); + + if (DECL_MAIN_P (decl1)) + /* main must return int. grokfndecl should have corrected it + (and issued a diagnostic) if the user got it wrong. */ + gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)), + integer_type_node)); + + start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT); return 1; } *************** store_parm_decls (tree current_function_ *** 10547,10553 **** || TREE_CODE (parm) != VOID_TYPE) pushdecl (parm); else ! error ("parameter `%D' declared void", parm); } else { --- 10245,10251 ---- || TREE_CODE (parm) != VOID_TYPE) pushdecl (parm); else ! error ("parameter %qD declared void", parm); } else { *************** store_parm_decls (tree current_function_ *** 10572,10582 **** DECL_ARGUMENTS is not modified. */ current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl)); ! /* Do the starting of the exception specifications, if we have any. */ ! if (flag_exceptions && !processing_template_decl ! && flag_enforce_eh_specs ! && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) ! current_eh_spec_block = begin_eh_spec_block (); } --- 10270,10285 ---- DECL_ARGUMENTS is not modified. */ current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl)); ! /* For a cloned function, we've already got all the code we need; ! there's no need to add any extra bits. */ ! if (!DECL_CLONED_FUNCTION_P (fndecl)) ! { ! /* Do the starting of the exception specifications, if we have any. */ ! if (flag_exceptions && !processing_template_decl ! && flag_enforce_eh_specs ! && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) ! current_eh_spec_block = begin_eh_spec_block (); ! } } *************** save_function_data (tree decl) *** 10591,10637 **** /* Save the language-specific per-function data so that we can get it back when we really expand this function. */ ! my_friendly_assert (!DECL_PENDING_INLINE_P (decl), ! 19990908); /* Make a copy. */ ! f = 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. */ ! f->base.x_stmt_tree.x_last_stmt = NULL_TREE; ! f->base.x_stmt_tree.x_last_expr_type = NULL_TREE; f->x_named_label_uses = NULL; f->bindings = NULL; f->x_local_names = NULL; - - /* If we've already decided that we cannot inline this function, we - must remember that fact when we actually go to expand the - function. */ - if (current_function_cannot_inline) - { - f->cannot_inline = current_function_cannot_inline; - DECL_INLINE (decl) = 0; - } } - /* Add a note to mark the beginning of the main body of the constructor. - This is used to set up the data structures for the cleanup regions for - fully-constructed bases and members. */ ! static void ! begin_constructor_body (void) ! { ! } ! ! /* Add a note to mark the end of the main body of the constructor. This is ! used to end the cleanup regions for fully-constructed bases and ! members. */ static void finish_constructor_body (void) { } /* Do all the processing for the beginning of a destructor; set up the --- 10294,10334 ---- /* Save the language-specific per-function data so that we can get it back when we really expand this function. */ ! gcc_assert (!DECL_PENDING_INLINE_P (decl)); /* Make a copy. */ ! f = GGC_NEW (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. */ ! f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE; f->x_named_label_uses = NULL; f->bindings = NULL; f->x_local_names = NULL; } ! /* Set the return value of the constructor (if present). */ static void finish_constructor_body (void) { + tree val; + tree exprstmt; + + if (targetm.cxx.cdtor_returns_this ()) + { + /* Any return from a constructor will end up here. */ + add_stmt (build_stmt (LABEL_EXPR, cdtor_label)); + + val = DECL_ARGUMENTS (current_function_decl); + val = build2 (MODIFY_EXPR, TREE_TYPE (val), + DECL_RESULT (current_function_decl), val); + /* Return the address of the object. */ + exprstmt = build_stmt (RETURN_EXPR, val); + add_stmt (exprstmt); + } } /* Do all the processing for the beginning of a destructor; set up the *************** begin_destructor_body (void) *** 10659,10671 **** if_stmt = begin_if_stmt (); /* If it is not safe to avoid setting up the vtables, then ! someone will change the condition to be boolean_true_node. (Actually, for now, we do not have code to set the condition appropriately, so we just assume that we always need to initialize the vtables.) */ finish_if_stmt_cond (boolean_true_node, if_stmt); ! compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); /* Make all virtual function table pointers in non-virtual base classes point to CURRENT_CLASS_TYPE's virtual function --- 10356,10368 ---- if_stmt = begin_if_stmt (); /* If it is not safe to avoid setting up the vtables, then ! someone will change the condition to be boolean_true_node. (Actually, for now, we do not have code to set the condition appropriately, so we just assume that we always need to initialize the vtables.) */ finish_if_stmt_cond (boolean_true_node, if_stmt); ! compound_stmt = begin_compound_stmt (0); /* Make all virtual function table pointers in non-virtual base classes point to CURRENT_CLASS_TYPE's virtual function *************** begin_destructor_body (void) *** 10674,10680 **** finish_compound_stmt (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. */ --- 10371,10377 ---- finish_compound_stmt (compound_stmt); finish_then_clause (if_stmt); ! finish_if_stmt (if_stmt); /* And insert cleanups for our bases and members so that they will be properly destroyed if we throw. */ *************** finish_destructor_body (void) *** 10691,10697 **** /* Any return from a destructor will end up here; that way all base and member cleanups will be run when the function returns. */ ! add_stmt (build_stmt (LABEL_STMT, dtor_label)); /* In a virtual destructor, we must call delete. */ if (DECL_VIRTUAL_P (current_function_decl)) --- 10388,10394 ---- /* Any return from a destructor will end up here; that way all base and member cleanups will be run when the function returns. */ ! add_stmt (build_stmt (LABEL_EXPR, cdtor_label)); /* In a virtual destructor, we must call delete. */ if (DECL_VIRTUAL_P (current_function_decl)) *************** finish_destructor_body (void) *** 10707,10722 **** found shall be accessible and unambiguous. */ exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, virtual_size, ! LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); if_stmt = begin_if_stmt (); ! finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node, ! current_in_charge_parm, ! integer_one_node), if_stmt); finish_expr_stmt (exprstmt); finish_then_clause (if_stmt); ! finish_if_stmt (); } } --- 10404,10431 ---- found shall be accessible and unambiguous. */ exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, virtual_size, ! /*global_p=*/false, NULL_TREE); if_stmt = begin_if_stmt (); ! finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node, ! current_in_charge_parm, ! integer_one_node), if_stmt); finish_expr_stmt (exprstmt); finish_then_clause (if_stmt); ! finish_if_stmt (if_stmt); ! } ! ! if (targetm.cxx.cdtor_returns_this ()) ! { ! tree val; ! ! val = DECL_ARGUMENTS (current_function_decl); ! val = build2 (MODIFY_EXPR, TREE_TYPE (val), ! DECL_RESULT (current_function_decl), val); ! /* Return the address of the object. */ ! exprstmt = build_stmt (RETURN_EXPR, val); ! add_stmt (exprstmt); } } *************** begin_function_body (void) *** 10739,10751 **** operation of dwarfout.c. */ keep_next_level (true); ! stmt = begin_compound_stmt (/*has_no_scope=*/false); ! COMPOUND_STMT_BODY_BLOCK (stmt) = 1; if (processing_template_decl) /* Do nothing now. */; - else if (DECL_CONSTRUCTOR_P (current_function_decl)) - begin_constructor_body (); else if (DECL_DESTRUCTOR_P (current_function_decl)) begin_destructor_body (); --- 10448,10457 ---- operation of dwarfout.c. */ keep_next_level (true); ! stmt = begin_compound_stmt (BCS_FN_BODY); if (processing_template_decl) /* Do nothing now. */; else if (DECL_DESTRUCTOR_P (current_function_decl)) begin_destructor_body (); *************** finish_function_body (tree compstmt) *** 10773,10779 **** finish_constructor_body (); else if (DECL_DESTRUCTOR_P (current_function_decl)) finish_destructor_body (); ! } /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage --- 10479,10485 ---- finish_constructor_body (); else if (DECL_DESTRUCTOR_P (current_function_decl)) finish_destructor_body (); ! } /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage *************** finish_function (int flags) *** 10814,10833 **** This caused &foo to be of type ptr-to-const-function which then got a warning when stored in a ptr-to-function variable. */ ! my_friendly_assert (building_stmt_tree (), 20000911); ! /* For a cloned function, we've already got all the code we need; there's no need to add any extra bits. */ if (!DECL_CLONED_FUNCTION_P (fndecl)) { if (DECL_MAIN_P (current_function_decl)) { ! /* Make it so that `main' always returns 0 by default. */ #if VMS_TARGET ! finish_return_stmt (integer_one_node); #else ! finish_return_stmt (integer_zero_node); #endif } /* Finish dealing with exception specifiers. */ --- 10520,10546 ---- This caused &foo to be of type ptr-to-const-function which then got a warning when stored in a ptr-to-function variable. */ ! gcc_assert (building_stmt_tree ()); ! /* For a cloned function, we've already got all the code we need; there's no need to add any extra bits. */ if (!DECL_CLONED_FUNCTION_P (fndecl)) { if (DECL_MAIN_P (current_function_decl)) { ! tree stmt; ! ! /* Make it so that `main' always returns 0 by default (or ! 1 for VMS). */ #if VMS_TARGET ! stmt = finish_return_stmt (integer_one_node); #else ! stmt = finish_return_stmt (integer_zero_node); #endif + /* Hack. We don't want the middle-end to warn that this + return is unreachable, so put the statement on the + special line 0. */ + annotate_with_file_line (stmt, input_filename, 0); } /* Finish dealing with exception specifiers. */ *************** finish_function (int flags) *** 10839,10848 **** current_eh_spec_block); } - finish_fname_decls (); - /* 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 --- 10552,10561 ---- current_eh_spec_block); } /* If we're saving up tree structure, tie off the function now. */ ! DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); ! ! finish_fname_decls (); /* If this function can't throw any exceptions, remember that. */ if (!processing_template_decl *************** finish_function (int flags) *** 10853,10871 **** /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ ! /* If the current binding level isn't the outermost binding level for this function, either there is a bug, or we have experienced syntax errors and the statement tree is malformed. */ if (current_binding_level->kind != sk_function_parms) { /* Make sure we have already experienced errors. */ ! if (errorcount == 0) ! abort (); /* Throw away the broken statement tree and extra binding levels. */ ! DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE); while (current_binding_level->kind != sk_function_parms) { --- 10566,10583 ---- /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ ! /* If the current binding level isn't the outermost binding level for this function, either there is a bug, or we have experienced syntax errors and the statement tree is malformed. */ if (current_binding_level->kind != sk_function_parms) { /* Make sure we have already experienced errors. */ ! gcc_assert (errorcount); /* Throw away the broken statement tree and extra binding levels. */ ! DECL_SAVED_TREE (fndecl) = alloc_stmt_list (); while (current_binding_level->kind != sk_function_parms) { *************** finish_function (int flags) *** 10879,10890 **** /* Statements should always be full-expressions at the outermost set of curly braces for a function. */ ! my_friendly_assert (stmts_are_full_exprs_p (), 19990831); ! /* Set up the named return value optimization, if we can. Here, we ! eliminate the copy from the nrv into the RESULT_DECL and any cleanup ! for the nrv. genrtl_start_function and declare_return_variable ! handle making the nrv and RESULT_DECL share space. */ if (current_function_return_value) { tree r = current_function_return_value; --- 10591,10600 ---- /* Statements should always be full-expressions at the outermost set of curly braces for a function. */ ! gcc_assert (stmts_are_full_exprs_p ()); ! /* Set up the named return value optimization, if we can. Candidate ! variables are selected in check_return_value. */ if (current_function_return_value) { tree r = current_function_return_value; *************** finish_function (int flags) *** 10898,10916 **** 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. */ /* Skip the artificial function body block. */ ! && (outer = BLOCK_SUBBLOCKS (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); ! } ! else ! /* Clear it so genrtl_start_function and declare_return_variable ! know we're not optimizing. */ ! current_function_return_value = NULL_TREE; } /* Remember that we were in class scope. */ --- 10608,10620 ---- 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))) /* Skip the artificial function body block. */ ! && (outer = BLOCK_SUBBLOCKS (outer)) ! && chain_member (r, BLOCK_VARS (outer))) ! finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl)); ! ! current_function_return_value = NULL_TREE; } /* Remember that we were in class scope. */ *************** finish_function (int flags) *** 10928,10945 **** if (!processing_template_decl) save_function_data (fndecl); - /* If this function calls `setjmp' it cannot be inlined. When - `longjmp' is called it is not guaranteed to restore the value of - local variables that have been modified since the call to - `setjmp'. So, if were to inline this function into some caller - `c', then when we `longjmp', we might not restore all variables - in `c'. (It might seem, at first blush, that there's no way for - this function to modify local variables in `c', but their - addresses may have been stored somewhere accessible to this - function.) */ - if (!processing_template_decl && calls_setjmp_p (fndecl)) - DECL_UNINLINABLE (fndecl) = 1; - /* Complain if there's just no return statement. */ if (warn_return_type && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE --- 10632,10637 ---- *************** finish_function (int flags) *** 10950,10960 **** && !DECL_NAME (DECL_RESULT (fndecl)) /* Normally, with -Wreturn-type, flow will complain. Unless we're an inline function, as we might never be compiled separately. */ ! && (DECL_INLINE (fndecl) || processing_template_decl)) warning ("no return statement in function returning non-void"); /* We're leaving the context of this function, so zap cfun. It's still in ! DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */ cfun = NULL; current_function_decl = NULL; --- 10642,10680 ---- && !DECL_NAME (DECL_RESULT (fndecl)) /* Normally, with -Wreturn-type, flow will complain. Unless we're an inline function, as we might never be compiled separately. */ ! && (DECL_INLINE (fndecl) || processing_template_decl) ! /* Structor return values (if any) are set by the compiler. */ ! && !DECL_CONSTRUCTOR_P (fndecl) ! && !DECL_DESTRUCTOR_P (fndecl)) warning ("no return statement in function returning non-void"); + /* Store the end of the function, so that we get good line number + info for the epilogue. */ + cfun->function_end_locus = input_location; + + /* Genericize before inlining. */ + if (!processing_template_decl) + { + struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl); + cp_genericize (fndecl); + /* Clear out the bits we don't need. */ + f->x_current_class_ptr = NULL; + f->x_current_class_ref = NULL; + f->x_eh_spec_block = NULL; + f->x_in_charge_parm = NULL; + f->x_vtt_parm = NULL; + f->x_return_value = NULL; + f->bindings = NULL; + + /* Handle attribute((warn_unused_result)). Relies on gimple input. */ + c_warn_unused_result (&DECL_SAVED_TREE (fndecl)); + } + /* Clear out the bits we don't need. */ + local_names = NULL; + named_label_uses = NULL; + /* We're leaving the context of this function, so zap cfun. It's still in ! DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */ cfun = NULL; current_function_decl = NULL; *************** finish_function (int flags) *** 11003,11009 **** CHANGES TO CODE IN `grokfield'. */ tree ! start_method (tree declspecs, tree declarator, tree attrlist) { tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, &attrlist); --- 10723,10730 ---- CHANGES TO CODE IN `grokfield'. */ tree ! start_method (cp_decl_specifier_seq *declspecs, ! const cp_declarator *declarator, tree attrlist) { tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, &attrlist); *************** start_method (tree declspecs, tree decla *** 11026,11038 **** if (DECL_IN_AGGR_P (fndecl)) { ! if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type) ! { ! if (DECL_CONTEXT (fndecl) ! && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL) ! error ("`%D' is already defined in class `%T'", fndecl, ! DECL_CONTEXT (fndecl)); ! } return void_type_node; } --- 10747,10756 ---- if (DECL_IN_AGGR_P (fndecl)) { ! if (DECL_CONTEXT (fndecl) ! && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL) ! error ("%qD is already defined in class %qT", fndecl, ! DECL_CONTEXT (fndecl)); return void_type_node; } *************** finish_method (tree decl) *** 11108,11114 **** { if (DECL_NAME (link) != NULL_TREE) pop_binding (DECL_NAME (link), link); ! my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163); DECL_CONTEXT (link) = NULL_TREE; } --- 10826,10832 ---- { if (DECL_NAME (link) != NULL_TREE) pop_binding (DECL_NAME (link), link); ! gcc_assert (TREE_CODE (link) != FUNCTION_DECL); DECL_CONTEXT (link) = NULL_TREE; } *************** finish_method (tree decl) *** 11121,11128 **** for String.cc in libg++. */ if (DECL_FRIEND_P (fndecl)) { ! CLASSTYPE_INLINE_FRIENDS (current_class_type) ! = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type)); decl = void_type_node; } --- 10839,10846 ---- for String.cc in libg++. */ if (DECL_FRIEND_P (fndecl)) { ! VEC_safe_push (tree, CLASSTYPE_INLINE_FRIENDS (current_class_type), ! fndecl); decl = void_type_node; } *************** finish_method (tree decl) *** 11136,11153 **** void maybe_register_incomplete_var (tree var) { ! my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406); /* Keep track of variables with incomplete types. */ ! if (!processing_template_decl && TREE_TYPE (var) != error_mark_node && DECL_EXTERNAL (var)) { tree inner_type = TREE_TYPE (var); ! while (TREE_CODE (inner_type) == ARRAY_TYPE) inner_type = TREE_TYPE (inner_type); inner_type = TYPE_MAIN_VARIANT (inner_type); ! if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type)) /* RTTI TD entries are created while defining the type_info. */ || (TYPE_LANG_SPECIFIC (inner_type) --- 10854,10871 ---- void maybe_register_incomplete_var (tree var) { ! gcc_assert (TREE_CODE (var) == VAR_DECL); /* Keep track of variables with incomplete types. */ ! if (!processing_template_decl && TREE_TYPE (var) != error_mark_node && DECL_EXTERNAL (var)) { tree inner_type = TREE_TYPE (var); ! while (TREE_CODE (inner_type) == ARRAY_TYPE) inner_type = TREE_TYPE (inner_type); inner_type = TYPE_MAIN_VARIANT (inner_type); ! if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type)) /* RTTI TD entries are created while defining the type_info. */ || (TYPE_LANG_SPECIFIC (inner_type) *************** complete_vars (tree type) *** 11165,11185 **** { tree *list = &incomplete_vars; ! my_friendly_assert (CLASS_TYPE_P (type), 20020406); ! while (*list) { if (same_type_p (type, TREE_PURPOSE (*list))) { tree var = TREE_VALUE (*list); /* Complete the type of the variable. The VAR_DECL itself will be laid out in expand_expr. */ ! complete_type (TREE_TYPE (var)); /* Remove this entry from the list. */ *list = TREE_CHAIN (*list); } else list = &TREE_CHAIN (*list); } } /* If DECL is of a type which needs a cleanup, build that cleanup --- 10883,10908 ---- { tree *list = &incomplete_vars; ! gcc_assert (CLASS_TYPE_P (type)); ! while (*list) { if (same_type_p (type, TREE_PURPOSE (*list))) { tree var = TREE_VALUE (*list); + tree type = TREE_TYPE (var); /* Complete the type of the variable. The VAR_DECL itself will be laid out in expand_expr. */ ! complete_type (type); ! cp_apply_type_quals_to_decl (cp_type_quals (type), var); /* Remove this entry from the list. */ *list = TREE_CHAIN (*list); } else list = &TREE_CHAIN (*list); } + + /* Check for pending declarations which may have abstract type. */ + complete_type_check_abstract (type); } /* If DECL is of a type which needs a cleanup, build that cleanup *************** cxx_maybe_build_cleanup (tree decl) *** 11194,11199 **** --- 10917,10924 ---- { int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR; tree rval; + bool has_vbases = (TREE_CODE (type) == RECORD_TYPE + && CLASSTYPE_VBASECLASSES (type)); if (TREE_CODE (type) == ARRAY_TYPE) rval = decl; *************** cxx_maybe_build_cleanup (tree decl) *** 11204,11220 **** } /* Optimize for space over speed here. */ ! if (! TYPE_USES_VIRTUAL_BASECLASSES (type) ! || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; rval = build_delete (TREE_TYPE (rval), rval, sfk_complete_destructor, flags, 0); - if (TYPE_USES_VIRTUAL_BASECLASSES (type) - && ! TYPE_HAS_DESTRUCTOR (type)) - rval = build_compound_expr (rval, build_vbase_delete (type, decl)); - return rval; } return NULL_TREE; --- 10929,10940 ---- } /* Optimize for space over speed here. */ ! if (!has_vbases || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; rval = build_delete (TREE_TYPE (rval), rval, sfk_complete_destructor, flags, 0); return rval; } return NULL_TREE; *************** cxx_maybe_build_cleanup (tree decl) *** 11225,11234 **** void finish_stmt (void) { - /* Always assume this statement was not an expression statement. If - it actually was an expression statement, its our callers - responsibility to fix this up. */ - last_expr_type = NULL_TREE; } /* DECL was originally constructed as a non-static member function, --- 10945,10950 ---- *************** revert_static_member_fn (tree decl) *** 11243,11250 **** if (cp_type_quals (TREE_TYPE (TREE_VALUE (args))) != TYPE_UNQUALIFIED) ! error ("static member function `%#D' declared with type qualifiers", ! decl); args = TREE_CHAIN (args); tmp = build_function_type (TREE_TYPE (function), args); --- 10959,10965 ---- if (cp_type_quals (TREE_TYPE (TREE_VALUE (args))) != TYPE_UNQUALIFIED) ! error ("static member function %q#D declared with type qualifiers", decl); args = TREE_CHAIN (args); tmp = build_function_type (TREE_TYPE (function), args); *************** revert_static_member_fn (tree decl) *** 11263,11270 **** void cxx_push_function_context (struct function * f) { ! struct language_function *p ! = ggc_alloc_cleared (sizeof (struct language_function)); f->language = p; /* Whenever we start a new function, we destroy temporaries in the --- 10978,10984 ---- void cxx_push_function_context (struct function * f) { ! struct language_function *p = GGC_CNEW (struct language_function); f->language = p; /* Whenever we start a new function, we destroy temporaries in the *************** cxx_push_function_context (struct functi *** 11281,11294 **** now, restore saved state. */ *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn); - /* If we decided that we didn't want to inline this function, - make sure the back-end knows that. */ - if (!current_function_cannot_inline) - current_function_cannot_inline = cp_function_chain->cannot_inline; - /* We don't need the saved data anymore. Unless this is an inline function; we need the named return value info for ! cp_copy_res_decl_for_inlining. */ if (! DECL_INLINE (fn)) DECL_SAVED_FUNCTION_DATA (fn) = NULL; } --- 10995,11003 ---- now, restore saved state. */ *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn); /* We don't need the saved data anymore. Unless this is an inline function; we need the named return value info for ! declare_return_variable. */ if (! DECL_INLINE (fn)) DECL_SAVED_FUNCTION_DATA (fn) = NULL; } *************** cp_tree_node_structure (union lang_tree_ *** 11316,11324 **** 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 BASELINK: return TS_CP_BASELINK; - case WRAPPER: return TS_CP_WRAPPER; default: return TS_CP_GENERIC; } } --- 11025,11033 ---- case IDENTIFIER_NODE: return TS_CP_IDENTIFIER; case OVERLOAD: return TS_CP_OVERLOAD; case TEMPLATE_PARM_INDEX: return TS_CP_TPI; + case TINST_LEVEL: return TS_CP_TINST_LEVEL; case PTRMEM_CST: return TS_CP_PTRMEM; case BASELINK: return TS_CP_BASELINK; default: return TS_CP_GENERIC; } } *************** tree *** 11328,11343 **** build_void_list_node (void) { tree t = build_tree_list (NULL_TREE, void_type_node); - TREE_PARMLIST (t) = 1; return t; } ! static int cp_missing_noreturn_ok_p (tree decl) { /* A missing noreturn is ok for the `main' function. */ return DECL_MAIN_P (decl); } #include "gt-cp-decl.h" - #include "gtype-cp.h" --- 11037,11085 ---- build_void_list_node (void) { tree t = build_tree_list (NULL_TREE, void_type_node); return t; } ! bool cp_missing_noreturn_ok_p (tree decl) { /* A missing noreturn is ok for the `main' function. */ return DECL_MAIN_P (decl); } + /* Return the COMDAT group into which DECL should be placed. */ + + const char * + cxx_comdat_group (tree decl) + { + tree name; + + /* Virtual tables, construction virtual tables, and virtual table + tables all go in a single COMDAT group, named after the primary + virtual table. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl)) + name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl))); + /* For all other DECLs, the COMDAT group is the mangled name of the + declaration itself. */ + else + { + while (DECL_THUNK_P (decl)) + { + /* If TARGET_USE_LOCAL_THUNK_ALIAS_P, use_thunk puts the thunk + into the same section as the target function. In that case + we must return target's name. */ + tree target = THUNK_TARGET (decl); + if (TARGET_USE_LOCAL_THUNK_ALIAS_P (target) + && DECL_SECTION_NAME (target) != NULL + && DECL_ONE_ONLY (target)) + decl = target; + else + break; + } + name = DECL_ASSEMBLER_NAME (decl); + } + + return IDENTIFIER_POINTER (name); + } + #include "gt-cp-decl.h" diff -Nrcpad gcc-3.4.3/gcc/cp/decl.h gcc-4.0.0/gcc/cp/decl.h *** gcc-3.4.3/gcc/cp/decl.h Sat Mar 20 00:13:12 2004 --- gcc-4.0.0/gcc/cp/decl.h Tue Feb 8 14:46:52 2005 *************** *** 1,5 **** /* Variables and structures for declaration processing. ! Copyright (C) 1993, 2000, 2002 Free Software Foundation, Inc. This file is part of GCC. --- 1,5 ---- /* Variables and structures for declaration processing. ! Copyright (C) 1993, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. *************** enum decl_context *** 31,39 **** }; /* We need this in here to get the decl_context definition. */ ! extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*); ! ! #ifdef DEBUG_CP_BINDING_LEVELS ! /* Purely for debugging purposes. */ ! extern int debug_bindings_indentation; ! #endif --- 31,36 ---- }; /* We need this in here to get the decl_context definition. */ ! extern tree grokdeclarator (const cp_declarator *, ! const cp_decl_specifier_seq *, ! enum decl_context, int, tree*); diff -Nrcpad gcc-3.4.3/gcc/cp/decl2.c gcc-4.0.0/gcc/cp/decl2.c *** gcc-3.4.3/gcc/cp/decl2.c Mon Oct 11 14:42:36 2004 --- gcc-4.0.0/gcc/cp/decl2.c Tue Apr 5 15:38:09 2005 *************** *** 1,6 **** /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 38,44 **** #include "flags.h" #include "cp-tree.h" #include "decl.h" - #include "lex.h" #include "output.h" #include "except.h" #include "toplev.h" --- 38,43 ---- *************** Boston, MA 02111-1307, USA. */ *** 46,53 **** --- 45,55 ---- #include "cpplib.h" #include "target.h" #include "c-common.h" + #include "tree-mudflap.h" #include "cgraph.h" #include "tree-inline.h" + #include "c-pragma.h" + extern cpp_reader *parse_in; /* This structure contains information about the initializations *************** typedef struct priority_info_s { *** 62,70 **** } *priority_info; static void mark_vtable_entries (tree); - static void grok_function_init (tree, tree); static bool maybe_emit_vtables (tree); - static tree build_anon_union_vars (tree); static bool acceptable_java_type (tree); static tree start_objects (int, int); static void finish_objects (int, int, tree); --- 64,70 ---- *************** tree static_dtors; *** 117,148 **** TYPE_UNQUALIFIED will be an extension. */ int ! grok_method_quals (tree ctype, tree function, tree quals) { tree fntype = TREE_TYPE (function); tree raises = TYPE_RAISES_EXCEPTIONS (fntype); int type_quals = TYPE_UNQUALIFIED; - int dup_quals = TYPE_UNQUALIFIED; int this_quals = TYPE_UNQUALIFIED; ! do ! { ! int tq = cp_type_qual_from_rid (TREE_VALUE (quals)); ! ! if ((type_quals | this_quals) & tq) ! dup_quals |= tq; ! else if (tq & TYPE_QUAL_RESTRICT) ! this_quals |= tq; ! else ! type_quals |= tq; ! quals = TREE_CHAIN (quals); ! } ! while (quals); ! ! if (dup_quals != TYPE_UNQUALIFIED) ! error ("duplicate type qualifiers in %s declaration", ! TREE_CODE (function) == FUNCTION_DECL ! ? "member function" : "type"); ctype = cp_build_qualified_type (ctype, type_quals); fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), --- 117,131 ---- TYPE_UNQUALIFIED will be an extension. */ int ! grok_method_quals (tree ctype, tree function, cp_cv_quals quals) { tree fntype = TREE_TYPE (function); tree raises = TYPE_RAISES_EXCEPTIONS (fntype); int type_quals = TYPE_UNQUALIFIED; int this_quals = TYPE_UNQUALIFIED; ! type_quals = quals & ~TYPE_QUAL_RESTRICT; ! this_quals = quals & TYPE_QUAL_RESTRICT; ctype = cp_build_qualified_type (ctype, type_quals); fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), *************** grok_method_quals (tree ctype, tree func *** 156,182 **** return this_quals; } - /* A subroutine of the parser, to handle a component list. */ - - void - grok_x_components (tree specs) - { - tree t; - - specs = strip_attrs (specs); - - check_tag_decl (specs); - t = groktypename (build_tree_list (specs, NULL_TREE)); - - /* The only case where we need to do anything additional here is an - anonymous union field, e.g.: `struct S { union { int i; }; };'. */ - if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t)) - return; - - fixup_anonymous_aggr (t); - finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); - } - /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE appropriately. */ --- 139,144 ---- *************** cp_build_parm_decl (tree name, tree type *** 194,200 **** /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the indicated NAME. */ ! tree build_artificial_parm (tree name, tree type) { tree parm = cp_build_parm_decl (name, type); --- 156,162 ---- /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the indicated NAME. */ ! static tree build_artificial_parm (tree name, tree type) { tree parm = cp_build_parm_decl (name, type); *************** maybe_retrofit_in_chrg (tree fn) *** 235,241 **** /* We don't need an in-charge parameter for constructors that don't have virtual bases. */ if (DECL_CONSTRUCTOR_P (fn) ! && !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) return; arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); --- 197,203 ---- /* We don't need an in-charge parameter for constructors that don't have virtual bases. */ if (DECL_CONSTRUCTOR_P (fn) ! && !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) return; arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); *************** maybe_retrofit_in_chrg (tree fn) *** 246,252 **** /* If this is a subobject constructor or destructor, our caller will pass us a pointer to our VTT. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) { parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type); --- 208,214 ---- /* If this is a subobject constructor or destructor, our caller will pass us a pointer to our VTT. */ ! if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) { parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type); *************** maybe_retrofit_in_chrg (tree fn) *** 302,311 **** QUALS are the qualifiers for the this pointer. */ void ! grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals) { tree fn_name = DECL_NAME (function); ! int this_quals = TYPE_UNQUALIFIED; /* Even within an `extern "C"' block, members get C++ linkage. See [dcl.link] for details. */ --- 264,274 ---- QUALS are the qualifiers for the this pointer. */ void ! grokclassfn (tree ctype, tree function, enum overload_flags flags, ! cp_cv_quals quals) { tree fn_name = DECL_NAME (function); ! cp_cv_quals this_quals = TYPE_UNQUALIFIED; /* Even within an `extern "C"' block, members get C++ linkage. See [dcl.link] for details. */ *************** grokclassfn (tree ctype, tree function, *** 335,341 **** this_quals |= TYPE_QUAL_CONST; qual_type = cp_build_qualified_type (type, this_quals); parm = build_artificial_parm (this_identifier, qual_type); ! c_apply_type_quals_to_decl (this_quals, parm); TREE_CHAIN (parm) = DECL_ARGUMENTS (function); DECL_ARGUMENTS (function) = parm; } --- 298,304 ---- this_quals |= TYPE_QUAL_CONST; qual_type = cp_build_qualified_type (type, this_quals); parm = build_artificial_parm (this_identifier, qual_type); ! cp_apply_type_quals_to_decl (this_quals, parm); TREE_CHAIN (parm) = DECL_ARGUMENTS (function); DECL_ARGUMENTS (function) = parm; } *************** grok_array_decl (tree array_expr, tree i *** 367,379 **** { if (type_dependent_expression_p (array_expr) || type_dependent_expression_p (index_exp)) ! return build_min_nt (ARRAY_REF, array_expr, index_exp); array_expr = build_non_dependent_expr (array_expr); index_exp = build_non_dependent_expr (index_exp); } type = TREE_TYPE (array_expr); ! my_friendly_assert (type, 20030626); type = non_reference (type); /* If they have an `operator[]', use that. */ --- 330,343 ---- { if (type_dependent_expression_p (array_expr) || type_dependent_expression_p (index_exp)) ! return build_min_nt (ARRAY_REF, array_expr, index_exp, ! NULL_TREE, NULL_TREE); array_expr = build_non_dependent_expr (array_expr); index_exp = build_non_dependent_expr (index_exp); } type = TREE_TYPE (array_expr); ! gcc_assert (type); type = non_reference (type); /* If they have an `operator[]', use that. */ *************** grok_array_decl (tree array_expr, tree i *** 413,420 **** array_expr = p2, index_exp = i1; else { ! error ("invalid types `%T[%T]' for array subscript", ! type, TREE_TYPE (index_exp)); return error_mark_node; } --- 377,384 ---- array_expr = p2, index_exp = i1; else { ! error ("invalid types %<%T[%T]%> for array subscript", ! type, TREE_TYPE (index_exp)); return error_mark_node; } *************** grok_array_decl (tree array_expr, tree i *** 424,431 **** expr = build_array_ref (array_expr, index_exp); } if (processing_template_decl && expr != error_mark_node) ! return build_min_non_dep (ARRAY_REF, expr, ! orig_array_expr, orig_index_exp); return expr; } --- 388,395 ---- expr = build_array_ref (array_expr, index_exp); } if (processing_template_decl && expr != error_mark_node) ! return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp, ! NULL_TREE, NULL_TREE); return expr; } *************** delete_sanity (tree exp, tree size, bool *** 453,471 **** return t; } - exp = convert_from_reference (exp); - /* An array can't have been allocated by new, so complain. */ if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) ! warning ("deleting array `%#D'", exp); t = build_expr_type_conversion (WANT_POINTER, exp, true); if (t == NULL_TREE || t == error_mark_node) { ! error ("type `%#T' argument given to `delete', expected pointer", ! TREE_TYPE (exp)); return error_mark_node; } --- 417,433 ---- return t; } /* An array can't have been allocated by new, so complain. */ if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) ! warning ("deleting array %q#D", exp); t = build_expr_type_conversion (WANT_POINTER, exp, true); if (t == NULL_TREE || t == error_mark_node) { ! error ("type %q#T argument given to %, expected pointer", ! TREE_TYPE (exp)); return error_mark_node; } *************** delete_sanity (tree exp, tree size, bool *** 476,489 **** /* You can't delete functions. */ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) { ! error ("cannot delete a function. Only pointer-to-objects are valid arguments to `delete'"); return error_mark_node; } /* Deleting ptr to void is undefined behavior [expr.delete/3]. */ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) { ! warning ("deleting `%T' is undefined", type); doing_vec = 0; } --- 438,452 ---- /* You can't delete functions. */ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) { ! error ("cannot delete a function. Only pointer-to-objects are " ! "valid arguments to %"); return error_mark_node; } /* Deleting ptr to void is undefined behavior [expr.delete/3]. */ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) { ! warning ("deleting %qT is undefined", type); doing_vec = 0; } *************** check_member_template (tree tmpl) *** 508,514 **** { tree decl; ! my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); decl = DECL_TEMPLATE_RESULT (tmpl); if (TREE_CODE (decl) == FUNCTION_DECL --- 471,477 ---- { tree decl; ! gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); decl = DECL_TEMPLATE_RESULT (tmpl); if (TREE_CODE (decl) == FUNCTION_DECL *************** check_member_template (tree tmpl) *** 519,526 **** /* 14.5.2.2 [temp.mem] A local class shall not have member templates. */ ! error ("invalid declaration of member template `%#D' in local class", ! decl); if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) { --- 482,489 ---- /* 14.5.2.2 [temp.mem] A local class shall not have member templates. */ ! error ("invalid declaration of member template %q#D in local class", ! decl); if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) { *************** check_member_template (tree tmpl) *** 528,534 **** A member function template shall not be virtual. */ error ! ("invalid use of `virtual' in template declaration of `%#D'", decl); DECL_VIRTUAL_P (decl) = 0; } --- 491,497 ---- A member function template shall not be virtual. */ error ! ("invalid use of % in template declaration of %q#D", decl); DECL_VIRTUAL_P (decl) = 0; } *************** check_member_template (tree tmpl) *** 538,544 **** DECL_IGNORED_P (tmpl) = 1; } else ! error ("template declaration of `%#D'", decl); } /* Return true iff TYPE is a valid Java parameter or return type. */ --- 501,507 ---- DECL_IGNORED_P (tmpl) = 1; } else ! error ("template declaration of %q#D", decl); } /* Return true iff TYPE is a valid Java parameter or return type. */ *************** check_java_method (tree method) *** 587,594 **** if (!acceptable_java_type (ret_type)) { ! error ("Java method '%D' has non-Java return type `%T'", ! method, ret_type); jerr = true; } --- 550,557 ---- if (!acceptable_java_type (ret_type)) { ! error ("Java method %qD has non-Java return type %qT", ! method, ret_type); jerr = true; } *************** check_java_method (tree method) *** 603,610 **** tree type = TREE_VALUE (arg_types); if (!acceptable_java_type (type)) { ! error ("Java method '%D' has non-Java parameter type `%T'", ! method, type); jerr = true; } } --- 566,573 ---- tree type = TREE_VALUE (arg_types); if (!acceptable_java_type (type)) { ! error ("Java method %qD has non-Java parameter type %qT", ! method, type); jerr = true; } } *************** check_java_method (tree method) *** 613,632 **** /* Sanity check: report error if this function FUNCTION is not really a member of the class (CTYPE) it is supposed to belong to. ! CNAME is the same here as it is for grokclassfn above. ! TEMPLATE_HEADER_P is true when this declaration comes with a ! template header. */ tree ! check_classfn (tree ctype, tree function, bool template_header_p) { int ix; ! int is_template; if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL && DECL_TEMPLATE_SPECIALIZATION (function)) ! && is_member_template (DECL_TI_TEMPLATE (function))) /* Since this is a specialization of a member template, we're not going to find the declaration in the class. For example, in: --- 576,599 ---- /* Sanity check: report error if this function FUNCTION is not really a member of the class (CTYPE) it is supposed to belong to. ! TEMPLATE_PARMS is used to specify the template parameters of a member ! template passed as FUNCTION_DECL. If the member template is passed as a ! TEMPLATE_DECL, it can be NULL since the parameters can be extracted ! from the declaration. If the function is not a function template, it ! must be NULL. ! It returns the original declaration for the function, or NULL_TREE ! if no declaration was found (and an error was emitted). */ tree ! check_classfn (tree ctype, tree function, tree template_parms) { int ix; ! bool is_template; if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL && DECL_TEMPLATE_SPECIALIZATION (function)) ! && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (function))) /* Since this is a specialization of a member template, we're not going to find the declaration in the class. For example, in: *************** check_classfn (tree ctype, tree function *** 639,663 **** find the method, but we don't complain. */ return NULL_TREE; ! /* OK, is this a definition of a member template? */ ! is_template = (TREE_CODE (function) == TEMPLATE_DECL ! || template_header_p); ! 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) { ! tree methods = CLASSTYPE_METHOD_VEC (ctype); tree fndecls, fndecl = 0; bool is_conv_op; ! bool pop_p; const char *format = NULL; ! pop_p = push_scope (ctype); ! for (fndecls = TREE_VEC_ELT (methods, ix); fndecls; fndecls = OVL_NEXT (fndecls)) { tree p1, p2; --- 606,635 ---- find the method, but we don't complain. */ return NULL_TREE; ! /* Basic sanity check: for a template function, the template parameters ! either were not passed, or they are the same of DECL_TEMPLATE_PARMS. */ ! if (TREE_CODE (function) == TEMPLATE_DECL) ! { ! gcc_assert (!template_parms ! || comp_template_parms (template_parms, ! DECL_TEMPLATE_PARMS (function))); ! template_parms = DECL_TEMPLATE_PARMS (function); ! } ! /* OK, is this a definition of a member template? */ ! is_template = (template_parms != NULL_TREE); + ix = class_method_index_for_fn (complete_type (ctype), function); if (ix >= 0) { ! VEC(tree) *methods = CLASSTYPE_METHOD_VEC (ctype); tree fndecls, fndecl = 0; bool is_conv_op; ! tree pushed_scope; const char *format = NULL; ! pushed_scope = push_scope (ctype); ! for (fndecls = VEC_index (tree, methods, ix); fndecls; fndecls = OVL_NEXT (fndecls)) { tree p1, p2; *************** check_classfn (tree ctype, tree function *** 685,690 **** --- 657,665 ---- if (same_type_p (TREE_TYPE (TREE_TYPE (function)), TREE_TYPE (TREE_TYPE (fndecl))) && compparms (p1, p2) + && (!is_template + || comp_template_parms (template_parms, + DECL_TEMPLATE_PARMS (fndecl))) && (DECL_TEMPLATE_SPECIALIZATION (function) == DECL_TEMPLATE_SPECIALIZATION (fndecl)) && (!DECL_TEMPLATE_SPECIALIZATION (function) *************** check_classfn (tree ctype, tree function *** 692,708 **** == DECL_TI_TEMPLATE (fndecl)))) break; } ! if (pop_p) ! pop_scope (ctype); if (fndecls) return OVL_CURRENT (fndecls); ! 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); --- 667,683 ---- == DECL_TI_TEMPLATE (fndecl)))) break; } ! if (pushed_scope) ! pop_scope (pushed_scope); if (fndecls) return OVL_CURRENT (fndecls); ! error ("prototype for %q#D does not match any in class %qT", function, ctype); is_conv_op = DECL_CONV_FN_P (fndecl); if (is_conv_op) ix = CLASSTYPE_FIRST_CONVERSION_SLOT; ! fndecls = VEC_index (tree, methods, ix); while (fndecls) { fndecl = OVL_CURRENT (fndecls); *************** check_classfn (tree ctype, tree function *** 710,719 **** if (!fndecls && is_conv_op) { ! if (TREE_VEC_LENGTH (methods) > ix) { ! ix++; ! fndecls = TREE_VEC_ELT (methods, ix); if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls))) { fndecls = NULL_TREE; --- 685,693 ---- if (!fndecls && is_conv_op) { ! if (VEC_length (tree, methods) > (size_t) ++ix) { ! fndecls = VEC_index (tree, methods, ix); if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls))) { fndecls = NULL_TREE; *************** check_classfn (tree ctype, tree function *** 735,741 **** else if (!COMPLETE_TYPE_P (ctype)) cxx_incomplete_type_error (function, ctype); else ! 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 --- 709,715 ---- else if (!COMPLETE_TYPE_P (ctype)) cxx_incomplete_type_error (function, ctype); else ! error ("no %q#D member function declared in class %qT", function, ctype); /* If we did not find the method in the class, add it to avoid *************** check_classfn (tree ctype, tree function *** 743,752 **** case we'll only confuse ourselves when the function is declared properly within the class. */ if (COMPLETE_TYPE_P (ctype)) ! add_method (ctype, function, /*error_p=*/1); return NULL_TREE; } /* We have just processed the DECL, which is a static data member. Its initializer, if present, is INIT. The ASMSPEC_TREE, if present, is the assembly-language name for the data member. --- 717,753 ---- case we'll only confuse ourselves when the function is declared properly within the class. */ if (COMPLETE_TYPE_P (ctype)) ! add_method (ctype, function); return NULL_TREE; } + /* DECL is a function with vague linkage. Remember it so that at the + end of the translation unit we can decide whether or not to emit + it. */ + + void + note_vague_linkage_fn (tree decl) + { + if (!DECL_DEFERRED_FN (decl)) + { + DECL_DEFERRED_FN (decl) = 1; + DECL_DEFER_OUTPUT (decl) = 1; + if (!deferred_fns) + VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns"); + VARRAY_PUSH_TREE (deferred_fns, decl); + } + } + + /* Like note_vague_linkage_fn but for variables. */ + + static void + note_vague_linkage_var (tree var) + { + if (!pending_statics) + VARRAY_TREE_INIT (pending_statics, 32, "pending_statics"); + VARRAY_PUSH_TREE (pending_statics, var); + } + /* We have just processed the DECL, which is a static data member. Its initializer, if present, is INIT. The ASMSPEC_TREE, if present, is the assembly-language name for the data member. *************** void *** 756,762 **** finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree, int flags) { ! my_friendly_assert (TREE_PUBLIC (decl), 0); DECL_CONTEXT (decl) = current_class_type; --- 757,763 ---- finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree, int flags) { ! gcc_assert (TREE_PUBLIC (decl)); DECL_CONTEXT (decl) = current_class_type; *************** finish_static_data_member_decl (tree dec *** 768,781 **** DECL_INITIAL (decl) = error_mark_node; if (! processing_template_decl) ! { ! if (!pending_statics) ! VARRAY_TREE_INIT (pending_statics, 32, "pending_statics"); ! VARRAY_PUSH_TREE (pending_statics, decl); ! } if (LOCAL_CLASS_P (current_class_type)) ! pedwarn ("local class `%#T' shall not have static data member `%#D'", current_class_type, decl); /* Static consts need not be initialized in the class definition. */ --- 769,778 ---- DECL_INITIAL (decl) = error_mark_node; if (! processing_template_decl) ! note_vague_linkage_var (decl); if (LOCAL_CLASS_P (current_class_type)) ! pedwarn ("local class %q#T shall not have static data member %q#D", current_class_type, decl); /* Static consts need not be initialized in the class definition. */ *************** finish_static_data_member_decl (tree dec *** 820,843 **** CHANGES TO CODE IN `start_method'. */ tree ! grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree, tree attrlist) { tree value; const char *asmspec = 0; int flags = LOOKUP_ONLYCONVERTING; ! if (declspecs == NULL_TREE ! && TREE_CODE (declarator) == SCOPE_REF ! && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE) ! { ! /* Access declaration */ ! if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0)))) ! ; ! else if (TREE_COMPLEXITY (declarator) == current_class_depth) ! pop_nested_class (); ! return do_class_using_decl (declarator); ! } if (init && TREE_CODE (init) == TREE_LIST --- 817,838 ---- CHANGES TO CODE IN `start_method'. */ tree ! grokfield (const cp_declarator *declarator, ! cp_decl_specifier_seq *declspecs, ! tree init, tree asmspec_tree, tree attrlist) { tree value; const char *asmspec = 0; int flags = LOOKUP_ONLYCONVERTING; ! if (!declspecs->any_specifiers_p ! && declarator->kind == cdk_id ! && declarator->u.id.qualifying_scope ! && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE) ! /* Access declaration */ ! return do_class_using_decl (declarator->u.id.qualifying_scope, ! declarator->u.id.unqualified_name); if (init && TREE_CODE (init) == TREE_LIST *************** grokfield (tree declarator, tree declspe *** 852,858 **** if (TREE_CODE (value) == TYPE_DECL && init) { ! error ("typedef `%D' is initialized (use __typeof__ instead)", value); init = NULL_TREE; } --- 847,853 ---- if (TREE_CODE (value) == TYPE_DECL && init) { ! error ("typedef %qD is initialized (use __typeof__ instead)", value); init = NULL_TREE; } *************** grokfield (tree declarator, tree declspe *** 869,876 **** if (DECL_NAME (value) != NULL_TREE && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) ! error ("member `%D' conflicts with virtual function table field name", ! value); /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) --- 864,871 ---- if (DECL_NAME (value) != NULL_TREE && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) ! error ("member %qD conflicts with virtual function table field name", ! value); /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) *************** grokfield (tree declarator, tree declspe *** 881,893 **** if (processing_template_decl) value = push_template_decl (value); return value; } if (DECL_IN_AGGR_P (value)) { ! error ("`%D' is already defined in `%T'", value, ! DECL_CONTEXT (value)); return void_type_node; } --- 876,899 ---- if (processing_template_decl) value = push_template_decl (value); + if (attrlist) + { + /* Avoid storing attributes in template parameters: + tsubst is not ready to handle them. */ + tree type = TREE_TYPE (value); + if (TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + sorry ("applying attributes to template parameters is not implemented"); + else + cplus_decl_attributes (&value, attrlist, 0); + } + return value; } if (DECL_IN_AGGR_P (value)) { ! error ("%qD is already defined in %qT", value, DECL_CONTEXT (value)); return void_type_node; } *************** grokfield (tree declarator, tree declspe *** 898,905 **** { if (TREE_CODE (value) == FUNCTION_DECL) { ! grok_function_init (value, init); ! init = NULL_TREE; } else if (pedantic && TREE_CODE (value) != VAR_DECL) /* Already complained in grokdeclarator. */ --- 904,914 ---- { if (TREE_CODE (value) == FUNCTION_DECL) { ! /* Initializers for functions are rejected early in the parser. ! If we get here, it must be a pure specifier for a method. */ ! gcc_assert (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE); ! gcc_assert (error_operand_p (init) || integer_zerop (init)); ! DECL_PURE_VIRTUAL_P (value) = 1; } else if (pedantic && TREE_CODE (value) != VAR_DECL) /* Already complained in grokdeclarator. */ *************** grokfield (tree declarator, tree declspe *** 918,929 **** if (!processing_template_decl) { ! if (TREE_CODE (init) == CONST_DECL) ! init = DECL_INITIAL (init); ! else if (TREE_READONLY_DECL_P (init)) ! 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 && ! TREE_CONSTANT (init)) { /* We can allow references to things that are effectively --- 927,937 ---- if (!processing_template_decl) { ! if (TREE_CODE (init) == CONSTRUCTOR) init = digest_init (TREE_TYPE (value), init, (tree *)0); + else + init = integral_constant_value (init); + if (init != error_mark_node && ! TREE_CONSTANT (init)) { /* We can allow references to things that are effectively *************** grokfield (tree declarator, tree declspe *** 952,983 **** if (attrlist) cplus_decl_attributes (&value, attrlist, 0); ! if (TREE_CODE (value) == VAR_DECL) { finish_static_data_member_decl (value, init, asmspec_tree, flags); return value; ! } ! if (TREE_CODE (value) == FIELD_DECL) ! { if (asmspec) ! error ("`asm' specifiers are not permitted on non-static data members"); if (DECL_INITIAL (value) == error_mark_node) init = error_mark_node; cp_finish_decl (value, init, NULL_TREE, flags); DECL_INITIAL (value) = init; DECL_IN_AGGR_P (value) = 1; return value; ! } ! if (TREE_CODE (value) == FUNCTION_DECL) ! { if (asmspec) ! { ! /* This must override the asm specifier which was placed ! by grokclassfn. Lay this out fresh. */ ! SET_DECL_RTL (value, NULL_RTX); ! change_decl_assembler_name (value, get_identifier (asmspec)); ! } if (!DECL_FRIEND_P (value)) grok_special_member_properties (value); --- 960,985 ---- if (attrlist) cplus_decl_attributes (&value, attrlist, 0); ! switch (TREE_CODE (value)) { + case VAR_DECL: finish_static_data_member_decl (value, init, asmspec_tree, flags); return value; ! ! case FIELD_DECL: if (asmspec) ! error ("% specifiers are not permitted on non-static data members"); if (DECL_INITIAL (value) == error_mark_node) init = error_mark_node; cp_finish_decl (value, init, NULL_TREE, flags); DECL_INITIAL (value) = init; DECL_IN_AGGR_P (value) = 1; return value; ! ! case FUNCTION_DECL: if (asmspec) ! set_user_assembler_name (value, asmspec); if (!DECL_FRIEND_P (value)) grok_special_member_properties (value); *************** grokfield (tree declarator, tree declspe *** 989,997 **** DECL_IN_AGGR_P (value) = 1; return value; } - abort (); - /* NOTREACHED */ return NULL_TREE; } --- 991,1000 ---- DECL_IN_AGGR_P (value) = 1; return value; + + default: + gcc_unreachable (); } return NULL_TREE; } *************** grokfield (tree declarator, tree declspe *** 999,1005 **** WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */ tree ! grokbitfield (tree declarator, tree declspecs, tree width) { tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL); --- 1002,1009 ---- WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */ tree ! grokbitfield (const cp_declarator *declarator, ! cp_decl_specifier_seq *declspecs, tree width) { tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL); *************** grokbitfield (tree declarator, tree decl *** 1011,1017 **** if (TREE_CODE (value) == TYPE_DECL) { ! error ("cannot declare `%D' to be a bit-field type", value); return NULL_TREE; } --- 1015,1021 ---- if (TREE_CODE (value) == TYPE_DECL) { ! error ("cannot declare %qD to be a bit-field type", value); return NULL_TREE; } *************** grokbitfield (tree declarator, tree decl *** 1021,1041 **** check here. */ if (TREE_CODE (value) == FUNCTION_DECL) { ! error ("cannot declare bit-field `%D' with function type", DECL_NAME (value)); return NULL_TREE; } if (DECL_IN_AGGR_P (value)) { ! error ("`%D' is already defined in the class %T", value, ! DECL_CONTEXT (value)); return void_type_node; } if (TREE_STATIC (value)) { ! error ("static member `%D' cannot be a bit-field", value); return NULL_TREE; } cp_finish_decl (value, NULL_TREE, NULL_TREE, 0); --- 1025,1045 ---- check here. */ if (TREE_CODE (value) == FUNCTION_DECL) { ! error ("cannot declare bit-field %qD with function type", DECL_NAME (value)); return NULL_TREE; } if (DECL_IN_AGGR_P (value)) { ! error ("%qD is already defined in the class %qT", value, ! DECL_CONTEXT (value)); return void_type_node; } if (TREE_STATIC (value)) { ! error ("static member %qD cannot be a bit-field", value); return NULL_TREE; } cp_finish_decl (value, NULL_TREE, NULL_TREE, 0); *************** grokbitfield (tree declarator, tree decl *** 1051,1105 **** return value; } - /* When a function is declared with an initializer, - do the right thing. Currently, there are two possibilities: - - class B - { - public: - // initialization possibility #1. - virtual void f () = 0; - int g (); - }; - - class D1 : B - { - public: - int d1; - // error, no f (); - }; - - class D2 : B - { - public: - int d2; - void f (); - }; - - class D3 : B - { - public: - int d3; - // initialization possibility #2 - void f () = B::f; - }; - - */ - - static void - grok_function_init (tree decl, tree init) - { - /* An initializer for a function tells how this function should - be inherited. */ - tree type = TREE_TYPE (decl); - - if (TREE_CODE (type) == FUNCTION_TYPE) - error ("initializer specified for non-member function `%D'", decl); - else if (integer_zerop (init)) - DECL_PURE_VIRTUAL_P (decl) = 1; - else - error ("invalid initializer for virtual method `%D'", decl); - } void cplus_decl_attributes (tree *decl, tree attributes, int flags) --- 1055,1060 ---- *************** cplus_decl_attributes (tree *decl, tree *** 1116,1144 **** SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl)); } ! /* Defer the compilation of the FN until the end of compilation. */ ! ! void ! defer_fn (tree fn) ! { ! if (DECL_DEFERRED_FN (fn)) ! return; ! DECL_DEFERRED_FN (fn) = 1; ! DECL_DEFER_OUTPUT (fn) = 1; ! if (!deferred_fns) ! VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns"); ! ! VARRAY_PUSH_TREE (deferred_fns, fn); ! } ! ! /* Walks through the namespace- or function-scope anonymous union OBJECT, ! building appropriate ALIAS_DECLs. Returns one of the fields for use in ! the mangled name. */ static tree ! build_anon_union_vars (tree object) { - tree type = TREE_TYPE (object); tree main_decl = NULL_TREE; tree field; --- 1071,1083 ---- SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl)); } ! /* Walks through the namespace- or function-scope anonymous union ! OBJECT, with the indicated TYPE, building appropriate ALIAS_DECLs. ! Returns one of the fields for use in the mangled name. */ static tree ! build_anon_union_vars (tree type, tree object) { tree main_decl = NULL_TREE; tree field; *************** build_anon_union_vars (tree object) *** 1158,1176 **** continue; if (TREE_CODE (field) != FIELD_DECL) { ! cp_pedwarn_at ("\ ! `%#D' invalid; an anonymous union can only have non-static data members", field); continue; } if (TREE_PRIVATE (field)) ! cp_pedwarn_at ("private member `%#D' in anonymous union", field); else if (TREE_PROTECTED (field)) ! cp_pedwarn_at ("protected member `%#D' in anonymous union", field); if (processing_template_decl) ! ref = build_min_nt (COMPONENT_REF, object, DECL_NAME (field)); else ref = build_class_member_access_expr (object, field, NULL_TREE, false); --- 1097,1116 ---- continue; if (TREE_CODE (field) != FIELD_DECL) { ! cp_pedwarn_at ("%q#D invalid; an anonymous union can only " ! "have non-static data members", field); continue; } if (TREE_PRIVATE (field)) ! cp_pedwarn_at ("private member %q#D in anonymous union", field); else if (TREE_PROTECTED (field)) ! cp_pedwarn_at ("protected member %q#D in anonymous union", field); if (processing_template_decl) ! ref = build_min_nt (COMPONENT_REF, object, ! DECL_NAME (field), NULL_TREE); else ref = build_class_member_access_expr (object, field, NULL_TREE, false); *************** build_anon_union_vars (tree object) *** 1185,1191 **** decl = pushdecl (decl); } else if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) ! decl = build_anon_union_vars (ref); else decl = 0; --- 1125,1131 ---- decl = pushdecl (decl); } else if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) ! decl = build_anon_union_vars (TREE_TYPE (field), ref); else decl = 0; *************** finish_anon_union (tree anon_union_decl) *** 1225,1231 **** return; } ! main_decl = build_anon_union_vars (anon_union_decl); if (main_decl == NULL_TREE) { warning ("anonymous union with no members"); --- 1165,1171 ---- return; } ! main_decl = build_anon_union_vars (type, anon_union_decl); if (main_decl == NULL_TREE) { warning ("anonymous union with no members"); *************** finish_anon_union (tree anon_union_decl) *** 1243,1251 **** pushdecl (anon_union_decl); if (building_stmt_tree () && at_function_scope_p ()) ! add_decl_stmt (anon_union_decl); else if (!processing_template_decl) ! rest_of_decl_compilation (anon_union_decl, NULL, toplevel_bindings_p (), at_eof); } --- 1183,1191 ---- pushdecl (anon_union_decl); if (building_stmt_tree () && at_function_scope_p ()) ! add_decl_expr (anon_union_decl); else if (!processing_template_decl) ! rest_of_decl_compilation (anon_union_decl, toplevel_bindings_p (), at_eof); } *************** coerce_new_type (tree type) *** 1259,1268 **** int e = 0; tree args = TYPE_ARG_TYPES (type); ! my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107); if (!same_type_p (TREE_TYPE (type), ptr_type_node)) ! e = 1, error ("`operator new' must return type `%T'", ptr_type_node); if (!args || args == void_list_node || !same_type_p (TREE_VALUE (args), size_type_node)) --- 1199,1211 ---- int e = 0; tree args = TYPE_ARG_TYPES (type); ! gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); if (!same_type_p (TREE_TYPE (type), ptr_type_node)) ! { ! e = 1; ! error ("% must return type %qT", ptr_type_node); ! } if (!args || args == void_list_node || !same_type_p (TREE_VALUE (args), size_type_node)) *************** coerce_new_type (tree type) *** 1270,1276 **** e = 2; if (args && args != void_list_node) args = TREE_CHAIN (args); ! pedwarn ("`operator new' takes type `size_t' (`%T') as first parameter", size_type_node); } switch (e) { --- 1213,1220 ---- e = 2; if (args && args != void_list_node) args = TREE_CHAIN (args); ! pedwarn ("% takes type % (%qT) " ! "as first parameter", size_type_node); } switch (e) { *************** coerce_delete_type (tree type) *** 1293,1302 **** int e = 0; tree args = TYPE_ARG_TYPES (type); ! my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107); if (!same_type_p (TREE_TYPE (type), void_type_node)) ! e = 1, error ("`operator delete' must return type `%T'", void_type_node); if (!args || args == void_list_node || !same_type_p (TREE_VALUE (args), ptr_type_node)) --- 1237,1249 ---- int e = 0; tree args = TYPE_ARG_TYPES (type); ! gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); if (!same_type_p (TREE_TYPE (type), void_type_node)) ! { ! e = 1; ! error ("% must return type %qT", void_type_node); ! } if (!args || args == void_list_node || !same_type_p (TREE_VALUE (args), ptr_type_node)) *************** coerce_delete_type (tree type) *** 1304,1310 **** e = 2; if (args && args != void_list_node) args = TREE_CHAIN (args); ! error ("`operator delete' takes type `%T' as first parameter", ptr_type_node); } switch (e) { --- 1251,1258 ---- e = 2; if (args && args != void_list_node) args = TREE_CHAIN (args); ! error ("% takes type %qT as first parameter", ! ptr_type_node); } switch (e) { *************** comdat_linkage (tree decl) *** 1406,1412 **** /* For win32 we also want to put explicit instantiations in linkonce sections, so that they will be merged with implicit ! instantiations; otherwise we get duplicate symbol errors. */ void maybe_make_one_only (tree decl) --- 1354,1362 ---- /* For win32 we also want to put explicit instantiations in linkonce sections, so that they will be merged with implicit ! instantiations; otherwise we get duplicate symbol errors. ! For Darwin we do not want explicit instantiations to be ! linkonce. */ void maybe_make_one_only (tree decl) *************** maybe_make_one_only (tree decl) *** 1420,1481 **** if (! flag_weak) return; ! /* We can't set DECL_COMDAT on functions, or finish_file will think we can get away with not emitting them if they aren't used. We need to for variables so that cp_finish_decl will update their linkage, because their DECL_INITIAL may not have been set properly yet. */ ! make_decl_one_only (decl); ! ! if (TREE_CODE (decl) == VAR_DECL) ! { ! DECL_COMDAT (decl) = 1; ! /* Mark it needed so we don't forget to emit it. */ ! mark_referenced (DECL_ASSEMBLER_NAME (decl)); ! } ! } ! ! /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL, ! based on TYPE and other static flags. ! ! Note that anything public is tagged TREE_PUBLIC, whether ! it's public in this file or in another one. */ ! ! void ! import_export_vtable (tree decl, tree type, int final) ! { ! if (DECL_INTERFACE_KNOWN (decl)) ! return; ! ! if (TYPE_FOR_JAVA (type)) ! { ! TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = 1; ! DECL_INTERFACE_KNOWN (decl) = 1; ! } ! else if (CLASSTYPE_INTERFACE_KNOWN (type)) ! { ! TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type); ! DECL_INTERFACE_KNOWN (decl) = 1; ! } ! else { ! /* We can only wait to decide if we have real non-inline virtual ! functions in our class, or if we come from a template. */ ! ! int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type) ! || CLASSTYPE_KEY_METHOD (type) != NULL_TREE); ! if (final || ! found) ! { ! comdat_linkage (decl); ! DECL_EXTERNAL (decl) = 0; ! } ! else { ! TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = 1; } } } --- 1370,1391 ---- if (! flag_weak) return; ! /* We can't set DECL_COMDAT on functions, or cp_finish_file will think we can get away with not emitting them if they aren't used. We need to for variables so that cp_finish_decl will update their linkage, because their DECL_INITIAL may not have been set properly yet. */ ! if (!TARGET_WEAK_NOT_IN_ARCHIVE_TOC ! || (! DECL_EXPLICIT_INSTANTIATION (decl) ! && ! DECL_TEMPLATE_SPECIALIZATION (decl))) { ! make_decl_one_only (decl); ! if (TREE_CODE (decl) == VAR_DECL) { ! DECL_COMDAT (decl) = 1; ! /* Mark it needed so we don't forget to emit it. */ ! mark_decl_referenced (decl); } } } *************** import_export_class (tree ctype) *** 1494,1505 **** non-abstract virtual member function has been defined in this translation unit. But, we can't possibly know that until we've seen the entire translation unit. */ ! my_friendly_assert (at_eof, 20000226); if (CLASSTYPE_INTERFACE_KNOWN (ctype)) return; ! /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma interface, we will have CLASSTYPE_INTERFACE_ONLY set but not CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this heuristic because someone will supply a #pragma implementation --- 1404,1415 ---- non-abstract virtual member function has been defined in this translation unit. But, we can't possibly know that until we've seen the entire translation unit. */ ! gcc_assert (at_eof); if (CLASSTYPE_INTERFACE_KNOWN (ctype)) return; ! /* If MULTIPLE_SYMBOL_SPACES is set and we saw a #pragma interface, we will have CLASSTYPE_INTERFACE_ONLY set but not CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this heuristic because someone will supply a #pragma implementation *************** import_export_class (tree ctype) *** 1511,1538 **** import_export = -1; else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype))) import_export = 1; ! ! /* If we got -fno-implicit-templates, we import template classes that ! weren't explicitly instantiated. */ ! if (import_export == 0 ! && CLASSTYPE_IMPLICIT_INSTANTIATION (ctype) ! && ! flag_implicit_templates) ! import_export = -1; ! ! /* Base our import/export status on that of the first non-inline, ! non-pure virtual function, if any. */ ! if (import_export == 0 ! && TYPE_POLYMORPHIC_P (ctype)) { tree method = CLASSTYPE_KEY_METHOD (ctype); ! if (method) import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); } ! #ifdef MULTIPLE_SYMBOL_SPACES ! if (import_export == -1) import_export = 0; ! #endif if (import_export) { --- 1421,1456 ---- import_export = -1; else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype))) import_export = 1; ! else if (CLASSTYPE_IMPLICIT_INSTANTIATION (ctype) ! && !flag_implicit_templates) ! /* For a template class, without -fimplicit-templates, check the ! repository. If the virtual table is assigned to this ! translation unit, then export the class; otherwise, import ! it. */ ! import_export = repo_export_class_p (ctype) ? 1 : -1; ! else if (TYPE_POLYMORPHIC_P (ctype)) { + /* The ABI specifies that the virtual table and associated + information are emitted with the key method, if any. */ tree method = CLASSTYPE_KEY_METHOD (ctype); ! /* If weak symbol support is not available, then we must be ! careful not to emit the vtable when the key function is ! inline. An inline function can be defined in multiple ! translation units. If we were to emit the vtable in each ! translation unit containing a definition, we would get ! multiple definition errors at link-time. */ ! if (method && (flag_weak || ! DECL_DECLARED_INLINE_P (method))) import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); } ! /* When MULTIPLE_SYMBOL_SPACES is set, we cannot count on seeing ! a definition anywhere else. */ ! if (MULTIPLE_SYMBOL_SPACES && import_export == -1) import_export = 0; ! ! /* Allow backends the chance to overrule the decision. */ ! if (targetm.cxx.import_export_class) ! import_export = targetm.cxx.import_export_class (ctype, import_export); if (import_export) { *************** import_export_class (tree ctype) *** 1546,1555 **** static bool var_finalized_p (tree var) { ! if (flag_unit_at_a_time) ! return cgraph_varpool_node (var)->finalized; ! else ! return TREE_ASM_WRITTEN (var); } /* If necessary, write out the vtables for the dynamic class CTYPE. --- 1464,1514 ---- static bool var_finalized_p (tree var) { ! return cgraph_varpool_node (var)->finalized; ! } ! ! /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, ! must be emitted in this translation unit. Mark it as such. */ ! ! void ! mark_needed (tree decl) ! { ! /* It's possible that we no longer need to set ! TREE_SYMBOL_REFERENCED here directly, but doing so is ! harmless. */ ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1; ! mark_decl_referenced (decl); ! } ! ! /* DECL is either a FUNCTION_DECL or a VAR_DECL. This function ! returns true if a definition of this entity should be provided in ! this object file. Callers use this function to determine whether ! or not to let the back end know that a definition of DECL is ! available in this translation unit. */ ! ! bool ! decl_needed_p (tree decl) ! { ! gcc_assert (TREE_CODE (decl) == VAR_DECL ! || TREE_CODE (decl) == FUNCTION_DECL); ! /* This function should only be called at the end of the translation ! unit. We cannot be sure of whether or not something will be ! COMDAT until that point. */ ! gcc_assert (at_eof); ! ! /* All entities with external linkage that are not COMDAT should be ! emitted; they may be referred to from other object files. */ ! if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl)) ! return true; ! /* If this entity was used, let the back-end see it; it will decide ! whether or not to emit it into the object file. */ ! if (TREE_USED (decl) ! || (DECL_ASSEMBLER_NAME_SET_P (decl) ! && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) ! return true; ! /* Otherwise, DECL does not need to be emitted -- yet. A subsequent ! reference to DECL might cause it to be emitted later. */ ! return false; } /* If necessary, write out the vtables for the dynamic class CTYPE. *************** maybe_emit_vtables (tree ctype) *** 1560,1566 **** { tree vtbl; tree primary_vtbl; ! bool needed = false; /* If the vtables for this class have already been emitted there is nothing more to do. */ --- 1519,1525 ---- { tree vtbl; tree primary_vtbl; ! int needed = 0; /* If the vtables for this class have already been emitted there is nothing more to do. */ *************** maybe_emit_vtables (tree ctype) *** 1571,1586 **** if (TREE_TYPE (primary_vtbl) == void_type_node) return false; ! import_export_class (ctype); /* See if any of the vtables are needed. */ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) { ! import_export_vtable (vtbl, ctype, 1); ! 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 --- 1530,1549 ---- if (TREE_TYPE (primary_vtbl) == void_type_node) return false; ! /* On some targets, we cannot determine the key method until the end ! of the translation unit -- which is when this function is ! called. */ ! if (!targetm.cxx.key_method_may_be_inline ()) ! determine_key_method (ctype); /* See if any of the vtables are needed. */ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) { ! import_export_decl (vtbl); ! if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl)) ! needed = 1; } ! if (!needed) { /* If the references to this class' vtables are optimized away, still emit the appropriate debugging information. See *************** maybe_emit_vtables (tree ctype) *** 1590,1649 **** note_debug_info_needed (ctype); return false; } - else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) - needed = true; - /* 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)) { ! /* Write it out. */ ! import_export_vtable (vtbl, ctype, 1); mark_vtable_entries (vtbl); - /* If we know that DECL is needed, mark it as such for the varpool. */ - if (needed) - cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); - if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) { /* It had better be all done at compile-time. */ ! if (store_init_value (vtbl, DECL_INITIAL (vtbl))) ! abort (); ! } ! ! if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG) ! { ! /* Mark the VAR_DECL node representing the vtable itself as a ! "gratuitous" one, thereby forcing dwarfout.c to ignore it. ! It is rather important that such things be ignored because ! any effort to actually generate DWARF for them will run ! into trouble when/if we encounter code like: ! ! #pragma interface ! struct S { virtual void member (); }; ! ! because the artificial declaration of the vtable itself (as ! manufactured by the g++ front end) will say that the vtable ! is a static member of `S' but only *after* the debug output ! for the definition of `S' has already been output. This causes ! grief because the DWARF entry for the definition of the vtable ! will try to refer back to an earlier *declaration* of the ! vtable as a static member of `S' and there won't be one. ! We might be able to arrange to have the "vtable static member" ! attached to the member list for `S' before the debug info for ! `S' get written (which would solve the problem) but that would ! require more intrusive changes to the g++ front end. */ ! ! DECL_IGNORED_P (vtbl) = 1; } ! /* Always make vtables weak. */ ! if (flag_weak) ! comdat_linkage (vtbl); ! ! rest_of_decl_compilation (vtbl, NULL, 1, 1); /* Because we're only doing syntax-checking, we'll never end up actually marking the variable as written. */ --- 1553,1577 ---- note_debug_info_needed (ctype); return false; } /* 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)) { ! /* Mark entities references from the virtual table as used. */ mark_vtable_entries (vtbl); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) { + tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl)); + /* It had better be all done at compile-time. */ ! gcc_assert (!expr); } ! /* Write it out. */ ! DECL_EXTERNAL (vtbl) = 0; ! rest_of_decl_compilation (vtbl, 1, 1); /* Because we're only doing syntax-checking, we'll never end up actually marking the variable as written. */ *************** maybe_emit_vtables (tree ctype) *** 1658,1695 **** return true; } ! /* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an ! inline function or template instantiation at end-of-file. */ void import_export_decl (tree decl) { if (DECL_INTERFACE_KNOWN (decl)) return; ! if (DECL_TEMPLATE_INSTANTIATION (decl) ! || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) { ! DECL_NOT_REALLY_EXTERN (decl) = 1; ! if ((DECL_IMPLICIT_INSTANTIATION (decl) ! || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) ! && (flag_implicit_templates ! || (flag_implicit_inline_templates ! && TREE_CODE (decl) == FUNCTION_DECL ! && DECL_DECLARED_INLINE_P (decl)))) { ! if (!TREE_PUBLIC (decl)) ! /* Templates are allowed to have internal linkage. See ! [basic.link]. */ ! ; else ! comdat_linkage (decl); } else { ! DECL_EXTERNAL (decl) = 1; ! DECL_NOT_REALLY_EXTERN (decl) = 0; } } else if (DECL_FUNCTION_MEMBER_P (decl)) { --- 1586,1876 ---- return true; } ! /* Like c_determine_visibility, but with additional C++-specific ! behavior. */ ! ! void ! determine_visibility (tree decl) ! { ! tree class_type; ! ! /* Cloned constructors and destructors get the same visibility as ! the underlying function. That should be set up in ! maybe_clone_body. */ ! gcc_assert (!DECL_CLONED_FUNCTION_P (decl)); ! ! /* Give the common code a chance to make a determination. */ ! if (c_determine_visibility (decl)) ! return; ! ! /* If DECL is a member of a class, visibility specifiers on the ! class can influence the visibility of the DECL. */ ! if (DECL_CLASS_SCOPE_P (decl)) ! class_type = DECL_CONTEXT (decl); ! else if (TREE_CODE (decl) == VAR_DECL ! && DECL_TINFO_P (decl) ! && CLASS_TYPE_P (TREE_TYPE (DECL_NAME (decl)))) ! class_type = TREE_TYPE (DECL_NAME (decl)); ! else ! { ! /* Virtual tables have DECL_CONTEXT set to their associated class, ! so they are automatically handled above. */ ! gcc_assert (TREE_CODE (decl) != VAR_DECL ! || !DECL_VTABLE_OR_VTT_P (decl)); ! /* Entities not associated with any class just get the ! visibility specified by their attributes. */ ! return; ! } ! ! /* By default, static data members and function members receive ! the visibility of their containing class. */ ! if (class_type) ! { ! if (TARGET_DLLIMPORT_DECL_ATTRIBUTES ! && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type))) ! { ! DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; ! DECL_VISIBILITY_SPECIFIED (decl) = 1; ! } ! else if (TREE_CODE (decl) == FUNCTION_DECL ! && DECL_DECLARED_INLINE_P (decl) ! && visibility_options.inlines_hidden) ! { ! DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; ! DECL_VISIBILITY_SPECIFIED (decl) = 1; ! } ! else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type)) ! { ! DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); ! DECL_VISIBILITY_SPECIFIED (decl) = 1; ! } ! /* If no explicit visibility information has been provided for ! this class, some targets require that class data be ! exported. */ ! else if (TREE_CODE (decl) == VAR_DECL ! && targetm.cxx.export_class_data () ! && (DECL_TINFO_P (decl) ! || (DECL_VTABLE_OR_VTT_P (decl) ! /* Construction virtual tables are not emitted ! because they cannot be referred to from other ! object files; their name is not standardized by ! the ABI. */ ! && !DECL_CONSTRUCTION_VTABLE_P (decl)))) ! DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; ! else ! { ! DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); ! DECL_VISIBILITY_SPECIFIED (decl) = 0; ! } ! } ! } ! ! /* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage ! for DECL has not already been determined, do so now by setting ! DECL_EXTERNAL, DECL_COMDAT and other related flags. Until this ! function is called entities with vague linkage whose definitions ! are available must have TREE_PUBLIC set. ! ! If this function decides to place DECL in COMDAT, it will set ! appropriate flags -- but will not clear DECL_EXTERNAL. It is up to ! the caller to decide whether or not to clear DECL_EXTERNAL. Some ! callers defer that decision until it is clear that DECL is actually ! required. */ void import_export_decl (tree decl) { + int emit_p; + bool comdat_p; + bool import_p; + if (DECL_INTERFACE_KNOWN (decl)) return; ! /* We cannot determine what linkage to give to an entity with vague ! linkage until the end of the file. For example, a virtual table ! for a class will be defined if and only if the key method is ! defined in this translation unit. As a further example, consider ! that when compiling a translation unit that uses PCH file with ! "-frepo" it would be incorrect to make decisions about what ! entities to emit when building the PCH; those decisions must be ! delayed until the repository information has been processed. */ ! gcc_assert (at_eof); ! /* Object file linkage for explicit instantiations is handled in ! mark_decl_instantiated. For static variables in functions with ! vague linkage, maybe_commonize_var is used. ! ! Therefore, the only declarations that should be provided to this ! function are those with external linkage that are: ! ! * implicit instantiations of function templates ! ! * inline function ! ! * implicit instantiations of static data members of class ! templates ! ! * virtual tables ! ! * typeinfo objects ! ! Furthermore, all entities that reach this point must have a ! definition available in this translation unit. ! ! The following assertions check these conditions. */ ! gcc_assert (TREE_CODE (decl) == FUNCTION_DECL ! || TREE_CODE (decl) == VAR_DECL); ! /* Any code that creates entities with TREE_PUBLIC cleared should ! also set DECL_INTERFACE_KNOWN. */ ! gcc_assert (TREE_PUBLIC (decl)); ! if (TREE_CODE (decl) == FUNCTION_DECL) ! gcc_assert (DECL_IMPLICIT_INSTANTIATION (decl) ! || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl) ! || DECL_DECLARED_INLINE_P (decl)); ! else ! gcc_assert (DECL_IMPLICIT_INSTANTIATION (decl) ! || DECL_VTABLE_OR_VTT_P (decl) ! || DECL_TINFO_P (decl)); ! /* Check that a definition of DECL is available in this translation ! unit. */ ! gcc_assert (!DECL_REALLY_EXTERN (decl)); ! ! /* Assume that DECL will not have COMDAT linkage. */ ! comdat_p = false; ! /* Assume that DECL will not be imported into this translation ! unit. */ ! import_p = false; ! ! /* See if the repository tells us whether or not to emit DECL in ! this translation unit. */ ! emit_p = repo_emit_p (decl); ! if (emit_p == 0) ! import_p = true; ! else if (emit_p == 1) { ! /* The repository indicates that this entity should be defined ! here. Make sure the back end honors that request. */ ! if (TREE_CODE (decl) == VAR_DECL) ! mark_needed (decl); ! else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) ! || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) { ! tree clone; ! FOR_EACH_CLONE (clone, decl) ! mark_needed (clone); ! } ! else ! mark_needed (decl); ! /* Output the definition as an ordinary strong definition. */ ! DECL_EXTERNAL (decl) = 0; ! DECL_INTERFACE_KNOWN (decl) = 1; ! return; ! } ! ! if (import_p) ! /* We have already decided what to do with this DECL; there is no ! need to check anything further. */ ! ; ! else if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl)) ! { ! tree type = DECL_CONTEXT (decl); ! import_export_class (type); ! if (TYPE_FOR_JAVA (type)) ! import_p = true; ! else if (CLASSTYPE_INTERFACE_KNOWN (type) ! && CLASSTYPE_INTERFACE_ONLY (type)) ! import_p = true; ! else if ((!flag_weak || TARGET_WEAK_NOT_IN_ARCHIVE_TOC) ! && !CLASSTYPE_USE_TEMPLATE (type) ! && CLASSTYPE_KEY_METHOD (type) ! && !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type))) ! /* The ABI requires that all virtual tables be emitted with ! COMDAT linkage. However, on systems where COMDAT symbols ! don't show up in the table of contents for a static ! archive, or on systems without weak symbols (where we ! approximate COMDAT linkage by using internal linkage), the ! linker will report errors about undefined symbols because ! it will not see the virtual table definition. Therefore, ! in the case that we know that the virtual table will be ! emitted in only one translation unit, we make the virtual ! table an ordinary definition with external linkage. */ ! DECL_EXTERNAL (decl) = 0; ! else if (CLASSTYPE_INTERFACE_KNOWN (type)) ! { ! /* TYPE is being exported from this translation unit, so DECL ! should be defined here. */ ! if (!flag_weak && CLASSTYPE_EXPLICIT_INSTANTIATION (type)) ! /* If a class is declared in a header with the "extern ! template" extension, then it will not be instantiated, ! even in translation units that would normally require ! it. Often such classes are explicitly instantiated in ! one translation unit. Therefore, the explicit ! instantiation must be made visible to other translation ! units. */ ! DECL_EXTERNAL (decl) = 0; else ! { ! /* The ABI requires COMDAT linkage. Normally, we only ! emit COMDAT things when they are needed; make sure ! that we realize that this entity is indeed ! needed. */ ! comdat_p = true; ! mark_needed (decl); ! } } + else if (!flag_implicit_templates + && CLASSTYPE_IMPLICIT_INSTANTIATION (type)) + import_p = true; else + comdat_p = true; + } + else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)) + { + tree type = TREE_TYPE (DECL_NAME (decl)); + if (CLASS_TYPE_P (type)) { ! import_export_class (type); ! if (CLASSTYPE_INTERFACE_KNOWN (type) ! && TYPE_POLYMORPHIC_P (type) ! && CLASSTYPE_INTERFACE_ONLY (type) ! /* If -fno-rtti was specified, then we cannot be sure ! that RTTI information will be emitted with the ! virtual table of the class, so we must emit it ! wherever it is used. */ ! && flag_rtti) ! import_p = true; ! else ! { ! comdat_p = true; ! if (CLASSTYPE_INTERFACE_KNOWN (type) ! && !CLASSTYPE_INTERFACE_ONLY (type)) ! { ! mark_needed (decl); ! if (!flag_weak) ! { ! comdat_p = false; ! DECL_EXTERNAL (decl) = 0; ! } ! } ! } } + else + comdat_p = true; + } + else if (DECL_TEMPLATE_INSTANTIATION (decl) + || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) + { + /* DECL is an implicit instantiation of a function or static + data member. */ + if (flag_implicit_templates + || (flag_implicit_inline_templates + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (decl))) + comdat_p = true; + else + /* If we are not implicitly generating templates, then mark + this entity as undefined in this translation unit. */ + import_p = true; } else if (DECL_FUNCTION_MEMBER_P (decl)) { *************** import_export_decl (tree decl) *** 1710,1764 **** /* Always make artificials weak. */ if (DECL_ARTIFICIAL (decl) && flag_weak) ! comdat_linkage (decl); else maybe_make_one_only (decl); } } else ! comdat_linkage (decl); } else ! comdat_linkage (decl); ! ! DECL_INTERFACE_KNOWN (decl) = 1; ! } ! ! /* Here, we only decide whether or not the tinfo node should be ! emitted with the vtable. IS_IN_LIBRARY is nonzero iff the ! typeinfo for TYPE should be in the runtime library. */ ! void ! import_export_tinfo (tree decl, tree type, bool is_in_library) ! { ! if (DECL_INTERFACE_KNOWN (decl)) ! return; ! ! if (IS_AGGR_TYPE (type)) ! import_export_class (type); ! ! if (IS_AGGR_TYPE (type) && CLASSTYPE_INTERFACE_KNOWN (type) ! && TYPE_POLYMORPHIC_P (type) ! /* If -fno-rtti, we're not necessarily emitting this stuff with ! the class, so go ahead and emit it now. This can happen when ! a class is used in exception handling. */ ! && flag_rtti) { ! DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type); ! DECL_COMDAT (decl) = 0; } ! else { ! DECL_NOT_REALLY_EXTERN (decl) = 1; ! DECL_COMDAT (decl) = 1; } - /* Now override some cases. */ - if (flag_weak) - DECL_COMDAT (decl) = 1; - else if (is_in_library) - DECL_COMDAT (decl) = 0; - DECL_INTERFACE_KNOWN (decl) = 1; } --- 1891,1921 ---- /* Always make artificials weak. */ if (DECL_ARTIFICIAL (decl) && flag_weak) ! comdat_p = true; else maybe_make_one_only (decl); } } else ! comdat_p = true; } else ! comdat_p = true; ! if (import_p) { ! /* If we are importing DECL into this translation unit, mark is ! an undefined here. */ ! DECL_EXTERNAL (decl) = 1; ! DECL_NOT_REALLY_EXTERN (decl) = 0; } ! else if (comdat_p) { ! /* If we decided to put DECL in COMDAT, mark it accordingly at ! this point. */ ! comdat_linkage (decl); } DECL_INTERFACE_KNOWN (decl) = 1; } *************** build_cleanup (tree decl) *** 1774,1780 **** /* 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. */ --- 1931,1937 ---- /* This function should only be called for declarations that really require cleanups. */ ! gcc_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type)); /* Treat all objects with destructors as used; the destructor may do something substantive. */ *************** get_guard (tree decl) *** 1810,1816 **** /* We use a type that is big enough to contain a mutex as well as an integer counter. */ ! 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. */ --- 1967,1973 ---- /* We use a type that is big enough to contain a mutex as well as an integer counter. */ ! guard_type = targetm.cxx.guard_type (); guard = build_decl (VAR_DECL, sname, guard_type); /* The guard should have the same linkage as what it guards. */ *************** get_guard (tree decl) *** 1822,1827 **** --- 1979,1985 ---- DECL_WEAK (guard) = DECL_WEAK (decl); DECL_ARTIFICIAL (guard) = 1; + DECL_IGNORED_P (guard) = 1; TREE_USED (guard) = 1; pushdecl_top_level_and_finish (guard, NULL_TREE); } *************** get_guard (tree decl) *** 1834,1848 **** static tree get_guard_bits (tree guard) { ! /* We only set the first byte of the guard, in order to leave room ! for a mutex in the high-order bits. */ ! guard = build1 (ADDR_EXPR, ! build_pointer_type (TREE_TYPE (guard)), ! guard); ! guard = build1 (NOP_EXPR, ! build_pointer_type (char_type_node), ! guard); ! guard = build1 (INDIRECT_REF, char_type_node, guard); return guard; } --- 1992,2009 ---- static tree get_guard_bits (tree guard) { ! if (!targetm.cxx.guard_mask_bit ()) ! { ! /* We only set the first byte of the guard, in order to leave room ! for a mutex in the high-order bits. */ ! guard = build1 (ADDR_EXPR, ! build_pointer_type (TREE_TYPE (guard)), ! guard); ! guard = build1 (NOP_EXPR, ! build_pointer_type (char_type_node), ! guard); ! guard = build1 (INDIRECT_REF, char_type_node, guard); ! } return guard; } *************** get_guard_cond (tree guard) *** 1857,1862 **** --- 2018,2033 ---- /* Check to see if the GUARD is zero. */ guard = get_guard_bits (guard); + + /* Mask off all but the low bit. */ + if (targetm.cxx.guard_mask_bit ()) + { + guard_value = integer_one_node; + if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) + guard_value = convert (TREE_TYPE (guard), guard_value); + guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value); + } + guard_value = integer_zero_node; if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) guard_value = convert (TREE_TYPE (guard), guard_value); *************** set_guard (tree guard) *** 1885,1892 **** static tree start_objects (int method_type, int initp) { - tree fnname; tree body; char type[10]; /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ --- 2056,2063 ---- static tree start_objects (int method_type, int initp) { tree body; + tree fndecl; char type[10]; /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ *************** start_objects (int method_type, int init *** 1906,1917 **** else sprintf (type, "%c", method_type); ! fnname = get_file_function_name_long (type); ! ! start_function (void_list_node, ! make_call_declarator (fnname, void_list_node, NULL_TREE, ! NULL_TREE), ! NULL_TREE, SF_DEFAULT); /* It can be a static function as long as collect2 does not have to scan the object file to find its ctor/dtor routine. */ --- 2077,2087 ---- else sprintf (type, "%c", method_type); ! fndecl = build_lang_decl (FUNCTION_DECL, ! get_file_function_name_long (type), ! build_function_type (void_type_node, ! void_list_node)); ! start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED); /* It can be a static function as long as collect2 does not have to scan the object file to find its ctor/dtor routine. */ *************** start_objects (int method_type, int init *** 1927,1940 **** DECL_GLOBAL_DTOR_P (current_function_decl) = 1; DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1; ! body = begin_compound_stmt (/*has_no_scope=*/false); /* We cannot allow these functions to be elided, even if they do not have external linkage. And, there's no point in deferring compilation of thes functions; they're all going to have to be out anyhow. */ ! current_function_cannot_inline ! = "static constructors and destructors cannot be inlined"; return body; } --- 2097,2110 ---- DECL_GLOBAL_DTOR_P (current_function_decl) = 1; DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1; ! body = begin_compound_stmt (BCS_FN_BODY); /* We cannot allow these functions to be elided, even if they do not have external linkage. And, there's no point in deferring compilation of thes functions; they're all going to have to be out anyhow. */ ! DECL_INLINE (current_function_decl) = 0; ! DECL_UNINLINABLE (current_function_decl) = 1; return body; } *************** start_static_storage_duration_function ( *** 2078,2095 **** It is static because we only need to call this function from the various constructor and destructor functions for this module. */ ! start_function (/*specs=*/NULL_TREE, ! ssdf_decl, ! /*attrs=*/NULL_TREE, ! SF_PRE_PARSED); /* Set up the scope of the outermost block in the function. */ ! body = begin_compound_stmt (/*has_no_scope=*/false); /* This function must not be deferred because we are depending on its compilation to tell us what is TREE_SYMBOL_REFERENCED. */ ! current_function_cannot_inline ! = "static storage duration functions cannot be inlined"; return body; } --- 2248,2264 ---- It is static because we only need to call this function from the various constructor and destructor functions for this module. */ ! start_preparsed_function (ssdf_decl, ! /*attrs=*/NULL_TREE, ! SF_PRE_PARSED); /* Set up the scope of the outermost block in the function. */ ! body = begin_compound_stmt (BCS_FN_BODY); /* This function must not be deferred because we are depending on its compilation to tell us what is TREE_SYMBOL_REFERENCED. */ ! DECL_INLINE (ssdf_decl) = 0; ! DECL_UNINLINABLE (ssdf_decl) = 1; return body; } *************** start_static_initialization_or_destructi *** 2191,2197 **** guard_if_stmt = begin_if_stmt (); cond = cp_build_binary_op (EQ_EXPR, priority_decl, ! build_int_2 (priority, 0)); init_cond = initp ? integer_one_node : integer_zero_node; init_cond = cp_build_binary_op (EQ_EXPR, initialize_p_decl, --- 2360,2366 ---- guard_if_stmt = begin_if_stmt (); cond = cp_build_binary_op (EQ_EXPR, priority_decl, ! build_int_cst (NULL_TREE, priority)); init_cond = initp ? integer_one_node : integer_zero_node; init_cond = cp_build_binary_op (EQ_EXPR, initialize_p_decl, *************** start_static_initialization_or_destructi *** 2218,2224 **** { /* When using __cxa_atexit, we never try to destroy anything from a static destructor. */ ! my_friendly_assert (initp, 20000629); guard_cond = get_guard_cond (guard); } /* If we don't have __cxa_atexit, then we will be running --- 2387,2393 ---- { /* When using __cxa_atexit, we never try to destroy anything from a static destructor. */ ! gcc_assert (initp); guard_cond = get_guard_cond (guard); } /* If we don't have __cxa_atexit, then we will be running *************** static void *** 2264,2270 **** finish_static_initialization_or_destruction (tree guard_if_stmt) { finish_then_clause (guard_if_stmt); ! finish_if_stmt (); /* Now that we're done with DECL we don't need to pretend to be a member of its class any longer. */ --- 2433,2439 ---- finish_static_initialization_or_destruction (tree guard_if_stmt) { finish_then_clause (guard_if_stmt); ! finish_if_stmt (guard_if_stmt); /* Now that we're done with DECL we don't need to pretend to be a member of its class any longer. */ *************** do_static_initialization (tree decl, tre *** 2289,2300 **** if (init) finish_expr_stmt (init); ! /* If we're using __cxa_atexit, register a a function that calls the destructor for the object. */ if (flag_use_cxa_atexit) ! register_dtor_fn (decl); ! /* Finsh up. */ finish_static_initialization_or_destruction (guard_if_stmt); } --- 2458,2469 ---- if (init) finish_expr_stmt (init); ! /* If we're using __cxa_atexit, register a function that calls the destructor for the object. */ if (flag_use_cxa_atexit) ! finish_expr_stmt (register_dtor_fn (decl)); ! /* Finish up. */ finish_static_initialization_or_destruction (guard_if_stmt); } *************** do_static_destruction (tree decl) *** 2310,2316 **** /* If we're using __cxa_atexit, then destructors are registered immediately after objects are initialized. */ ! my_friendly_assert (!flag_use_cxa_atexit, 20000121); /* If we don't need a destructor, there's nothing to do. */ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) --- 2479,2485 ---- /* If we're using __cxa_atexit, then destructors are registered immediately after objects are initialized. */ ! gcc_assert (!flag_use_cxa_atexit); /* If we don't need a destructor, there's nothing to do. */ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) *************** prune_vars_needing_no_initialization (tr *** 2351,2357 **** } /* The only things that can be initialized are variables. */ ! my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420); /* If this object is not defined, we don't need to do anything here. */ --- 2520,2526 ---- } /* The only things that can be initialized are variables. */ ! gcc_assert (TREE_CODE (decl) == VAR_DECL); /* If this object is not defined, we don't need to do anything here. */ *************** write_out_vars (tree vars) *** 2389,2396 **** tree v; for (v = vars; v; v = TREE_CHAIN (v)) ! if (!var_finalized_p (TREE_VALUE (v))) ! rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1); } /* Generate a static constructor (if CONSTRUCTOR_P) or destructor --- 2558,2571 ---- tree v; for (v = vars; v; v = TREE_CHAIN (v)) ! { ! tree var = TREE_VALUE (v); ! if (!var_finalized_p (var)) ! { ! import_export_decl (var); ! rest_of_decl_compilation (var, 1, 1); ! } ! } } /* Generate a static constructor (if CONSTRUCTOR_P) or destructor *************** generate_ctor_or_dtor_function (bool con *** 2408,2414 **** --- 2583,2593 ---- size_t i; input_location = *locus; + #ifdef USE_MAPPED_LOCATION + /* ??? */ + #else locus->line++; + #endif /* We use `I' to indicate initialization and `D' to indicate destruction. */ *************** generate_ctor_or_dtor_function (bool con *** 2431,2439 **** if (! body) body = start_objects (function_key, priority); ! 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 (fndecl, arguments)); } --- 2610,2620 ---- if (! body) body = start_objects (function_key, priority); ! arguments = tree_cons (NULL_TREE, ! build_int_cst (NULL_TREE, priority), NULL_TREE); ! arguments = tree_cons (NULL_TREE, ! build_int_cst (NULL_TREE, constructor_p), arguments); finish_expr_stmt (build_function_call (fndecl, arguments)); } *************** cxx_callgraph_analyze_expr (tree *tp, in *** 2502,2522 **** { tree t = *tp; ! if (flag_unit_at_a_time) ! switch (TREE_CODE (t)) ! { ! case PTRMEM_CST: ! if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) ! cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t))); ! break; ! case BASELINK: ! if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL) ! cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t))); ! break; ! ! default: ! break; ! } return NULL; } --- 2683,2718 ---- { tree t = *tp; ! switch (TREE_CODE (t)) ! { ! case PTRMEM_CST: ! if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) ! cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t))); ! break; ! case BASELINK: ! if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL) ! cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t))); ! break; ! case VAR_DECL: ! if (DECL_VTABLE_OR_VTT_P (t)) ! { ! /* The ABI requires that all virtual tables be emitted ! whenever one of them is. */ ! tree vtbl; ! for (vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (t)); ! vtbl; ! vtbl = TREE_CHAIN (vtbl)) ! mark_decl_referenced (vtbl); ! } ! else if (DECL_CONTEXT (t) ! && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL) ! /* If we need a static variable in a function, then we ! need the containing function. */ ! mark_decl_referenced (DECL_CONTEXT (t)); ! break; ! default: ! break; ! } return NULL; } *************** cxx_callgraph_analyze_expr (tree *tp, in *** 2527,2539 **** first, since that way we only need to reverse the decls once. */ void ! finish_file (void) { tree vars; bool reconsider; size_t i; location_t locus; unsigned ssdf_count = 0; locus = input_location; at_eof = 1; --- 2723,2736 ---- first, since that way we only need to reverse the decls once. */ void ! cp_finish_file (void) { tree vars; bool reconsider; size_t i; location_t locus; unsigned ssdf_count = 0; + int retries = 0; locus = input_location; at_eof = 1; *************** finish_file (void) *** 2545,2556 **** if (pch_file) c_common_write_pch (); /* Otherwise, GDB can get confused, because in only knows about source for LINENO-1 lines. */ input_line -= 1; ! ! interface_unknown = 1; ! interface_only = 0; /* We now have to write out all the stuff we put off writing out. These include: --- 2742,2754 ---- if (pch_file) c_common_write_pch (); + #ifdef USE_MAPPED_LOCATION + /* FIXME - huh? */ + #else /* Otherwise, GDB can get confused, because in only knows about source for LINENO-1 lines. */ input_line -= 1; ! #endif /* We now have to write out all the stuff we put off writing out. These include: *************** finish_file (void) *** 2571,2587 **** timevar_push (TV_VARCONST); emit_support_tinfos (); ! do { tree t; - size_t n_old, n_new; reconsider = false; /* If there are templates that we've put off instantiating, do them now. */ ! instantiate_pending_templates (); ggc_collect (); /* Write out virtual tables as required. Note that writing out --- 2769,2784 ---- timevar_push (TV_VARCONST); emit_support_tinfos (); ! do { tree t; reconsider = false; /* If there are templates that we've put off instantiating, do them now. */ ! instantiate_pending_templates (retries); ggc_collect (); /* Write out virtual tables as required. Note that writing out *************** finish_file (void) *** 2589,2595 **** 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))) { --- 2786,2792 ---- 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))) { *************** finish_file (void) *** 2615,2649 **** next = TREE_CHAIN (t); } } ! /* Write out needed type info variables. We have to be careful looping through unemitted decls, because emit_tinfo_decl may ! cause other variables to be needed. We stick new elements ! (and old elements that we may need to reconsider) at the end ! of the array, then shift them back to the beginning once we're ! done. */ ! ! n_old = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls); ! for (i = 0; i < n_old; ++i) ! { ! tree tinfo_decl = VARRAY_TREE (unemitted_tinfo_decls, i); ! if (emit_tinfo_decl (tinfo_decl)) ! reconsider = true; ! else ! VARRAY_PUSH_TREE (unemitted_tinfo_decls, tinfo_decl); ! } ! ! /* The only elements we want to keep are the new ones. Copy ! them to the beginning of the array, then get rid of the ! leftovers. */ ! n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) - n_old; ! if (n_new) ! memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0), ! &VARRAY_TREE (unemitted_tinfo_decls, n_old), ! n_new * sizeof (tree)); ! memset (&VARRAY_TREE (unemitted_tinfo_decls, n_new), ! 0, n_old * sizeof (tree)); ! VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new; /* The list of objects with static storage duration is built up in reverse order. We clear STATIC_AGGREGATES so that any new --- 2812,2830 ---- next = TREE_CHAIN (t); } } ! /* Write out needed type info variables. We have to be careful looping through unemitted decls, because emit_tinfo_decl may ! cause other variables to be needed. New elements will be ! appended, and we remove from the vector those that actually ! get emitted. */ ! for (i = VEC_length (tree, unemitted_tinfo_decls); ! VEC_iterate (tree, unemitted_tinfo_decls, --i, t);) ! if (emit_tinfo_decl (t)) ! { ! reconsider = true; ! VEC_unordered_remove (tree, unemitted_tinfo_decls, i); ! } /* The list of objects with static storage duration is built up in reverse order. We clear STATIC_AGGREGATES so that any new *************** finish_file (void) *** 2703,2718 **** instantiations, etc. */ reconsider = true; ssdf_count++; locus.line++; } for (i = 0; i < deferred_fns_used; ++i) { tree decl = VARRAY_TREE (deferred_fns, i); /* Does it need synthesizing? */ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - && TREE_USED (decl) && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) { /* Even though we're already at the top-level, we push --- 2884,2905 ---- instantiations, etc. */ reconsider = true; ssdf_count++; + #ifdef USE_MAPPED_LOCATION + /* ??? */ + #else locus.line++; + #endif } + /* Go through the set of inline functions whose bodies have not + been emitted yet. If out-of-line copies of these functions + are required, emit them. */ for (i = 0; i < deferred_fns_used; ++i) { tree decl = VARRAY_TREE (deferred_fns, i); /* Does it need synthesizing? */ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) { /* Even though we're already at the top-level, we push *************** finish_file (void) *** 2726,2737 **** reconsider = true; } - /* 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; --- 2913,2918 ---- *************** finish_file (void) *** 2749,2755 **** function twice. */ if (DECL_NOT_REALLY_EXTERN (decl) && DECL_INITIAL (decl) ! && DECL_NEEDED_P (decl)) DECL_EXTERNAL (decl) = 0; /* If we're going to need to write this function out, and --- 2930,2936 ---- function twice. */ if (DECL_NOT_REALLY_EXTERN (decl) && DECL_INITIAL (decl) ! && decl_needed_p (decl)) DECL_EXTERNAL (decl) = 0; /* If we're going to need to write this function out, and *************** finish_file (void) *** 2757,2767 **** (There might be no body if this is a method we haven't gotten around to synthesizing yet.) */ if (!DECL_EXTERNAL (decl) ! && DECL_NEEDED_P (decl) ! && DECL_SAVED_TREE (decl) && !TREE_ASM_WRITTEN (decl) ! && (!flag_unit_at_a_time ! || !cgraph_node (decl)->local.finalized)) { /* We will output the function; no longer consider it in this loop. */ --- 2938,2946 ---- (There might be no body if this is a method we haven't gotten around to synthesizing yet.) */ if (!DECL_EXTERNAL (decl) ! && decl_needed_p (decl) && !TREE_ASM_WRITTEN (decl) ! && !cgraph_node (decl)->local.finalized) { /* We will output the function; no longer consider it in this loop. */ *************** finish_file (void) *** 2785,2794 **** for (i = 0; i < pending_statics_used; ++i) { tree decl = VARRAY_TREE (pending_statics, i); ! if (var_finalized_p (decl)) continue; import_export_decl (decl); ! if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl)) DECL_EXTERNAL (decl) = 0; } if (pending_statics --- 2964,2975 ---- for (i = 0; i < pending_statics_used; ++i) { tree decl = VARRAY_TREE (pending_statics, i); ! if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)) continue; import_export_decl (decl); ! /* If this static data member is needed, provide it to the ! back end. */ ! if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl)) DECL_EXTERNAL (decl) = 0; } if (pending_statics *************** finish_file (void) *** 2796,2803 **** --- 2977,2991 ---- pending_statics_used)) reconsider = true; + /* Ask the back end to emit functions and variables that are + enqueued. These emissions may result in marking more entities + as needed. */ if (cgraph_assemble_pending_functions ()) reconsider = true; + if (cgraph_varpool_assemble_pending_decls ()) + reconsider = true; + + retries++; } while (reconsider); *************** finish_file (void) *** 2806,2825 **** { 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); /* This symbol is effectively an "extern" declaration now. This is not strictly necessary, but removes a duplicate warning. */ TREE_PUBLIC (decl) = 1; } - } /* We give C linkage to static constructors and destructors. */ --- 2994,3021 ---- { tree decl = VARRAY_TREE (deferred_fns, i); ! if (/* Check online inline functions that were actually used. */ ! TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) ! /* But not defined. */ ! && DECL_REALLY_EXTERN (decl) ! /* If we decided to emit this function in another ! translation unit, the fact that the definition was ! missing here likely indicates only that the repository ! decided to place the function elsewhere. With -Winline, ! we will still warn if we could not inline the ! function. */ ! && !flag_use_repository ! /* 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 %qD used but never defined", decl); /* This symbol is effectively an "extern" declaration now. This is not strictly necessary, but removes a duplicate warning. */ TREE_PUBLIC (decl) = 1; } } /* We give C linkage to static constructors and destructors. */ *************** finish_file (void) *** 2846,2860 **** if (priority_info_map) splay_tree_delete (priority_info_map); /* We're done with static constructors, so we can go back to "C++" linkage now. */ pop_lang_context (); ! if (flag_unit_at_a_time) ! { ! cgraph_finalize_compilation_unit (); ! cgraph_optimize (); ! } /* Now, issue warnings about static, but not defined, functions, etc., and emit debugging information. */ --- 3042,3056 ---- if (priority_info_map) splay_tree_delete (priority_info_map); + /* Generate any missing aliases. */ + maybe_apply_pending_pragma_weaks (); + /* We're done with static constructors, so we can go back to "C++" linkage now. */ pop_lang_context (); ! cgraph_finalize_compilation_unit (); ! cgraph_optimize (); /* Now, issue warnings about static, but not defined, functions, etc., and emit debugging information. */ *************** finish_file (void) *** 2869,2880 **** to a file. */ { int flags; ! FILE *stream = dump_begin (TDI_all, &flags); if (stream) { dump_node (global_namespace, flags & ~TDF_SLIM, stream); ! dump_end (TDI_all, stream); } } --- 3065,3076 ---- to a file. */ { int flags; ! FILE *stream = dump_begin (TDI_tu, &flags); if (stream) { dump_node (global_namespace, flags & ~TDF_SLIM, stream); ! dump_end (TDI_tu, stream); } } *************** finish_file (void) *** 2886,2891 **** --- 3082,3091 ---- dump_time_statistics (); } input_location = locus; + + #ifdef ENABLE_CHECKING + validate_conversion_obstack (); + #endif /* ENABLE_CHECKING */ } /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the *************** build_offset_ref_call_from_tree (tree fn *** 2907,2918 **** if (processing_template_decl) { ! my_friendly_assert (TREE_CODE (fn) == DOTSTAR_EXPR ! || TREE_CODE (fn) == MEMBER_REF, ! 20030708); if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (args)) ! return build_min_nt (CALL_EXPR, fn, args); /* Transform the arguments and add the implicit "this" parameter. That must be done before the FN is transformed --- 3107,3117 ---- if (processing_template_decl) { ! gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR ! || TREE_CODE (fn) == MEMBER_REF); if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (args)) ! return build_min_nt (CALL_EXPR, fn, args, NULL_TREE); /* Transform the arguments and add the implicit "this" parameter. That must be done before the FN is transformed *************** build_offset_ref_call_from_tree (tree fn *** 2942,2948 **** expr = build_function_call (fn, args); if (processing_template_decl && expr != error_mark_node) ! return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args); return expr; } --- 3141,3147 ---- expr = build_function_call (fn, args); if (processing_template_decl && expr != error_mark_node) ! return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE); return expr; } *************** check_default_args (tree x) *** 2959,2965 **** saw_def = true; else if (saw_def) { ! cp_error_at ("default argument missing for parameter %P of `%+#D'", i, x); break; } --- 3158,3164 ---- saw_def = true; else if (saw_def) { ! cp_error_at ("default argument missing for parameter %P of %q+#D", i, x); break; } *************** mark_used (tree decl) *** 2976,2983 **** 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? */ --- 3175,3186 ---- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && !TREE_ASM_WRITTEN (decl)) /* Remember it, so we can check it was defined. */ ! { ! if (DECL_DEFERRED_FN (decl)) ! return; ! note_vague_linkage_fn (decl); ! } ! assemble_external (decl); /* Is it a synthesized method that needs to be synthesized? */ *************** mark_used (tree decl) *** 2986,2994 **** && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl) && ! DECL_INITIAL (decl) ! /* Kludge: don't synthesize for default args. */ && current_function_decl) { synthesize_method (decl); /* If we've already synthesized the method we don't need to instantiate it, so we can return right away. */ --- 3189,3208 ---- && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl) && ! DECL_INITIAL (decl) ! /* Kludge: don't synthesize for default args. Unfortunately this ! rules out initializers of namespace-scoped objects too, but ! it's sort-of ok if the implicit ctor or dtor decl keeps ! pointing to the class location. */ && current_function_decl) { + /* Put the function definition at the position where it is needed, + rather than within the body of the class. That way, an error + 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. */ + DECL_SOURCE_LOCATION (decl) = input_location; + synthesize_method (decl); /* If we've already synthesized the method we don't need to instantiate it, so we can return right away. */ *************** mark_used (tree decl) *** 3005,3044 **** || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (DECL_TEMPLATE_RESULT (template_for_substitution (decl)))))) ! { ! 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. ! ! This is not needed for unit-at-a-time since we reorder the functions ! in topological order anyway. ! */ ! defer = (!flag_exceptions ! || flag_unit_at_a_time ! || !optimize ! || 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 ! || !current_function_decl ! /* 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); ! } } #include "gt-cp-decl2.h" --- 3219,3229 ---- || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (DECL_TEMPLATE_RESULT (template_for_substitution (decl)))))) ! /* 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. */ ! instantiate_decl (decl, /*defer_ok=*/true, /*undefined_ok=*/0); } #include "gt-cp-decl2.h" diff -Nrcpad gcc-3.4.3/gcc/cp/dump.c gcc-4.0.0/gcc/cp/dump.c *** gcc-3.4.3/gcc/cp/dump.c Mon Dec 8 20:29:15 2003 --- gcc-4.0.0/gcc/cp/dump.c Fri Oct 15 14:49:30 2004 *************** *** 1,5 **** /* Tree-dumping functionality for intermediate representation. ! Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Mark Mitchell This file is part of GCC. --- 1,5 ---- /* Tree-dumping functionality for intermediate representation. ! Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Written by Mark Mitchell This file is part of GCC. *************** cp_dump_tree (void* dump_info, tree t) *** 264,278 **** if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t)) dump_string(di, "spec"); ! if (!dump_flag (di, TDF_SLIM, t)) { int i; ! for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i) { - tree base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i); dump_child ("base", BINFO_TYPE (base_binfo)); ! if (TREE_VIA_VIRTUAL (base_binfo)) dump_string (di, "virtual"); dump_access (di, base_binfo); } --- 264,280 ---- if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t)) dump_string(di, "spec"); ! if (!dump_flag (di, TDF_SLIM, t) && TYPE_BINFO (t)) { int i; + tree binfo; + tree base_binfo; ! for (binfo = TYPE_BINFO (t), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { dump_child ("base", BINFO_TYPE (base_binfo)); ! if (BINFO_VIRTUAL_P (base_binfo)) dump_string (di, "virtual"); dump_access (di, base_binfo); } *************** cp_dump_tree (void* dump_info, tree t) *** 366,379 **** dump_string (di, "cleanup"); dump_child ("body", TRY_STMTS (t)); dump_child ("hdlr", TRY_HANDLERS (t)); - dump_next_stmt (di, t); break; case EH_SPEC_BLOCK: dump_stmt (di, t); dump_child ("body", EH_SPEC_STMTS (t)); dump_child ("raises", EH_SPEC_RAISES (t)); - dump_next_stmt (di, t); break; case PTRMEM_CST: --- 368,379 ---- *************** cp_dump_tree (void* dump_info, tree t) *** 397,417 **** dump_stmt (di, t); dump_child ("parm", HANDLER_PARMS (t)); dump_child ("body", HANDLER_BODY (t)); - dump_next_stmt (di, t); break; case MUST_NOT_THROW_EXPR: dump_stmt (di, t); dump_child ("body", TREE_OPERAND (t, 0)); - dump_next_stmt (di, t); break; case USING_STMT: dump_stmt (di, t); dump_child ("nmsp", USING_STMT_NAMESPACE (t)); - dump_next_stmt (di, t); break; ! default: break; } --- 397,428 ---- dump_stmt (di, t); dump_child ("parm", HANDLER_PARMS (t)); dump_child ("body", HANDLER_BODY (t)); break; case MUST_NOT_THROW_EXPR: dump_stmt (di, t); dump_child ("body", TREE_OPERAND (t, 0)); break; case USING_STMT: dump_stmt (di, t); dump_child ("nmsp", USING_STMT_NAMESPACE (t)); break; ! ! case CLEANUP_STMT: ! dump_stmt (di, t); ! dump_child ("decl", CLEANUP_DECL (t)); ! dump_child ("expr", CLEANUP_EXPR (t)); ! dump_child ("body", CLEANUP_BODY (t)); ! break; ! ! case IF_STMT: ! dump_stmt (di, t); ! dump_child ("cond", IF_COND (t)); ! dump_child ("then", THEN_CLAUSE (t)); ! dump_child ("else", ELSE_CLAUSE (t)); ! break; ! default: break; } diff -Nrcpad gcc-3.4.3/gcc/cp/error.c gcc-4.0.0/gcc/cp/error.c *** gcc-3.4.3/gcc/cp/error.c Thu Oct 28 03:49:40 2004 --- gcc-4.0.0/gcc/cp/error.c Thu Feb 24 21:55:15 2005 *************** *** 1,7 **** /* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, ! 2003 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify --- 1,7 ---- /* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, ! 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify *************** Boston, MA 02111-1307, USA. */ *** 32,44 **** #include "langhooks-def.h" #include "cxx-pretty-print.h" ! enum pad { none, before, after }; ! ! #define pp_template_argument_list_start(PP) \ ! pp_non_consecutive_character (PP, '<') ! #define pp_template_argument_list_end(PP) \ ! pp_non_consecutive_character (PP, '>') ! #define pp_separate_with_comma(PP) pp_string (PP, ", ") /* The global buffer where we dump everything. It is there only for transitional purpose. It is expected, in the near future, to be --- 32,38 ---- #include "langhooks-def.h" #include "cxx-pretty-print.h" ! #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',') /* The global buffer where we dump everything. It is there only for transitional purpose. It is expected, in the near future, to be *************** static cxx_pretty_printer scratch_pretty *** 48,56 **** # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T))) - #define reinit_global_formatting_buffer() \ - output_clear_message_text (scratch_buffer) - static const char *args_to_string (tree, int); static const char *assop_to_string (enum tree_code); static const char *code_to_string (enum tree_code); --- 42,47 ---- *************** static void dump_expr (tree, int); *** 72,86 **** static void dump_unary_op (const char *, tree, int); static void dump_binary_op (const char *, tree, int); static void dump_aggr_type (tree, int); ! static enum pad dump_type_prefix (tree, int); static void dump_type_suffix (tree, int); static void dump_function_name (tree, int); static void dump_expr_list (tree, int); static void dump_global_iord (tree); - static enum pad dump_qualifiers (tree, enum pad); static void dump_parameters (tree, int); static void dump_exception_spec (tree, int); - static const char *class_key_or_enum (tree); static void dump_template_argument (tree, int); static void dump_template_argument_list (tree, int); static void dump_template_parameter (tree, int); --- 63,75 ---- static void dump_unary_op (const char *, tree, int); static void dump_binary_op (const char *, tree, int); static void dump_aggr_type (tree, int); ! static void dump_type_prefix (tree, int); static void dump_type_suffix (tree, int); static void dump_function_name (tree, int); static void dump_expr_list (tree, int); static void dump_global_iord (tree); static void dump_parameters (tree, int); static void dump_exception_spec (tree, int); static void dump_template_argument (tree, int); static void dump_template_argument_list (tree, int); static void dump_template_parameter (tree, int); *************** static void cp_diagnostic_finalizer (dia *** 98,104 **** static void cp_print_error_function (diagnostic_context *, diagnostic_info *); static bool cp_printer (pretty_printer *, text_info *); - static void pp_non_consecutive_character (cxx_pretty_printer *, int); static tree locate_error (const char *, va_list); static location_t location_of (tree); --- 87,92 ---- *************** dump_scope (tree scope, int flags) *** 128,178 **** if (scope != global_namespace) { dump_decl (scope, f); ! pp_colon_colon (cxx_pp); } } else if (AGGREGATE_TYPE_P (scope)) { dump_type (scope, f); ! pp_colon_colon (cxx_pp); } else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL) { dump_function_decl (scope, f); ! pp_colon_colon (cxx_pp); ! } ! } ! ! /* Dump type qualifiers, providing padding as requested. Return an ! indication of whether we dumped something. */ ! ! static enum pad ! dump_qualifiers (tree t, enum pad p) ! { ! static const int masks[] = ! {TYPE_QUAL_CONST, TYPE_QUAL_VOLATILE, TYPE_QUAL_RESTRICT}; ! static const char *const names[] = ! {"const", "volatile", "__restrict"}; ! int ix; ! int quals = TYPE_QUALS (t); ! int do_after = p == after; ! ! if (quals) ! { ! for (ix = 0; ix != 3; ix++) ! if (masks[ix] & quals) ! { ! if (p == before) ! pp_space (cxx_pp); ! p = before; ! pp_identifier (cxx_pp, names[ix]); ! } ! if (do_after) ! pp_space (cxx_pp); } - else - p = none; - return p; } /* Dump the template ARGument under control of FLAGS. */ --- 116,134 ---- if (scope != global_namespace) { dump_decl (scope, f); ! pp_cxx_colon_colon (cxx_pp); } } else if (AGGREGATE_TYPE_P (scope)) { dump_type (scope, f); ! pp_cxx_colon_colon (cxx_pp); } else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL) { dump_function_decl (scope, f); ! pp_cxx_colon_colon (cxx_pp); } } /* Dump the template ARGument under control of FLAGS. */ *************** dump_template_parameter (tree parm, int *** 217,231 **** { if (flags & TFF_DECL_SPECIFIERS) { ! pp_identifier (cxx_pp, "class"); if (DECL_NAME (p)) ! { ! pp_space (cxx_pp); ! pp_tree_identifier (cxx_pp, DECL_NAME (p)); ! } } else if (DECL_NAME (p)) ! pp_tree_identifier (cxx_pp, DECL_NAME (p)); else pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p)); } --- 173,184 ---- { if (flags & TFF_DECL_SPECIFIERS) { ! pp_cxx_identifier (cxx_pp, "class"); if (DECL_NAME (p)) ! pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); } else if (DECL_NAME (p)) ! pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); else pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p)); } *************** dump_template_parameter (tree parm, int *** 234,240 **** if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE) { ! pp_string (cxx_pp, " = "); if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL) dump_type (a, flags & ~TFF_CHASE_TYPEDEF); else --- 187,195 ---- if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE) { ! pp_cxx_whitespace (cxx_pp); ! pp_equal (cxx_pp); ! pp_cxx_whitespace (cxx_pp); if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL) dump_type (a, flags & ~TFF_CHASE_TYPEDEF); else *************** dump_template_bindings (tree parms, tree *** 273,279 **** if (need_comma) pp_separate_with_comma (cxx_pp); dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER); ! pp_string (cxx_pp, " = "); if (arg) dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); else --- 228,236 ---- if (need_comma) pp_separate_with_comma (cxx_pp); dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER); ! pp_cxx_whitespace (cxx_pp); ! pp_equal (cxx_pp); ! pp_cxx_whitespace (cxx_pp); if (arg) dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); else *************** dump_type (tree t, int flags) *** 311,320 **** break; case IDENTIFIER_NODE: ! pp_tree_identifier (cxx_pp, t); break; ! case TREE_VEC: dump_type (BINFO_TYPE (t), flags); break; --- 268,277 ---- break; case IDENTIFIER_NODE: ! pp_cxx_tree_identifier (cxx_pp, t); break; ! case TREE_BINFO: dump_type (BINFO_TYPE (t), flags); break; *************** dump_type (tree t, int flags) *** 344,357 **** case BOOLEAN_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: - pp_base (cxx_pp)->padding = pp_none; pp_type_specifier_seq (cxx_pp, t); break; case TEMPLATE_TEMPLATE_PARM: /* For parameters inside template signature. */ if (TYPE_IDENTIFIER (t)) ! pp_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); else pp_cxx_canonical_template_parameter (cxx_pp, t); break; --- 301,313 ---- case BOOLEAN_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: pp_type_specifier_seq (cxx_pp, t); break; case TEMPLATE_TEMPLATE_PARM: /* For parameters inside template signature. */ if (TYPE_IDENTIFIER (t)) ! pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); else pp_cxx_canonical_template_parameter (cxx_pp, t); break; *************** dump_type (tree t, int flags) *** 359,376 **** case BOUND_TEMPLATE_TEMPLATE_PARM: { tree args = TYPE_TI_ARGS (t); ! dump_qualifiers (t, after); ! pp_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); ! pp_template_argument_list_start (cxx_pp); dump_template_argument_list (args, flags); ! pp_template_argument_list_end (cxx_pp); } break; case TEMPLATE_TYPE_PARM: ! dump_qualifiers (t, after); if (TYPE_IDENTIFIER (t)) ! pp_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); else pp_cxx_canonical_template_parameter (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t)); --- 315,332 ---- case BOUND_TEMPLATE_TEMPLATE_PARM: { tree args = TYPE_TI_ARGS (t); ! pp_cxx_cv_qualifier_seq (cxx_pp, t); ! pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); ! pp_cxx_begin_template_argument_list (cxx_pp); dump_template_argument_list (args, flags); ! pp_cxx_end_template_argument_list (cxx_pp); } break; case TEMPLATE_TYPE_PARM: ! pp_cxx_cv_qualifier_seq (cxx_pp, t); if (TYPE_IDENTIFIER (t)) ! pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); else pp_cxx_canonical_template_parameter (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t)); *************** dump_type (tree t, int flags) *** 391,412 **** break; } case TYPENAME_TYPE: ! dump_qualifiers (t, after); ! pp_string (cxx_pp, "typename "); dump_typename (t, flags); break; case UNBOUND_CLASS_TEMPLATE: dump_type (TYPE_CONTEXT (t), flags); ! pp_colon_colon (cxx_pp); ! pp_identifier (cxx_pp, "template "); dump_type (DECL_NAME (TYPE_NAME (t)), flags); break; case TYPEOF_TYPE: ! pp_string (cxx_pp, "__typeof ("); ! dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS); ! pp_right_paren (cxx_pp); break; default: --- 347,373 ---- break; } case TYPENAME_TYPE: ! pp_cxx_cv_qualifier_seq (cxx_pp, t); ! pp_cxx_identifier (cxx_pp, ! TYPENAME_IS_ENUM_P (t) ? "enum" ! : TYPENAME_IS_CLASS_P (t) ? "class" ! : "typename"); dump_typename (t, flags); break; case UNBOUND_CLASS_TEMPLATE: dump_type (TYPE_CONTEXT (t), flags); ! pp_cxx_colon_colon (cxx_pp); ! pp_cxx_identifier (cxx_pp, "template"); dump_type (DECL_NAME (TYPE_NAME (t)), flags); break; case TYPEOF_TYPE: ! pp_cxx_identifier (cxx_pp, "__typeof__"); ! pp_cxx_whitespace (cxx_pp); ! pp_cxx_left_paren (cxx_pp); ! dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS); ! pp_cxx_right_paren (cxx_pp); break; default: *************** dump_typename (tree t, int flags) *** 431,444 **** dump_typename (ctx, flags); else dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM); ! pp_colon_colon (cxx_pp); dump_decl (TYPENAME_TYPE_FULLNAME (t), flags); } /* Return the name of the supplied aggregate, or enumeral type. */ ! static const char * ! class_key_or_enum (tree t) { if (TREE_CODE (t) == ENUMERAL_TYPE) return "enum"; --- 392,405 ---- dump_typename (ctx, flags); else dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM); ! pp_cxx_colon_colon (cxx_pp); dump_decl (TYPENAME_TYPE_FULLNAME (t), flags); } /* Return the name of the supplied aggregate, or enumeral type. */ ! const char * ! class_key_or_enum_as_string (tree t) { if (TREE_CODE (t) == ENUMERAL_TYPE) return "enum"; *************** static void *** 457,473 **** dump_aggr_type (tree t, int flags) { tree name; ! const char *variety = class_key_or_enum (t); int typdef = 0; int tmplate = 0; ! dump_qualifiers (t, after); if (flags & TFF_CLASS_KEY_OR_ENUM) ! { ! pp_identifier (cxx_pp, variety); ! pp_space (cxx_pp); ! } if (flags & TFF_CHASE_TYPEDEF) t = TYPE_MAIN_VARIANT (t); --- 418,431 ---- dump_aggr_type (tree t, int flags) { tree name; ! const char *variety = class_key_or_enum_as_string (t); int typdef = 0; int tmplate = 0; ! pp_cxx_cv_qualifier_seq (cxx_pp, t); if (flags & TFF_CLASS_KEY_OR_ENUM) ! pp_cxx_identifier (cxx_pp, variety); if (flags & TFF_CHASE_TYPEDEF) t = TYPE_MAIN_VARIANT (t); *************** dump_aggr_type (tree t, int flags) *** 505,511 **** pp_printf (pp_base (cxx_pp), "", variety); } else ! pp_tree_identifier (cxx_pp, name); if (tmplate) dump_template_parms (TYPE_TEMPLATE_INFO (t), !CLASSTYPE_USE_TEMPLATE (t), --- 463,469 ---- pp_printf (pp_base (cxx_pp), "", variety); } else ! pp_cxx_tree_identifier (cxx_pp, name); if (tmplate) dump_template_parms (TYPE_TEMPLATE_INFO (t), !CLASSTYPE_USE_TEMPLATE (t), *************** dump_aggr_type (tree t, int flags) *** 521,536 **** deal with prefix and suffix. Arrays must also do this for DECL nodes, like int a[], and for things like ! int *[]&. ! ! Return indicates how you should pad an object name after this. I.e. you ! want to pad non-*, non-& cores, but not pad * or & types. */ ! static enum pad dump_type_prefix (tree t, int flags) { - enum pad padding = before; - if (TYPE_PTRMEMFUNC_P (t)) { t = TYPE_PTRMEMFUNC_FN_TYPE (t); --- 479,489 ---- deal with prefix and suffix. Arrays must also do this for DECL nodes, like int a[], and for things like ! int *[]&. */ ! static void dump_type_prefix (tree t, int flags) { if (TYPE_PTRMEMFUNC_P (t)) { t = TYPE_PTRMEMFUNC_FN_TYPE (t); *************** dump_type_prefix (tree t, int flags) *** 544,596 **** { tree sub = TREE_TYPE (t); ! padding = dump_type_prefix (sub, flags); if (TREE_CODE (sub) == ARRAY_TYPE) { ! pp_space (cxx_pp); ! pp_left_paren (cxx_pp); } pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]); ! padding = dump_qualifiers (t, before); } break; case OFFSET_TYPE: offset_type: ! padding = dump_type_prefix (TREE_TYPE (t), flags); if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ { ! if (padding != none) ! pp_space (cxx_pp); dump_type (TYPE_OFFSET_BASETYPE (t), flags); ! pp_colon_colon (cxx_pp); } ! pp_star (cxx_pp); ! padding = dump_qualifiers (t, none); break; /* Can only be reached through function pointer -- this would not be correct if FUNCTION_DECLs used it. */ case FUNCTION_TYPE: ! padding = dump_type_prefix (TREE_TYPE (t), flags); ! if (padding != none) ! pp_space (cxx_pp); ! pp_left_paren (cxx_pp); ! padding = none; break; case METHOD_TYPE: ! padding = dump_type_prefix (TREE_TYPE (t), flags); ! if (padding != none) ! pp_space (cxx_pp); ! pp_left_paren (cxx_pp); ! padding = none; dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags); ! pp_colon_colon (cxx_pp); break; case ARRAY_TYPE: ! padding = dump_type_prefix (TREE_TYPE (t), flags); break; case ENUMERAL_TYPE: --- 497,548 ---- { tree sub = TREE_TYPE (t); ! dump_type_prefix (sub, flags); if (TREE_CODE (sub) == ARRAY_TYPE) { ! pp_cxx_whitespace (cxx_pp); ! pp_cxx_left_paren (cxx_pp); } pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]); ! pp_base (cxx_pp)->padding = pp_before; ! pp_cxx_cv_qualifier_seq (cxx_pp, t); } break; case OFFSET_TYPE: offset_type: ! dump_type_prefix (TREE_TYPE (t), flags); if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ { ! pp_maybe_space (cxx_pp); ! if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) ! pp_cxx_left_paren (cxx_pp); dump_type (TYPE_OFFSET_BASETYPE (t), flags); ! pp_cxx_colon_colon (cxx_pp); } ! pp_cxx_star (cxx_pp); ! pp_cxx_cv_qualifier_seq (cxx_pp, t); ! pp_base (cxx_pp)->padding = pp_before; break; /* Can only be reached through function pointer -- this would not be correct if FUNCTION_DECLs used it. */ case FUNCTION_TYPE: ! dump_type_prefix (TREE_TYPE (t), flags); ! pp_maybe_space (cxx_pp); ! pp_cxx_left_paren (cxx_pp); break; case METHOD_TYPE: ! dump_type_prefix (TREE_TYPE (t), flags); ! pp_maybe_space (cxx_pp); ! pp_cxx_left_paren (cxx_pp); dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags); ! pp_cxx_colon_colon (cxx_pp); break; case ARRAY_TYPE: ! dump_type_prefix (TREE_TYPE (t), flags); break; case ENUMERAL_TYPE: *************** dump_type_prefix (tree t, int flags) *** 613,619 **** case VECTOR_TYPE: case TYPEOF_TYPE: dump_type (t, flags); ! padding = before; break; default: --- 565,571 ---- case VECTOR_TYPE: case TYPEOF_TYPE: dump_type (t, flags); ! pp_base (cxx_pp)->padding = pp_before; break; default: *************** dump_type_prefix (tree t, int flags) *** 623,629 **** pp_identifier (cxx_pp, ""); break; } - return padding; } /* Dump the suffix of type T, under control of FLAGS. This is the part --- 575,580 ---- *************** dump_type_suffix (tree t, int flags) *** 641,647 **** case REFERENCE_TYPE: case OFFSET_TYPE: if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) ! pp_right_paren (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); break; --- 592,598 ---- case REFERENCE_TYPE: case OFFSET_TYPE: if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) ! pp_cxx_right_paren (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); break; *************** dump_type_suffix (tree t, int flags) *** 650,656 **** case METHOD_TYPE: { tree arg; ! pp_right_paren (cxx_pp); arg = TYPE_ARG_TYPES (t); if (TREE_CODE (t) == METHOD_TYPE) arg = TREE_CHAIN (arg); --- 601,607 ---- case METHOD_TYPE: { tree arg; ! pp_cxx_right_paren (cxx_pp); arg = TYPE_ARG_TYPES (t); if (TREE_CODE (t) == METHOD_TYPE) arg = TREE_CHAIN (arg); *************** dump_type_suffix (tree t, int flags) *** 660,674 **** dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS); if (TREE_CODE (t) == METHOD_TYPE) ! dump_qualifiers ! (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before); dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); dump_type_suffix (TREE_TYPE (t), flags); break; } case ARRAY_TYPE: ! pp_left_bracket (cxx_pp); if (TYPE_DOMAIN (t)) { if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0)) --- 611,628 ---- dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS); if (TREE_CODE (t) == METHOD_TYPE) ! pp_cxx_cv_qualifier_seq ! (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); ! else ! pp_cxx_cv_qualifier_seq(cxx_pp, t); dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); dump_type_suffix (TREE_TYPE (t), flags); break; } case ARRAY_TYPE: ! pp_maybe_space (cxx_pp); ! pp_cxx_left_bracket (cxx_pp); if (TYPE_DOMAIN (t)) { if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0)) *************** dump_type_suffix (tree t, int flags) *** 683,689 **** integer_one_node)), flags & ~TFF_EXPR_IN_PARENS); } ! pp_right_bracket (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); break; --- 637,643 ---- integer_one_node)), flags & ~TFF_EXPR_IN_PARENS); } ! pp_cxx_right_bracket (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); break; *************** dump_global_iord (tree t) *** 727,733 **** else if (DECL_GLOBAL_DTOR_P (t)) p = "destructors"; else ! abort (); pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename); } --- 681,687 ---- else if (DECL_GLOBAL_DTOR_P (t)) p = "destructors"; else ! gcc_unreachable (); pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename); } *************** dump_simple_decl (tree t, tree type, int *** 737,744 **** { if (flags & TFF_DECL_SPECIFIERS) { ! if (dump_type_prefix (type, flags) != none) ! pp_space (cxx_pp); } if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX) dump_scope (CP_DECL_CONTEXT (t), flags); --- 691,698 ---- { if (flags & TFF_DECL_SPECIFIERS) { ! dump_type_prefix (type, flags); ! pp_maybe_space (cxx_pp); } if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX) dump_scope (CP_DECL_CONTEXT (t), flags); *************** dump_decl (tree t, int flags) *** 761,781 **** switch (TREE_CODE (t)) { case TYPE_DECL: ! { ! /* Don't say 'typedef class A' */ ! if (DECL_ARTIFICIAL (t)) ! { ! if ((flags & TFF_DECL_SPECIFIERS) ! && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM) ! /* Say `class T' not just `T'. */ ! pp_string (cxx_pp, "class "); ! ! dump_type (TREE_TYPE (t), flags); ! break; ! } ! } if (flags & TFF_DECL_SPECIFIERS) ! pp_string (cxx_pp, "typedef "); dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags); --- 715,733 ---- switch (TREE_CODE (t)) { case TYPE_DECL: ! /* Don't say 'typedef class A' */ ! if (DECL_ARTIFICIAL (t)) ! { ! if ((flags & TFF_DECL_SPECIFIERS) ! && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM) ! /* Say `class T' not just `T'. */ ! pp_cxx_identifier (cxx_pp, "class"); ! ! dump_type (TREE_TYPE (t), flags); ! break; ! } if (flags & TFF_DECL_SPECIFIERS) ! pp_cxx_identifier (cxx_pp, "typedef"); dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags); *************** dump_decl (tree t, int flags) *** 785,791 **** if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t))) { pp_string (cxx_pp, "vtable for "); ! my_friendly_assert (TYPE_P (DECL_CONTEXT (t)), 20010720); dump_type (DECL_CONTEXT (t), flags); break; } --- 737,743 ---- if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t))) { pp_string (cxx_pp, "vtable for "); ! gcc_assert (TYPE_P (DECL_CONTEXT (t))); dump_type (DECL_CONTEXT (t), flags); break; } *************** dump_decl (tree t, int flags) *** 810,816 **** if (DECL_NAME (t) == NULL_TREE) pp_identifier (cxx_pp, ""); else ! pp_tree_identifier (cxx_pp, DECL_NAME (t)); } break; --- 762,768 ---- if (DECL_NAME (t) == NULL_TREE) pp_identifier (cxx_pp, ""); else ! pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); } break; *************** dump_decl (tree t, int flags) *** 820,828 **** case ARRAY_REF: dump_decl (TREE_OPERAND (t, 0), flags); ! pp_left_bracket (cxx_pp); dump_decl (TREE_OPERAND (t, 1), flags); ! pp_right_bracket (cxx_pp); break; /* So that we can do dump_decl on an aggr type. */ --- 772,780 ---- case ARRAY_REF: dump_decl (TREE_OPERAND (t, 0), flags); ! pp_cxx_left_bracket (cxx_pp); dump_decl (TREE_OPERAND (t, 1), flags); ! pp_cxx_right_bracket (cxx_pp); break; /* So that we can do dump_decl on an aggr type. */ *************** dump_decl (tree t, int flags) *** 835,846 **** case BIT_NOT_EXPR: /* This is a pseudo destructor call which has not been folded into a PSEUDO_DTOR_EXPR yet. */ ! pp_complement (cxx_pp); dump_type (TREE_OPERAND (t, 0), flags); break; case TYPE_EXPR: ! abort (); break; /* These special cases are duplicated here so that other functions --- 787,798 ---- case BIT_NOT_EXPR: /* This is a pseudo destructor call which has not been folded into a PSEUDO_DTOR_EXPR yet. */ ! pp_cxx_complement (cxx_pp); dump_type (TREE_OPERAND (t, 0), flags); break; case TYPE_EXPR: ! gcc_unreachable (); break; /* These special cases are duplicated here so that other functions *************** dump_decl (tree t, int flags) *** 848,860 **** case IDENTIFIER_NODE: if (IDENTIFIER_TYPENAME_P (t)) { ! pp_string (cxx_pp, "operator "); /* Not exactly IDENTIFIER_TYPE_VALUE. */ dump_type (TREE_TYPE (t), flags); break; } else ! pp_tree_identifier (cxx_pp, t); break; case OVERLOAD: --- 800,812 ---- case IDENTIFIER_NODE: if (IDENTIFIER_TYPENAME_P (t)) { ! pp_cxx_identifier (cxx_pp, "operator"); /* Not exactly IDENTIFIER_TYPE_VALUE. */ dump_type (TREE_TYPE (t), flags); break; } else ! pp_cxx_tree_identifier (cxx_pp, t); break; case OVERLOAD: *************** dump_decl (tree t, int flags) *** 864,875 **** if (DECL_CLASS_SCOPE_P (t)) { dump_type (DECL_CONTEXT (t), flags); ! pp_colon_colon (cxx_pp); } else if (DECL_CONTEXT (t)) { dump_decl (DECL_CONTEXT (t), flags); ! pp_colon_colon (cxx_pp); } dump_decl (DECL_NAME (t), flags); break; --- 816,827 ---- if (DECL_CLASS_SCOPE_P (t)) { dump_type (DECL_CONTEXT (t), flags); ! pp_cxx_colon_colon (cxx_pp); } else if (DECL_CONTEXT (t)) { dump_decl (DECL_CONTEXT (t), flags); ! pp_cxx_colon_colon (cxx_pp); } dump_decl (DECL_NAME (t), flags); break; *************** dump_decl (tree t, int flags) *** 881,890 **** /* Fall through. */ case FUNCTION_DECL: ! if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) dump_global_iord (t); - else if (! DECL_LANG_SPECIFIC (t)) - pp_identifier (cxx_pp, ""); else dump_function_decl (t, flags); break; --- 833,842 ---- /* Fall through. */ case FUNCTION_DECL: ! if (! DECL_LANG_SPECIFIC (t)) ! pp_identifier (cxx_pp, ""); ! else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) dump_global_iord (t); else dump_function_decl (t, flags); break; *************** dump_decl (tree t, int flags) *** 900,914 **** if (is_overloaded_fn (name)) name = DECL_NAME (get_first_fn (name)); dump_decl (name, flags); ! pp_template_argument_list_start (cxx_pp); if (TREE_OPERAND (t, 1)) dump_template_argument_list (TREE_OPERAND (t, 1), flags); ! pp_template_argument_list_end (cxx_pp); } break; case LABEL_DECL: ! pp_tree_identifier (cxx_pp, DECL_NAME (t)); break; case CONST_DECL: --- 852,866 ---- if (is_overloaded_fn (name)) name = DECL_NAME (get_first_fn (name)); dump_decl (name, flags); ! pp_cxx_begin_template_argument_list (cxx_pp); if (TREE_OPERAND (t, 1)) dump_template_argument_list (TREE_OPERAND (t, 1), flags); ! pp_cxx_end_template_argument_list (cxx_pp); } break; case LABEL_DECL: ! pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); break; case CONST_DECL: *************** dump_decl (tree t, int flags) *** 925,933 **** break; case USING_DECL: ! pp_string (cxx_pp, "using "); dump_type (DECL_INITIAL (t), flags); ! pp_colon_colon (cxx_pp); dump_decl (DECL_NAME (t), flags); break; --- 877,885 ---- break; case USING_DECL: ! pp_cxx_identifier (cxx_pp, "using"); dump_type (DECL_INITIAL (t), flags); ! pp_cxx_colon_colon (cxx_pp); dump_decl (DECL_NAME (t), flags); break; *************** dump_decl (tree t, int flags) *** 948,954 **** default: pp_unsupported_tree (cxx_pp, t); ! /* Fallthrough to error. */ case ERROR_MARK: pp_identifier (cxx_pp, ""); --- 900,906 ---- default: pp_unsupported_tree (cxx_pp, t); ! /* Fall through to error. */ case ERROR_MARK: pp_identifier (cxx_pp, ""); *************** dump_template_decl (tree t, int flags) *** 975,981 **** tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms); int len = TREE_VEC_LENGTH (inner_parms); ! pp_string (cxx_pp, "template<"); /* If we've shown the template prefix, we'd better show the parameters' and decl's type too. */ --- 927,934 ---- tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms); int len = TREE_VEC_LENGTH (inner_parms); ! pp_cxx_identifier (cxx_pp, "template"); ! pp_cxx_begin_template_argument_list (cxx_pp); /* If we've shown the template prefix, we'd better show the parameters' and decl's type too. */ *************** dump_template_decl (tree t, int flags) *** 987,1000 **** pp_separate_with_comma (cxx_pp); dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags); } ! pp_template_argument_list_end (cxx_pp); ! pp_space (cxx_pp); } nreverse(orig_parms); if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) /* Say `template class TT' not just `template TT'. */ ! pp_string (cxx_pp, "class "); } if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) --- 940,953 ---- pp_separate_with_comma (cxx_pp); dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags); } ! pp_cxx_end_template_argument_list (cxx_pp); ! pp_cxx_whitespace (cxx_pp); } nreverse(orig_parms); if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) /* Say `template class TT' not just `template TT'. */ ! pp_cxx_identifier (cxx_pp, "class"); } if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) *************** dump_template_decl (tree t, int flags) *** 1003,1022 **** | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0))); else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL) dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME); - else if (TREE_TYPE (t) == NULL_TREE) - abort (); else - switch (NEXT_CODE (t)) { ! case METHOD_TYPE: ! case FUNCTION_TYPE: ! dump_function_decl (t, flags | TFF_TEMPLATE_NAME); ! break; ! default: ! /* 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)); } } --- 956,977 ---- | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0))); else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL) dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME); else { ! gcc_assert (TREE_TYPE (t)); ! switch (NEXT_CODE (t)) ! { ! case METHOD_TYPE: ! case FUNCTION_TYPE: ! dump_function_decl (t, flags | TFF_TEMPLATE_NAME); ! break; ! default: ! /* 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)); ! } } } *************** dump_function_decl (tree t, int flags) *** 1064,1088 **** if (!(flags & TFF_DECL_SPECIFIERS)) /* OK */; else if (DECL_STATIC_FUNCTION_P (t)) ! pp_identifier (cxx_pp, "static "); else if (DECL_VIRTUAL_P (t)) ! pp_identifier (cxx_pp, "virtual "); /* Print the return type? */ if (show_return) show_return = !DECL_CONV_FN_P (t) && !DECL_CONSTRUCTOR_P (t) && !DECL_DESTRUCTOR_P (t); if (show_return) ! { ! dump_type_prefix (TREE_TYPE (fntype), flags); ! pp_space (cxx_pp); ! } /* Print the function name. */ if (cname) { dump_type (cname, flags); ! pp_colon_colon (cxx_pp); } else dump_scope (CP_DECL_CONTEXT (t), flags); --- 1019,1040 ---- if (!(flags & TFF_DECL_SPECIFIERS)) /* OK */; else if (DECL_STATIC_FUNCTION_P (t)) ! pp_cxx_identifier (cxx_pp, "static"); else if (DECL_VIRTUAL_P (t)) ! pp_cxx_identifier (cxx_pp, "virtual"); /* Print the return type? */ if (show_return) show_return = !DECL_CONV_FN_P (t) && !DECL_CONSTRUCTOR_P (t) && !DECL_DESTRUCTOR_P (t); if (show_return) ! dump_type_prefix (TREE_TYPE (fntype), flags); /* Print the function name. */ if (cname) { dump_type (cname, flags); ! pp_cxx_colon_colon (cxx_pp); } else dump_scope (CP_DECL_CONTEXT (t), flags); *************** dump_function_decl (tree t, int flags) *** 1094,1104 **** dump_parameters (parmtypes, flags); if (TREE_CODE (fntype) == METHOD_TYPE) ! dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), ! before); if (flags & TFF_EXCEPTION_SPECIFICATION) ! dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags); if (show_return) dump_type_suffix (TREE_TYPE (fntype), flags); --- 1046,1062 ---- dump_parameters (parmtypes, flags); if (TREE_CODE (fntype) == METHOD_TYPE) ! { ! pp_base (cxx_pp)->padding = pp_before; ! pp_cxx_cv_qualifier_seq ! (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)))); ! } if (flags & TFF_EXCEPTION_SPECIFICATION) ! { ! pp_base (cxx_pp)->padding = pp_before; ! dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags); ! } if (show_return) dump_type_suffix (TREE_TYPE (fntype), flags); *************** dump_function_decl (tree t, int flags) *** 1107,1115 **** /* If T is a template instantiation, dump the parameter binding. */ if (template_parms != NULL_TREE && template_args != NULL_TREE) { ! pp_string (cxx_pp, " [with "); dump_template_bindings (template_parms, template_args); ! pp_right_bracket (cxx_pp); } } --- 1065,1076 ---- /* If T is a template instantiation, dump the parameter binding. */ if (template_parms != NULL_TREE && template_args != NULL_TREE) { ! pp_cxx_whitespace (cxx_pp); ! pp_cxx_left_bracket (cxx_pp); ! pp_cxx_identifier (cxx_pp, "with"); ! pp_cxx_whitespace (cxx_pp); dump_template_bindings (template_parms, template_args); ! pp_cxx_right_bracket (cxx_pp); } } *************** dump_parameters (tree parmtypes, int fla *** 1122,1128 **** { int first; ! pp_left_paren (cxx_pp); for (first = 1; parmtypes != void_list_node; parmtypes = TREE_CHAIN (parmtypes)) --- 1083,1089 ---- { int first; ! pp_cxx_left_paren (cxx_pp); for (first = 1; parmtypes != void_list_node; parmtypes = TREE_CHAIN (parmtypes)) *************** dump_parameters (tree parmtypes, int fla *** 1132,1150 **** first = 0; if (!parmtypes) { ! pp_identifier (cxx_pp, "..."); break; } dump_type (TREE_VALUE (parmtypes), flags); if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes)) { ! pp_string (cxx_pp, " = "); dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS); } } ! pp_right_paren (cxx_pp); } /* Print an exception specification. T is the exception specification. */ --- 1093,1113 ---- first = 0; if (!parmtypes) { ! pp_cxx_identifier (cxx_pp, "..."); break; } dump_type (TREE_VALUE (parmtypes), flags); if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes)) { ! pp_cxx_whitespace (cxx_pp); ! pp_equal (cxx_pp); ! pp_cxx_whitespace (cxx_pp); dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS); } } ! pp_cxx_right_paren (cxx_pp); } /* Print an exception specification. T is the exception specification. */ *************** dump_exception_spec (tree t, int flags) *** 1154,1160 **** { if (t) { ! pp_string (cxx_pp, " throw ("); if (TREE_VALUE (t) != NULL_TREE) while (1) { --- 1117,1125 ---- { if (t) { ! pp_cxx_identifier (cxx_pp, "throw"); ! pp_cxx_whitespace (cxx_pp); ! pp_cxx_left_paren (cxx_pp); if (TREE_VALUE (t) != NULL_TREE) while (1) { *************** dump_exception_spec (tree t, int flags) *** 1164,1170 **** break; pp_separate_with_comma (cxx_pp); } ! pp_right_paren (cxx_pp); } } --- 1129,1135 ---- break; pp_separate_with_comma (cxx_pp); } ! pp_cxx_right_paren (cxx_pp); } } *************** dump_function_name (tree t, int flags) *** 1176,1181 **** --- 1141,1157 ---- { tree name = DECL_NAME (t); + /* We can get here with a decl that was synthesized by language- + independent machinery (e.g. coverage.c) in which case it won't + have a lang_specific structure attached and DECL_CONSTRUCTOR_P + will crash. In this case it is safe just to print out the + literal name. */ + if (!DECL_LANG_SPECIFIC (t)) + { + pp_cxx_tree_identifier (cxx_pp, name); + return; + } + if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); *************** dump_function_name (tree t, int flags) *** 1186,1192 **** if (DECL_DESTRUCTOR_P (t)) { ! pp_complement (cxx_pp); dump_decl (name, TFF_PLAIN_IDENTIFIER); } else if (DECL_CONV_FN_P (t)) --- 1162,1168 ---- if (DECL_DESTRUCTOR_P (t)) { ! pp_cxx_complement (cxx_pp); dump_decl (name, TFF_PLAIN_IDENTIFIER); } else if (DECL_CONV_FN_P (t)) *************** dump_function_name (tree t, int flags) *** 1197,1211 **** declarations, both will have the same name, yet the types will be different, hence the TREE_TYPE field of the first name will be clobbered by the second. */ ! pp_string (cxx_pp, "operator "); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } else if (IDENTIFIER_OPNAME_P (name)) ! pp_tree_identifier (cxx_pp, name); else dump_decl (name, flags); ! if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t) && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) && (DECL_TEMPLATE_SPECIALIZATION (t) || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL --- 1173,1187 ---- declarations, both will have the same name, yet the types will be different, hence the TREE_TYPE field of the first name will be clobbered by the second. */ ! pp_cxx_identifier (cxx_pp, "operator"); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } else if (IDENTIFIER_OPNAME_P (name)) ! pp_cxx_tree_identifier (cxx_pp, name); else dump_decl (name, flags); ! if (DECL_TEMPLATE_INFO (t) && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) && (DECL_TEMPLATE_SPECIALIZATION (t) || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL *************** dump_template_parms (tree info, int prim *** 1228,1234 **** if (primary && flags & TFF_TEMPLATE_NAME) return; flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME); ! pp_template_argument_list_start (cxx_pp); /* Be careful only to print things when we have them, so as not to crash producing error messages. */ --- 1204,1210 ---- if (primary && flags & TFF_TEMPLATE_NAME) return; flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME); ! pp_cxx_begin_template_argument_list (cxx_pp); /* Be careful only to print things when we have them, so as not to crash producing error messages. */ *************** dump_template_parms (tree info, int prim *** 1273,1279 **** dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS); } } ! pp_template_argument_list_end (cxx_pp); } /* Print out a list of initializers (subr of dump_expr). */ --- 1249,1255 ---- dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS); } } ! pp_cxx_end_template_argument_list (cxx_pp); } /* Print out a list of initializers (subr of dump_expr). */ *************** dump_expr (tree t, int flags) *** 1312,1357 **** dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS); break; - case INTEGER_CST: case STRING_CST: case REAL_CST: pp_c_constant (pp_c_base (cxx_pp), t); break; case THROW_EXPR: ! pp_identifier (cxx_pp, "throw"); dump_expr (TREE_OPERAND (t, 0), flags); break; case PTRMEM_CST: pp_ampersand (cxx_pp); dump_type (PTRMEM_CST_CLASS (t), flags); ! pp_colon_colon (cxx_pp); ! pp_tree_identifier (cxx_pp, DECL_NAME (PTRMEM_CST_MEMBER (t))); break; case COMPOUND_EXPR: ! pp_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); pp_separate_with_comma (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_right_paren (cxx_pp); break; case COND_EXPR: ! pp_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); pp_string (cxx_pp, " ? "); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); pp_string (cxx_pp, " : "); dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS); ! pp_right_paren (cxx_pp); break; case SAVE_EXPR: if (TREE_HAS_CONSTRUCTOR (t)) { ! pp_string (cxx_pp, "new "); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } else --- 1288,1341 ---- dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS); break; case STRING_CST: + if (PAREN_STRING_LITERAL_P (t)) + pp_cxx_left_paren (cxx_pp); + pp_c_constant (pp_c_base (cxx_pp), t); + if (PAREN_STRING_LITERAL_P (t)) + pp_cxx_right_paren (cxx_pp); + break; + + case INTEGER_CST: case REAL_CST: pp_c_constant (pp_c_base (cxx_pp), t); break; case THROW_EXPR: ! pp_cxx_identifier (cxx_pp, "throw"); dump_expr (TREE_OPERAND (t, 0), flags); break; case PTRMEM_CST: pp_ampersand (cxx_pp); dump_type (PTRMEM_CST_CLASS (t), flags); ! pp_cxx_colon_colon (cxx_pp); ! pp_cxx_tree_identifier (cxx_pp, DECL_NAME (PTRMEM_CST_MEMBER (t))); break; case COMPOUND_EXPR: ! pp_cxx_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); pp_separate_with_comma (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_right_paren (cxx_pp); break; case COND_EXPR: ! pp_cxx_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); pp_string (cxx_pp, " ? "); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); pp_string (cxx_pp, " : "); dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_right_paren (cxx_pp); break; case SAVE_EXPR: if (TREE_HAS_CONSTRUCTOR (t)) { ! pp_cxx_identifier (cxx_pp, "new"); ! pp_cxx_whitespace (cxx_pp); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } else *************** dump_expr (tree t, int flags) *** 1368,1384 **** if (fn && TREE_CODE (fn) == FUNCTION_DECL) { if (DECL_CONSTRUCTOR_P (fn)) ! pp_tree_identifier (cxx_pp, TYPE_IDENTIFIER (TREE_TYPE (t))); else dump_decl (fn, 0); } else dump_expr (TREE_OPERAND (t, 0), 0); } ! pp_left_paren (cxx_pp); if (TREE_OPERAND (t, 1)) dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); ! pp_right_paren (cxx_pp); break; case CALL_EXPR: --- 1352,1368 ---- if (fn && TREE_CODE (fn) == FUNCTION_DECL) { if (DECL_CONSTRUCTOR_P (fn)) ! dump_type (DECL_CONTEXT (fn), flags); else dump_decl (fn, 0); } else dump_expr (TREE_OPERAND (t, 0), 0); } ! pp_cxx_left_paren (cxx_pp); if (TREE_OPERAND (t, 1)) dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); ! pp_cxx_right_paren (cxx_pp); break; case CALL_EXPR: *************** dump_expr (tree t, int flags) *** 1406,1414 **** args = TREE_CHAIN (args); } dump_expr (fn, flags | TFF_EXPR_IN_PARENS); ! pp_left_paren (cxx_pp); dump_expr_list (args, flags); ! pp_right_paren (cxx_pp); } break; --- 1390,1398 ---- args = TREE_CHAIN (args); } dump_expr (fn, flags | TFF_EXPR_IN_PARENS); ! pp_cxx_left_paren (cxx_pp); dump_expr_list (args, flags); ! pp_cxx_right_paren (cxx_pp); } break; *************** dump_expr (tree t, int flags) *** 1417,1440 **** tree type = TREE_OPERAND (t, 1); tree init = TREE_OPERAND (t, 2); if (NEW_EXPR_USE_GLOBAL (t)) ! pp_colon_colon (cxx_pp); ! pp_string (cxx_pp, "new "); if (TREE_OPERAND (t, 0)) { ! pp_left_paren (cxx_pp); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_string (cxx_pp, ") "); } if (TREE_CODE (type) == ARRAY_REF) type = build_cplus_array_type (TREE_OPERAND (type, 0), ! build_index_type (fold (build (MINUS_EXPR, integer_type_node, ! TREE_OPERAND (type, 1), ! integer_one_node)))); dump_type (type, flags); if (init) { ! pp_left_paren (cxx_pp); if (TREE_CODE (init) == TREE_LIST) dump_expr_list (init, flags); else if (init == void_zero_node) --- 1401,1425 ---- tree type = TREE_OPERAND (t, 1); tree init = TREE_OPERAND (t, 2); if (NEW_EXPR_USE_GLOBAL (t)) ! pp_cxx_colon_colon (cxx_pp); ! pp_cxx_identifier (cxx_pp, "new"); if (TREE_OPERAND (t, 0)) { ! pp_cxx_left_paren (cxx_pp); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_cxx_right_paren (cxx_pp); ! pp_cxx_whitespace (cxx_pp); } if (TREE_CODE (type) == ARRAY_REF) type = build_cplus_array_type (TREE_OPERAND (type, 0), ! build_index_type (fold (build2 (MINUS_EXPR, integer_type_node, ! TREE_OPERAND (type, 1), ! integer_one_node)))); dump_type (type, flags); if (init) { ! pp_cxx_left_paren (cxx_pp); if (TREE_CODE (init) == TREE_LIST) dump_expr_list (init, flags); else if (init == void_zero_node) *************** dump_expr (tree t, int flags) *** 1443,1449 **** ; else dump_expr (init, flags); ! pp_right_paren (cxx_pp); } } break; --- 1428,1434 ---- ; else dump_expr (init, flags); ! pp_cxx_right_paren (cxx_pp); } } break; *************** dump_expr (tree t, int flags) *** 1507,1519 **** || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")) { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_arrow (cxx_pp); } } else { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_dot (cxx_pp); } dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS); } --- 1492,1504 ---- || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")) { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_cxx_arrow (cxx_pp); } } else { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_cxx_dot (cxx_pp); } dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS); } *************** dump_expr (tree t, int flags) *** 1521,1537 **** case ARRAY_REF: dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_left_bracket (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_right_bracket (cxx_pp); break; case CONVERT_EXPR: if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t))) { ! pp_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_right_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags); } else --- 1506,1522 ---- case ARRAY_REF: dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_left_bracket (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_right_bracket (cxx_pp); break; case CONVERT_EXPR: if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t))) { ! pp_cxx_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_cxx_right_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags); } else *************** dump_expr (tree t, int flags) *** 1555,1565 **** if (TREE_HAS_CONSTRUCTOR (t)) { t = TREE_OPERAND (t, 0); ! my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_left_paren (cxx_pp); dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); ! pp_right_paren (cxx_pp); } else { --- 1540,1550 ---- if (TREE_HAS_CONSTRUCTOR (t)) { t = TREE_OPERAND (t, 0); ! gcc_assert (TREE_CODE (t) == CALL_EXPR); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_left_paren (cxx_pp); dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); ! pp_cxx_right_paren (cxx_pp); } else { *************** dump_expr (tree t, int flags) *** 1582,1591 **** case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: ! pp_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_identifier (cxx_pp, operator_name_info[(int)TREE_CODE (t)].name); ! pp_right_paren (cxx_pp); break; case NON_LVALUE_EXPR: --- 1567,1576 ---- case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: ! pp_cxx_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_identifier (cxx_pp, operator_name_info[(int)TREE_CODE (t)].name); ! pp_cxx_right_paren (cxx_pp); break; case NON_LVALUE_EXPR: *************** dump_expr (tree t, int flags) *** 1602,1612 **** if (TREE_CODE (next) == FUNCTION_TYPE) { if (flags & TFF_EXPR_IN_PARENS) ! pp_left_paren (cxx_pp); ! pp_star (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_right_paren (cxx_pp); break; } /* Else fall through. */ --- 1587,1597 ---- if (TREE_CODE (next) == FUNCTION_TYPE) { if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_star (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_right_paren (cxx_pp); break; } /* Else fall through. */ *************** dump_expr (tree t, int flags) *** 1623,1645 **** /* It is a cast, but we cannot tell whether it is a reinterpret or static cast. Use the C style notation. */ if (flags & TFF_EXPR_IN_PARENS) ! pp_left_paren (cxx_pp); ! pp_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_right_paren (cxx_pp); dump_expr (op, flags | TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_right_paren (cxx_pp); } else dump_expr (op, flags); break; } - case EXPR_WITH_FILE_LOCATION: - dump_expr (EXPR_WFL_NODE (t), flags); - break; - case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) { --- 1608,1626 ---- /* It is a cast, but we cannot tell whether it is a reinterpret or static cast. Use the C style notation. */ if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_cxx_right_paren (cxx_pp); dump_expr (op, flags | TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_right_paren (cxx_pp); } else dump_expr (op, flags); break; } case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) { *************** dump_expr (tree t, int flags) *** 1648,1658 **** if (integer_zerop (idx)) { /* A NULL pointer-to-member constant. */ ! pp_left_paren (cxx_pp); ! pp_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_right_paren (cxx_pp); ! pp_string (cxx_pp, ")0)"); break; } else if (host_integerp (idx, 0)) --- 1629,1640 ---- if (integer_zerop (idx)) { /* A NULL pointer-to-member constant. */ ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_cxx_right_paren (cxx_pp); ! pp_character (cxx_pp, '0'); ! pp_cxx_right_paren (cxx_pp); break; } else if (host_integerp (idx, 0)) *************** dump_expr (tree t, int flags) *** 1662,1668 **** t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); t = TYPE_METHOD_BASETYPE (t); ! virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t)); n = tree_low_cst (idx, 0); --- 1644,1650 ---- t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); t = TYPE_METHOD_BASETYPE (t); ! virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t))); n = tree_low_cst (idx, 0); *************** dump_expr (tree t, int flags) *** 1686,1699 **** if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t)) { dump_type (TREE_TYPE (t), 0); ! pp_left_paren (cxx_pp); ! pp_right_paren (cxx_pp); } else { ! pp_left_brace (cxx_pp); dump_expr_list (CONSTRUCTOR_ELTS (t), flags); ! pp_right_brace (cxx_pp); } break; --- 1668,1681 ---- if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t)) { dump_type (TREE_TYPE (t), 0); ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_right_paren (cxx_pp); } else { ! pp_cxx_left_brace (cxx_pp); dump_expr_list (CONSTRUCTOR_ELTS (t), flags); ! pp_cxx_right_brace (cxx_pp); } break; *************** dump_expr (tree t, int flags) *** 1718,1729 **** if (TREE_CODE (ob) == INDIRECT_REF) { dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS); ! pp_string (cxx_pp, "->*"); } else { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_string (cxx_pp, ".*"); } dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); } --- 1700,1713 ---- if (TREE_CODE (ob) == INDIRECT_REF) { dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_arrow (cxx_pp); ! pp_cxx_star (cxx_pp); } else { dump_expr (ob, flags | TFF_EXPR_IN_PARENS); ! pp_cxx_dot (cxx_pp); ! pp_cxx_star (cxx_pp); } dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); } *************** dump_expr (tree t, int flags) *** 1743,1805 **** || TREE_CHAIN (TREE_OPERAND (t, 0))) { dump_type (TREE_TYPE (t), flags); ! pp_left_paren (cxx_pp); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_right_paren (cxx_pp); } else { ! pp_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_string (cxx_pp, ")("); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_right_paren (cxx_pp); } break; case STATIC_CAST_EXPR: ! pp_string (cxx_pp, "static_cast<"); goto cast; case REINTERPRET_CAST_EXPR: ! pp_string (cxx_pp, "reinterpret_cast<"); goto cast; case CONST_CAST_EXPR: ! pp_string (cxx_pp, "const_cast<"); goto cast; case DYNAMIC_CAST_EXPR: ! pp_string (cxx_pp, "dynamic_cast<"); cast: dump_type (TREE_TYPE (t), flags); ! pp_string (cxx_pp, ">("); dump_expr (TREE_OPERAND (t, 0), flags); ! pp_right_paren (cxx_pp); break; case ARROW_EXPR: dump_expr (TREE_OPERAND (t, 0), flags); ! pp_arrow (cxx_pp); break; case SIZEOF_EXPR: case ALIGNOF_EXPR: if (TREE_CODE (t) == SIZEOF_EXPR) ! pp_string (cxx_pp, "sizeof ("); else { ! my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0); ! pp_string (cxx_pp, "__alignof__ ("); } if (TYPE_P (TREE_OPERAND (t, 0))) dump_type (TREE_OPERAND (t, 0), flags); else dump_expr (TREE_OPERAND (t, 0), flags); ! pp_right_paren (cxx_pp); break; case REALPART_EXPR: case IMAGPART_EXPR: ! pp_identifier (cxx_pp, operator_name_info[TREE_CODE (t)].name); ! pp_space (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags); break; --- 1727,1794 ---- || TREE_CHAIN (TREE_OPERAND (t, 0))) { dump_type (TREE_TYPE (t), flags); ! pp_cxx_left_paren (cxx_pp); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_cxx_right_paren (cxx_pp); } else { ! pp_cxx_left_paren (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_cxx_right_paren (cxx_pp); ! pp_cxx_left_paren (cxx_pp); dump_expr_list (TREE_OPERAND (t, 0), flags); ! pp_cxx_right_paren (cxx_pp); } break; case STATIC_CAST_EXPR: ! pp_cxx_identifier (cxx_pp, "static_cast"); goto cast; case REINTERPRET_CAST_EXPR: ! pp_cxx_identifier (cxx_pp, "reinterpret_cast"); goto cast; case CONST_CAST_EXPR: ! pp_cxx_identifier (cxx_pp, "const_cast"); goto cast; case DYNAMIC_CAST_EXPR: ! pp_cxx_identifier (cxx_pp, "dynamic_cast"); cast: + pp_cxx_begin_template_argument_list (cxx_pp); dump_type (TREE_TYPE (t), flags); ! pp_cxx_end_template_argument_list (cxx_pp); ! pp_cxx_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags); ! pp_cxx_right_paren (cxx_pp); break; case ARROW_EXPR: dump_expr (TREE_OPERAND (t, 0), flags); ! pp_cxx_arrow (cxx_pp); break; case SIZEOF_EXPR: case ALIGNOF_EXPR: if (TREE_CODE (t) == SIZEOF_EXPR) ! pp_cxx_identifier (cxx_pp, "sizeof"); else { ! gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR); ! pp_cxx_identifier (cxx_pp, "__alignof__"); } + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); if (TYPE_P (TREE_OPERAND (t, 0))) dump_type (TREE_OPERAND (t, 0), flags); else dump_expr (TREE_OPERAND (t, 0), flags); ! pp_cxx_right_paren (cxx_pp); break; case REALPART_EXPR: case IMAGPART_EXPR: ! pp_cxx_identifier (cxx_pp, operator_name_info[TREE_CODE (t)].name); ! pp_cxx_whitespace (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags); break; *************** dump_expr (tree t, int flags) *** 1815,1824 **** case PSEUDO_DTOR_EXPR: dump_expr (TREE_OPERAND (t, 2), flags); ! pp_dot (cxx_pp); dump_type (TREE_OPERAND (t, 0), flags); ! pp_colon_colon (cxx_pp); ! pp_complement (cxx_pp); dump_type (TREE_OPERAND (t, 1), flags); break; --- 1804,1813 ---- case PSEUDO_DTOR_EXPR: dump_expr (TREE_OPERAND (t, 2), flags); ! pp_cxx_dot (cxx_pp); dump_type (TREE_OPERAND (t, 0), flags); ! pp_cxx_colon_colon (cxx_pp); ! pp_cxx_complement (cxx_pp); dump_type (TREE_OPERAND (t, 1), flags); break; *************** dump_expr (tree t, int flags) *** 1826,1847 **** dump_decl (t, flags); break; case STMT_EXPR: /* We don't yet have a way of dumping statements in a human-readable format. */ pp_string (cxx_pp, "({...})"); break; - case BIND_EXPR: - pp_left_brace (cxx_pp); - dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS); - pp_right_brace (cxx_pp); - break; - case LOOP_EXPR: pp_string (cxx_pp, "while (1) { "); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); ! pp_right_brace (cxx_pp); break; case EXIT_EXPR: --- 1815,1832 ---- dump_decl (t, flags); break; + case BIND_EXPR: case STMT_EXPR: + case STATEMENT_LIST: /* We don't yet have a way of dumping statements in a human-readable format. */ pp_string (cxx_pp, "({...})"); break; case LOOP_EXPR: pp_string (cxx_pp, "while (1) { "); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); ! pp_cxx_right_brace (cxx_pp); break; case EXIT_EXPR: *************** dump_expr (tree t, int flags) *** 1856,1863 **** case EMPTY_CLASS_EXPR: dump_type (TREE_TYPE (t), flags); ! pp_left_paren (cxx_pp); ! pp_right_paren (cxx_pp); break; case NON_DEPENDENT_EXPR: --- 1841,1848 ---- case EMPTY_CLASS_EXPR: dump_type (TREE_TYPE (t), flags); ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_right_paren (cxx_pp); break; case NON_DEPENDENT_EXPR: *************** dump_expr (tree t, int flags) *** 1879,1914 **** static void dump_binary_op (const char *opstring, tree t, int flags) { ! pp_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_space (cxx_pp); if (opstring) ! pp_identifier (cxx_pp, opstring); else pp_identifier (cxx_pp, ""); ! pp_space (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_right_paren (cxx_pp); } static void dump_unary_op (const char *opstring, tree t, int flags) { if (flags & TFF_EXPR_IN_PARENS) ! pp_left_paren (cxx_pp); ! pp_identifier (cxx_pp, opstring); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_right_paren (cxx_pp); } /* Exported interface to stringifying types, exprs and decls under TFF_* control. */ const char * type_as_string (tree typ, int flags) { ! pp_clear_output_area (cxx_pp); dump_type (typ, flags); return pp_formatted_text (cxx_pp); } --- 1864,1910 ---- static void dump_binary_op (const char *opstring, tree t, int flags) { ! pp_cxx_left_paren (cxx_pp); dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_whitespace (cxx_pp); if (opstring) ! pp_cxx_identifier (cxx_pp, opstring); else pp_identifier (cxx_pp, ""); ! pp_cxx_whitespace (cxx_pp); dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS); ! pp_cxx_right_paren (cxx_pp); } static void dump_unary_op (const char *opstring, tree t, int flags) { if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_left_paren (cxx_pp); ! pp_cxx_identifier (cxx_pp, opstring); dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS); if (flags & TFF_EXPR_IN_PARENS) ! pp_cxx_right_paren (cxx_pp); } + static void + reinit_cxx_pp (void) + { + pp_clear_output_area (cxx_pp); + pp_base (cxx_pp)->padding = pp_none; + pp_indentation (cxx_pp) = 0; + pp_needs_newline (cxx_pp) = false; + cxx_pp->enclosing_scope = 0; + } + + /* Exported interface to stringifying types, exprs and decls under TFF_* control. */ const char * type_as_string (tree typ, int flags) { ! reinit_cxx_pp (); dump_type (typ, flags); return pp_formatted_text (cxx_pp); } *************** type_as_string (tree typ, int flags) *** 1916,1922 **** const char * expr_as_string (tree decl, int flags) { ! pp_clear_output_area (cxx_pp); dump_expr (decl, flags); return pp_formatted_text (cxx_pp); } --- 1912,1918 ---- const char * expr_as_string (tree decl, int flags) { ! reinit_cxx_pp (); dump_expr (decl, flags); return pp_formatted_text (cxx_pp); } *************** expr_as_string (tree decl, int flags) *** 1924,1942 **** const char * decl_as_string (tree decl, int flags) { ! pp_clear_output_area (cxx_pp); dump_decl (decl, flags); return pp_formatted_text (cxx_pp); } - const char * - context_as_string (tree context, int flags) - { - pp_clear_output_area (cxx_pp); - dump_scope (context, flags); - return pp_formatted_text (cxx_pp); - } - /* Generate the three forms of printable names for cxx_printable_name. */ const char * --- 1920,1930 ---- const char * decl_as_string (tree decl, int flags) { ! reinit_cxx_pp (); dump_decl (decl, flags); return pp_formatted_text (cxx_pp); } /* Generate the three forms of printable names for cxx_printable_name. */ const char * *************** lang_decl_name (tree decl, int v) *** 1945,1955 **** if (v >= 2) return decl_as_string (decl, TFF_DECL_SPECIFIERS); ! pp_clear_output_area (cxx_pp); if (v == 1 && DECL_CLASS_SCOPE_P (decl)) { dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER); ! pp_colon_colon (cxx_pp); } if (TREE_CODE (decl) == FUNCTION_DECL) --- 1933,1943 ---- if (v >= 2) return decl_as_string (decl, TFF_DECL_SPECIFIERS); ! reinit_cxx_pp (); if (v == 1 && DECL_CLASS_SCOPE_P (decl)) { dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER); ! pp_cxx_colon_colon (cxx_pp); } if (TREE_CODE (decl) == FUNCTION_DECL) *************** decl_to_string (tree decl, int verbose) *** 1991,1997 **** flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE; flags |= TFF_TEMPLATE_HEADER; ! pp_clear_output_area (cxx_pp); dump_decl (decl, flags); return pp_formatted_text (cxx_pp); } --- 1979,1985 ---- flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE; flags |= TFF_TEMPLATE_HEADER; ! reinit_cxx_pp (); dump_decl (decl, flags); return pp_formatted_text (cxx_pp); } *************** decl_to_string (tree decl, int verbose) *** 1999,2005 **** static const char * expr_to_string (tree decl) { ! pp_clear_output_area (cxx_pp); dump_expr (decl, 0); return pp_formatted_text (cxx_pp); } --- 1987,1993 ---- static const char * expr_to_string (tree decl) { ! reinit_cxx_pp (); dump_expr (decl, 0); return pp_formatted_text (cxx_pp); } *************** fndecl_to_string (tree fndecl, int verbo *** 2012,2018 **** flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS; if (verbose) flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS; ! pp_clear_output_area (cxx_pp); dump_decl (fndecl, flags); return pp_formatted_text (cxx_pp); } --- 2000,2006 ---- flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS; if (verbose) flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS; ! reinit_cxx_pp (); dump_decl (fndecl, flags); return pp_formatted_text (cxx_pp); } *************** language_to_string (enum languages c) *** 2039,2047 **** return "Java"; default: ! abort (); ! return 0; } } /* Return the proper printed version of a parameter to a C++ function. */ --- 2027,2035 ---- return "Java"; default: ! gcc_unreachable (); } + return 0; } /* Return the proper printed version of a parameter to a C++ function. */ *************** language_to_string (enum languages c) *** 2049,2055 **** static const char * parm_to_string (int p) { ! pp_clear_output_area (cxx_pp); if (p < 0) pp_string (cxx_pp, "'this'"); else --- 2037,2043 ---- static const char * parm_to_string (int p) { ! reinit_cxx_pp (); if (p < 0) pp_string (cxx_pp, "'this'"); else *************** type_to_string (tree typ, int verbose) *** 2072,2078 **** flags |= TFF_CLASS_KEY_OR_ENUM; flags |= TFF_TEMPLATE_HEADER; ! pp_clear_output_area (cxx_pp); dump_type (typ, flags); return pp_formatted_text (cxx_pp); } --- 2060,2066 ---- flags |= TFF_CLASS_KEY_OR_ENUM; flags |= TFF_TEMPLATE_HEADER; ! reinit_cxx_pp (); dump_type (typ, flags); return pp_formatted_text (cxx_pp); } *************** args_to_string (tree p, int verbose) *** 2097,2107 **** if (TYPE_P (TREE_VALUE (p))) return type_as_string (p, flags); ! pp_clear_output_area (cxx_pp); for (; p; p = TREE_CHAIN (p)) { if (TREE_VALUE (p) == null_node) ! pp_identifier (cxx_pp, "NULL"); else dump_type (error_type (TREE_VALUE (p)), flags); if (TREE_CHAIN (p)) --- 2085,2095 ---- if (TYPE_P (TREE_VALUE (p))) return type_as_string (p, flags); ! reinit_cxx_pp (); for (; p; p = TREE_CHAIN (p)) { if (TREE_VALUE (p) == null_node) ! pp_cxx_identifier (cxx_pp, "NULL"); else dump_type (error_type (TREE_VALUE (p)), flags); if (TREE_CHAIN (p)) *************** args_to_string (tree p, int verbose) *** 2113,2120 **** static const char * cv_to_string (tree p, int v) { ! pp_clear_output_area (cxx_pp); ! dump_qualifiers (p, v ? before : none); return pp_formatted_text (cxx_pp); } --- 2101,2109 ---- static const char * cv_to_string (tree p, int v) { ! reinit_cxx_pp (); ! pp_base (cxx_pp)->padding = v ? pp_before : pp_none; ! pp_cxx_cv_qualifier_seq (cxx_pp, p); return pp_formatted_text (cxx_pp); } *************** cp_print_error_function (diagnostic_cont *** 2153,2168 **** if (diagnostic_last_function_changed (context)) { const char *old_prefix = context->printer->prefix; ! char *new_prefix = diagnostic->location.file ! ? file_name_as_prefix (diagnostic->location.file) ! : NULL; pp_base_set_prefix (context->printer, new_prefix); if (current_function_decl == NULL) pp_base_string (context->printer, "At global scope:"); else ! pp_printf (context->printer, "In %s `%s':", function_category (current_function_decl), cxx_printable_name (current_function_decl, 2)); pp_base_newline (context->printer); --- 2142,2156 ---- if (diagnostic_last_function_changed (context)) { const char *old_prefix = context->printer->prefix; ! const char *file = LOCATION_FILE (diagnostic->location); ! char *new_prefix = file ? file_name_as_prefix (file) : NULL; pp_base_set_prefix (context->printer, new_prefix); if (current_function_decl == NULL) pp_base_string (context->printer, "At global scope:"); else ! pp_printf (context->printer, "In %s %qs:", function_category (current_function_decl), cxx_printable_name (current_function_decl, 2)); pp_base_newline (context->printer); *************** print_instantiation_full_context (diagno *** 2213,2227 **** else { if (current_function_decl == TINST_DECL (p)) ! /* Avoid redundancy with the the "In function" line. */; else pp_verbatim (context->printer, ! "%s: In instantiation of `%s':\n", location.file, decl_as_string (TINST_DECL (p), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE)); ! location.line = TINST_LINE (p); ! location.file = TINST_FILE (p); p = TREE_CHAIN (p); } } --- 2201,2215 ---- else { if (current_function_decl == TINST_DECL (p)) ! /* Avoid redundancy with the "In function" line. */; else pp_verbatim (context->printer, ! "%s: In instantiation of %qs:\n", ! LOCATION_FILE (location), decl_as_string (TINST_DECL (p), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE)); ! location = TINST_LOCATION (p); p = TREE_CHAIN (p); } } *************** static void *** 2234,2250 **** print_instantiation_partial_context (diagnostic_context *context, tree t, location_t loc) { ! for (; t; t = TREE_CHAIN (t)) { ! pp_verbatim (context->printer, "%s:%d: instantiated from `%s'\n", ! loc.file, loc.line, decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE)); ! loc.line = TINST_LINE (t); ! loc.file = TINST_FILE (t); } pp_verbatim (context->printer, "%s:%d: instantiated from here\n", ! loc.file, loc.line); } /* Called from cp_thing to print the template context for an error. */ --- 2222,2241 ---- print_instantiation_partial_context (diagnostic_context *context, tree t, location_t loc) { ! expanded_location xloc; ! for (; ; t = TREE_CHAIN (t)) { ! xloc = expand_location (loc); ! if (t == NULL_TREE) ! break; ! pp_verbatim (context->printer, "%s:%d: instantiated from %qs\n", ! xloc.file, xloc.line, decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE)); ! loc = TINST_LOCATION (t); } pp_verbatim (context->printer, "%s:%d: instantiated from here\n", ! xloc.file, xloc.line); } /* Called from cp_thing to print the template context for an error. */ *************** cp_printer (pretty_printer *pp, text_inf *** 2324,2339 **** #undef next_int } - static void - pp_non_consecutive_character (cxx_pretty_printer *pp, int c) - { - const char *p = pp_last_position_in_text (pp); - - if (p != NULL && *p == c) - pp_space (pp); - pp_character (pp, c); - } - /* These are temporary wrapper functions which handle the historic behavior of cp_*_at. */ --- 2315,2320 ---- *************** locate_error (const char *msgid, va_list *** 2349,2357 **** plus = 0; if (*f == '%') { ! f++; if (*f == '+') ! f++, plus = 1; if (*f == '#') f++; --- 2330,2343 ---- plus = 0; if (*f == '%') { ! if (*++f == 'q') ! ++f; /* ignore quoting flag. */ ! if (*f == '+') ! { ! ++f; ! plus = 1; ! } if (*f == '#') f++; *************** locate_error (const char *msgid, va_list *** 2382,2388 **** default: errorcount = 0; /* damn ICE suppression */ ! internal_error ("unexpected letter `%c' in locate_error\n", *f); } } } --- 2368,2374 ---- default: errorcount = 0; /* damn ICE suppression */ ! internal_error ("unexpected letter %qc in locate_error\n", *f); } } } diff -Nrcpad gcc-3.4.3/gcc/cp/except.c gcc-4.0.0/gcc/cp/except.c *** gcc-3.4.3/gcc/cp/except.c Thu Aug 12 05:19:27 2004 --- gcc-4.0.0/gcc/cp/except.c Sat Feb 19 02:35:16 2005 *************** *** 1,6 **** /* Handle exceptional things in C++. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann Rewritten by Mike Stump , based upon an initial re-implementation courtesy Tad Hunt. --- 1,6 ---- /* Handle exceptional things in C++. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann Rewritten by Mike Stump , based upon an initial re-implementation courtesy Tad Hunt. *************** Boston, MA 02111-1307, USA. */ *** 37,42 **** --- 37,43 ---- #include "except.h" #include "toplev.h" #include "tree-inline.h" + #include "tree-iterator.h" static void push_eh_cleanup (tree); static tree prepare_eh_type (tree); *************** static tree wrap_cleanups_r (tree *, int *** 51,57 **** static int complete_ptr_ref_or_void_ptr_p (tree, tree); static bool is_admissible_throw_operand (tree); static int can_convert_eh (tree, tree); - static void check_handlers_1 (tree, tree); static tree cp_protect_cleanup_actions (void); /* Sets up all the global eh stuff that needs to be initialized at the --- 52,57 ---- *************** build_eh_type_type (tree type) *** 144,156 **** mark_used (exp); ! return build1 (ADDR_EXPR, ptr_type_node, exp); } tree build_exc_ptr (void) { ! return build (EXC_PTR_EXPR, ptr_type_node); } /* Build up a call to __cxa_begin_catch, to tell the runtime that the --- 144,176 ---- mark_used (exp); ! return convert (ptr_type_node, build_address (exp)); } tree build_exc_ptr (void) { ! return build0 (EXC_PTR_EXPR, ptr_type_node); ! } ! ! /* Build up a call to __cxa_get_exception_ptr so that we can build a ! copy constructor for the thrown object. */ ! ! static tree ! do_get_exception_ptr (void) ! { ! tree fn; ! ! fn = get_identifier ("__cxa_get_exception_ptr"); ! if (!get_global_value_if_present (fn, &fn)) ! { ! /* Declare void* __cxa_get_exception_ptr (void *). */ ! tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); ! fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp)); ! } ! ! return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), ! NULL_TREE)); } /* Build up a call to __cxa_begin_catch, to tell the runtime that the *************** dtor_nothrow (tree type) *** 182,190 **** if (type == NULL_TREE) return 0; ! if (! TYPE_HAS_DESTRUCTOR (type)) return 1; return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type)); } --- 202,213 ---- if (type == NULL_TREE) return 0; ! if (!CLASS_TYPE_P (type)) return 1; + if (CLASSTYPE_LAZY_DESTRUCTOR (type)) + lazily_declare_fn (sfk_destructor, type); + return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type)); } *************** decl_is_java_type (tree decl, int err) *** 236,243 **** && TYPE_FOR_JAVA (TREE_TYPE (decl))) { /* Can't throw a reference. */ ! error ("type `%T' is disallowed in Java `throw' or `catch'", ! decl); } if (r) --- 259,266 ---- && TYPE_FOR_JAVA (TREE_TYPE (decl))) { /* Can't throw a reference. */ ! error ("type %qT is disallowed in Java % or %", ! decl); } if (r) *************** decl_is_java_type (tree decl, int err) *** 247,261 **** if (jthrow_node == NULL_TREE) fatal_error ! ("call to Java `catch' or `throw' with `jthrowable' undefined"); jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node)); if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl))) { /* Thrown object must be a Throwable. */ ! error ("type `%T' is not derived from `java::lang::Throwable'", ! TREE_TYPE (decl)); } } } --- 270,284 ---- if (jthrow_node == NULL_TREE) fatal_error ! ("call to Java % or % with % undefined"); jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node)); if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl))) { /* Thrown object must be a Throwable. */ ! error ("type %qT is not derived from %", ! TREE_TYPE (decl)); } } } *************** choose_personality_routine (enum languag *** 312,318 **** break; default: ! abort (); } return; --- 335,341 ---- break; default: ! gcc_unreachable (); } return; *************** initialize_handler_parm (tree decl, tree *** 337,344 **** adjusted by value from __cxa_begin_catch. Others are returned by reference. */ init_type = TREE_TYPE (decl); ! if (! TYPE_PTR_P (init_type) ! && TREE_CODE (init_type) != REFERENCE_TYPE) init_type = build_reference_type (init_type); choose_personality_routine (decl_is_java_type (init_type, 0) --- 360,366 ---- adjusted by value from __cxa_begin_catch. Others are returned by reference. */ init_type = TREE_TYPE (decl); ! if (!POINTER_TYPE_P (init_type)) init_type = build_reference_type (init_type); choose_personality_routine (decl_is_java_type (init_type, 0) *************** initialize_handler_parm (tree decl, tree *** 379,387 **** tree expand_start_catch_block (tree decl) { ! tree exp = NULL_TREE; tree type; - bool is_java; if (! doing_eh (1)) return NULL_TREE; --- 401,408 ---- tree expand_start_catch_block (tree decl) { ! tree exp; tree type; if (! doing_eh (1)) return NULL_TREE; *************** expand_start_catch_block (tree decl) *** 395,439 **** else type = NULL_TREE; ! is_java = false; ! if (decl) { ! tree init; ! if (decl_is_java_type (type, 1)) ! { ! /* Java only passes object via pointer and doesn't require ! adjusting. The java object is immediately before the ! generic exception header. */ ! init = build_exc_ptr (); ! init = build1 (NOP_EXPR, build_pointer_type (type), init); ! init = build (MINUS_EXPR, TREE_TYPE (init), init, ! TYPE_SIZE_UNIT (TREE_TYPE (init))); ! init = build_indirect_ref (init, NULL); ! is_java = true; ! } ! else ! { ! /* C++ requires that we call __cxa_begin_catch to get the ! pointer to the actual object. */ ! init = do_begin_catch (); ! } ! exp = create_temporary_var (ptr_type_node); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING); finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); } - else - finish_expr_stmt (do_begin_catch ()); - - /* C++ requires that we call __cxa_end_catch at the end of - processing the exception. */ - if (! is_java) - push_eh_cleanup (type); - - if (decl) - initialize_handler_parm (decl, exp); return type; } --- 416,465 ---- else type = NULL_TREE; ! if (decl && decl_is_java_type (type, 1)) { ! /* Java only passes object via pointer and doesn't require ! adjusting. The java object is immediately before the ! generic exception header. */ ! exp = build_exc_ptr (); ! exp = build1 (NOP_EXPR, build_pointer_type (type), exp); ! exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp, ! TYPE_SIZE_UNIT (TREE_TYPE (exp))); ! exp = build_indirect_ref (exp, NULL); ! initialize_handler_parm (decl, exp); ! return type; ! } ! /* Call __cxa_end_catch at the end of processing the exception. */ ! push_eh_cleanup (type); ! ! /* If there's no decl at all, then all we need to do is make sure ! to tell the runtime that we've begun handling the exception. */ ! if (decl == NULL) ! finish_expr_stmt (do_begin_catch ()); ! ! /* If the C++ object needs constructing, we need to do that before ! calling __cxa_begin_catch, so that std::uncaught_exception gets ! the right value during the copy constructor. */ ! else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) ! { ! exp = do_get_exception_ptr (); ! initialize_handler_parm (decl, exp); ! finish_expr_stmt (do_begin_catch ()); ! } ! ! /* Otherwise the type uses a bitwise copy, and we don't have to worry ! about the value of std::uncaught_exception and therefore can do the ! copy with the return value of __cxa_end_catch instead. */ ! else ! { ! tree init = do_begin_catch (); exp = create_temporary_var (ptr_type_node); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING); finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); + initialize_handler_parm (decl, exp); } return type; } *************** begin_eh_spec_block (void) *** 462,467 **** --- 488,494 ---- { tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); + EH_SPEC_STMTS (r) = push_stmt_list (); return r; } *************** finish_eh_spec_block (tree raw_raises, t *** 470,476 **** { tree raises; ! RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block)); /* Strip cv quals, etc, from the specification types. */ for (raises = NULL_TREE; --- 497,503 ---- { tree raises; ! EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block)); /* Strip cv quals, etc, from the specification types. */ for (raises = NULL_TREE; *************** build_throw (tree exp) *** 595,601 **** } else if (really_overloaded_fn (fn)) { ! error ("`%D' should never be overloaded", fn); return error_mark_node; } fn = OVL_CURRENT (fn); --- 622,628 ---- } else if (really_overloaded_fn (fn)) { ! error ("%qD should never be overloaded", fn); return error_mark_node; } fn = OVL_CURRENT (fn); *************** build_throw (tree exp) *** 688,700 **** stabilize_init (exp, &temp_expr); if (elided) ! exp = build (TRY_CATCH_EXPR, void_type_node, exp, ! do_free_exception (ptr)); else exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp); /* Prepend the allocation. */ ! exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); if (temp_expr) { /* Prepend the calculation of the throw expression. Also, force --- 715,727 ---- stabilize_init (exp, &temp_expr); if (elided) ! exp = build2 (TRY_CATCH_EXPR, void_type_node, exp, ! do_free_exception (ptr)); else exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp); /* Prepend the allocation. */ ! exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); if (temp_expr) { /* Prepend the calculation of the throw expression. Also, force *************** build_throw (tree exp) *** 703,715 **** 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))); ! if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) { cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), complete_dtor_identifier, 0); --- 730,742 ---- 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 = build2 (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))); ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object))) { cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), complete_dtor_identifier, 0); *************** build_throw (tree exp) *** 720,730 **** cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); } else ! { ! cleanup = build_int_2 (0, 0); ! TREE_TYPE (cleanup) = cleanup_type; ! } ! tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE); tmp = tree_cons (NULL_TREE, throw_type, tmp); tmp = tree_cons (NULL_TREE, ptr, tmp); --- 747,754 ---- cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); } else ! cleanup = build_int_cst (cleanup_type, 0); ! tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE); tmp = tree_cons (NULL_TREE, throw_type, tmp); tmp = tree_cons (NULL_TREE, ptr, tmp); *************** build_throw (tree exp) *** 732,738 **** tmp = build_function_call (fn, tmp); /* Tack on the initialization stuff. */ ! exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); } else { --- 756,762 ---- tmp = build_function_call (fn, tmp); /* Tack on the initialization stuff. */ ! exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); } else { *************** is_admissible_throw_operand (tree expr) *** 809,815 **** conversion. */ else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) { ! error ("expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type); return false; } --- 833,840 ---- conversion. */ else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) { ! error ("expression %qE of abstract class type %qT cannot " ! "be used in throw-expression", expr, type); return false; } *************** nothrow_libfn_p (tree fn) *** 840,846 **** /* Can't be a C library function. */ return 0; ! id = DECL_ASSEMBLER_NAME (fn); return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); } --- 865,874 ---- /* Can't be a C library function. */ return 0; ! /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME ! unless the system headers are playing rename tricks, and if ! they are, we don't want to be confused by them. */ ! id = DECL_NAME (fn); return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); } *************** can_convert_eh (tree to, tree from) *** 874,924 **** return 0; } ! /* Check whether any of HANDLERS are shadowed by another handler accepting ! TYPE. Note that the shadowing may not be complete; even if an exception ! of type B would be caught by a handler for A, there could be a derived ! class C for which A is an ambiguous base but B is not, so the handler ! for B would catch an exception of type C. */ static void ! check_handlers_1 (tree master, tree handlers) { tree type = TREE_TYPE (master); - tree handler; ! for (handler = handlers; handler; handler = TREE_CHAIN (handler)) ! if (TREE_TYPE (handler) ! && can_convert_eh (type, TREE_TYPE (handler))) ! { ! input_line = STMT_LINENO (handler); ! warning ("exception of type `%T' will be caught", ! TREE_TYPE (handler)); ! input_line = STMT_LINENO (master); ! warning (" by earlier handler for `%T'", type); ! break; ! } } ! /* Given a chain of HANDLERs, make sure that they're OK. */ void check_handlers (tree handlers) { ! tree handler; ! int save_line = input_line; ! ! for (handler = handlers; handler; handler = TREE_CHAIN (handler)) ! { ! if (TREE_CHAIN (handler) == NULL_TREE) ! /* No more handlers; nothing to shadow. */; ! else if (TREE_TYPE (handler) == NULL_TREE) ! { ! input_line = STMT_LINENO (handler); ! pedwarn ! ("`...' handler must be the last handler for its try block"); ! } ! else ! check_handlers_1 (handler, TREE_CHAIN (handler)); ! } ! input_line = save_line; } --- 902,958 ---- return 0; } ! /* Check whether any of the handlers in I are shadowed by another handler ! accepting TYPE. Note that the shadowing may not be complete; even if ! an exception of type B would be caught by a handler for A, there could ! be a derived class C for which A is an ambiguous base but B is not, so ! the handler for B would catch an exception of type C. */ static void ! check_handlers_1 (tree master, tree_stmt_iterator i) { tree type = TREE_TYPE (master); ! for (; !tsi_end_p (i); tsi_next (&i)) ! { ! tree handler = tsi_stmt (i); ! if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler))) ! { ! warning ("%Hexception of type %qT will be caught", ! EXPR_LOCUS (handler), TREE_TYPE (handler)); ! warning ("%H by earlier handler for %qT", ! EXPR_LOCUS (master), type); ! break; ! } ! } } ! /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */ void check_handlers (tree handlers) { ! tree_stmt_iterator i; ! ! /* If we don't have a STATEMENT_LIST, then we've just got one ! handler, and thus nothing to warn about. */ ! if (TREE_CODE (handlers) != STATEMENT_LIST) ! return; ! ! i = tsi_start (handlers); ! if (!tsi_end_p (i)) ! while (1) ! { ! tree handler = tsi_stmt (i); ! tsi_next (&i); ! ! /* No more handlers; nothing to shadow. */ ! if (tsi_end_p (i)) ! break; ! if (TREE_TYPE (handler) == NULL_TREE) ! pedwarn ("%H%<...%> handler must be the last handler for" ! " its try block", EXPR_LOCUS (handler)); ! else ! check_handlers_1 (handler, i); ! } } diff -Nrcpad gcc-3.4.3/gcc/cp/expr.c gcc-4.0.0/gcc/cp/expr.c *** gcc-3.4.3/gcc/cp/expr.c Fri May 28 23:33:35 2004 --- gcc-4.0.0/gcc/cp/expr.c Fri May 28 23:34:39 2004 *************** cplus_expand_constant (tree cst) *** 86,91 **** --- 86,94 ---- } /* Hook used by expand_expr to expand language-specific tree codes. */ + /* ??? The only thing that should be here are things needed to expand + constant initializers; everything else should be handled by the + gimplification routines. Are EMPTY_CLASS_EXPR or BASELINK needed? */ rtx cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier, *************** cxx_expand_expr (tree exp, rtx target, e *** 94,100 **** tree type = TREE_TYPE (exp); enum machine_mode mode = TYPE_MODE (type); enum tree_code code = TREE_CODE (exp); - rtx ret; /* No sense saving up arithmetic to be done if it's all in the wrong mode to form part of an address. --- 97,102 ---- *************** cxx_expand_expr (tree exp, rtx target, e *** 112,128 **** case OFFSET_REF: /* 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 const0_rtx; - - case MUST_NOT_THROW_EXPR: - expand_eh_region_start (); - ret = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); - expand_eh_region_end_must_not_throw (build_call (terminate_node, 0)); - return ret; case EMPTY_CLASS_EXPR: /* We don't need to generate any code for an empty class. */ --- 114,119 ---- *************** cxx_expand_expr (tree exp, rtx target, e *** 135,141 **** default: return c_expand_expr (exp, target, tmode, modifier, alt_rtl); } - abort (); - /* NOTREACHED */ - return NULL; } --- 126,129 ---- diff -Nrcpad gcc-3.4.3/gcc/cp/friend.c gcc-4.0.0/gcc/cp/friend.c *** gcc-3.4.3/gcc/cp/friend.c Mon May 31 22:47:15 2004 --- gcc-4.0.0/gcc/cp/friend.c Mon Nov 29 20:10:11 2004 *************** *** 1,5 **** /* Help friends in C++. ! Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. --- 1,5 ---- /* Help friends in C++. ! Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. *************** is_friend (tree type, tree supplicant) *** 92,98 **** tree t = TREE_VALUE (list); if (TREE_CODE (t) == TEMPLATE_DECL ? ! is_specialization_of (TYPE_MAIN_DECL (supplicant), t) : same_type_p (supplicant, t)) return 1; } --- 92,98 ---- tree t = TREE_VALUE (list); if (TREE_CODE (t) == TEMPLATE_DECL ? ! is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) : same_type_p (supplicant, t)) return 1; } *************** add_friend (tree type, tree decl, bool c *** 129,134 **** --- 129,135 ---- tree typedecl; tree list; tree name; + tree ctx; if (decl == error_mark_node) return; *************** add_friend (tree type, tree decl, bool c *** 148,154 **** if (decl == TREE_VALUE (friends)) { if (complain) ! warning ("`%D' is already a friend of class `%T'", decl, type); return; } --- 149,155 ---- if (decl == TREE_VALUE (friends)) { if (complain) ! warning ("%qD is already a friend of class %qT", decl, type); return; } *************** add_friend (tree type, tree decl, bool c *** 163,174 **** list = TREE_CHAIN (list); } ! if (DECL_CLASS_SCOPE_P (decl)) ! { ! tree class_binfo = TYPE_BINFO (DECL_CONTEXT (decl)); ! if (!uses_template_parms (BINFO_TYPE (class_binfo))) ! perform_or_defer_access_check (class_binfo, decl); ! } maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); --- 164,172 ---- list = TREE_CHAIN (list); } ! ctx = DECL_CONTEXT (decl); ! if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx)) ! perform_or_defer_access_check (TYPE_BINFO (ctx), decl); maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); *************** void *** 199,213 **** make_friend_class (tree type, tree friend_type, bool complain) { tree classes; ! int is_template_friend; if (! IS_AGGR_TYPE (friend_type)) { ! error ("invalid type `%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. */ --- 197,235 ---- make_friend_class (tree type, tree friend_type, bool complain) { tree classes; ! ! /* CLASS_TEMPLATE_DEPTH counts the number of template headers for ! the enclosing class. FRIEND_DEPTH counts the number of template ! headers used for this friend declaration. TEMPLATE_MEMBER_P, ! defined inside the `if' block for TYPENAME_TYPE case, is true if ! a template header in FRIEND_DEPTH is intended for DECLARATOR. ! For example, the code ! ! template struct A { ! template struct B { ! template template ! friend class C::D; ! }; ! }; ! ! will eventually give the following results ! ! 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U'). ! 2. FRIEND_DEPTH equals 2 (for `V' and `W'). ! 3. TEMPLATE_MEMBER_P is true (for `W'). ! ! The friend is a template friend iff FRIEND_DEPTH is nonzero. */ ! ! int class_template_depth = template_class_depth (type); ! int friend_depth = processing_template_decl - class_template_depth; if (! IS_AGGR_TYPE (friend_type)) { ! error ("invalid type %qT declared %", friend_type); return; } ! if (friend_depth) /* 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. */ *************** make_friend_class (tree type, tree frien *** 219,240 **** /* [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)) { if (complain) ! pedwarn ("class `%T' is implicitly friends with itself", type); return; } - else - is_template_friend = 0; /* [temp.friend] --- 241,258 ---- /* [temp.friend] Friend declarations shall not declare partial specializations. */ ! error ("partial specialization %qT declared %", friend_type); return; } } else if (same_type_p (type, friend_type)) { if (complain) ! pedwarn ("class %qT is implicitly friends with itself", type); return; } /* [temp.friend] *************** make_friend_class (tree type, tree frien *** 242,271 **** class template, a specialization of a function template or class template, or an ordinary (nontemplate) function or class. */ ! if (!is_template_friend) ;/* ok */ else if (TREE_CODE (friend_type) == TYPENAME_TYPE) { ! /* template friend typename S::X; */ ! error ("typename type `%#T' declared `friend'", friend_type); ! return; } else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM) { /* template friend class T; */ ! error ("template parameter type `%T' declared `friend'", friend_type); return; } else if (!CLASSTYPE_TEMPLATE_INFO (friend_type)) { /* template friend class A; where A is not a template */ ! error ("`%#T' is not a template", friend_type); return; } ! ! if (is_template_friend) friend_type = CLASSTYPE_TI_TEMPLATE (friend_type); /* See if it is already a friend. */ for (classes = CLASSTYPE_FRIEND_CLASSES (type); classes; --- 260,354 ---- class template, a specialization of a function template or class template, or an ordinary (nontemplate) function or class. */ ! if (!friend_depth) ;/* ok */ else if (TREE_CODE (friend_type) == TYPENAME_TYPE) { ! if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type)) ! == TEMPLATE_ID_EXPR) ! { ! /* template friend class T::X; */ ! /* [temp.friend] ! Friend declarations shall not declare partial ! specializations. */ ! error ("partial specialization %qT declared %", ! friend_type); ! return; ! } ! else ! { ! /* We will figure this out later. */ ! bool template_member_p = false; ! ! tree ctype = TYPE_CONTEXT (friend_type); ! tree name = TYPE_IDENTIFIER (friend_type); ! tree decl; ! ! if (!uses_template_parms_level (ctype, class_template_depth ! + friend_depth)) ! template_member_p = true; ! ! if (class_template_depth) ! { ! /* We rely on tsubst_friend_class to check the ! validity of the declaration later. */ ! if (template_member_p) ! friend_type ! = make_unbound_class_template (ctype, ! name, ! current_template_parms, ! tf_error); ! else ! friend_type ! = make_typename_type (ctype, name, class_type, tf_error); ! } ! else ! { ! decl = lookup_member (ctype, name, 0, true); ! if (!decl) ! { ! error ("%qT is not a member of %qT", name, ctype); ! return; ! } ! if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl)) ! { ! error ("%qT is not a member class template of %qT", ! name, ctype); ! cp_error_at ("%qD declared here", decl); ! return; ! } ! if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL ! || !CLASS_TYPE_P (TREE_TYPE (decl)))) ! { ! error ("%qT is not a nested class of %qT", ! name, ctype); ! cp_error_at ("%qD declared here", decl); ! return; ! } ! ! friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)); ! } ! } } else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM) { /* template friend class T; */ ! error ("template parameter type %qT declared %", friend_type); return; } else if (!CLASSTYPE_TEMPLATE_INFO (friend_type)) { /* template friend class A; where A is not a template */ ! error ("%q#T is not a template", friend_type); return; } ! else ! /* template friend class A; where A is a template */ friend_type = CLASSTYPE_TI_TEMPLATE (friend_type); + if (friend_type == error_mark_node) + return; + /* See if it is already a friend. */ for (classes = CLASSTYPE_FRIEND_CLASSES (type); classes; *************** make_friend_class (tree type, tree frien *** 278,285 **** if (friend_type == probe) { if (complain) ! warning ("`%D' is already a friend of `%T'", ! probe, type); break; } } --- 361,367 ---- if (friend_type == probe) { if (complain) ! warning ("%qD is already a friend of %qT", probe, type); break; } } *************** make_friend_class (tree type, tree frien *** 288,295 **** if (same_type_p (probe, friend_type)) { if (complain) ! warning ("`%T' is already a friend of `%T'", ! probe, type); break; } } --- 370,376 ---- if (same_type_p (probe, friend_type)) { if (complain) ! warning ("%qT is already a friend of %qT", probe, type); break; } } *************** make_friend_class (tree type, tree frien *** 301,307 **** CLASSTYPE_FRIEND_CLASSES (type) = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); ! if (is_template_friend) friend_type = TREE_TYPE (friend_type); if (!uses_template_parms (type)) CLASSTYPE_BEFRIENDING_CLASSES (friend_type) --- 382,388 ---- CLASSTYPE_FRIEND_CLASSES (type) = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); ! if (TREE_CODE (friend_type) == TEMPLATE_DECL) friend_type = TREE_TYPE (friend_type); if (!uses_template_parms (type)) CLASSTYPE_BEFRIENDING_CLASSES (friend_type) *************** make_friend_class (tree type, tree frien *** 325,331 **** tree do_friend (tree ctype, tree declarator, tree decl, ! tree attrlist, enum overload_flags flags, tree quals, int funcdef_flag) { /* Every decl that gets here is a friend of something. */ --- 406,413 ---- tree do_friend (tree ctype, tree declarator, tree decl, ! tree attrlist, enum overload_flags flags, ! cp_cv_quals quals, int funcdef_flag) { /* Every decl that gets here is a friend of something. */ *************** do_friend (tree ctype, tree declarator, *** 338,345 **** declarator = DECL_NAME (get_first_fn (declarator)); } ! if (TREE_CODE (decl) != FUNCTION_DECL) ! abort (); if (ctype) { --- 420,426 ---- declarator = DECL_NAME (get_first_fn (declarator)); } ! gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); if (ctype) { *************** do_friend (tree ctype, tree declarator, *** 401,407 **** validity of the declaration later. */ decl = push_template_decl_real (decl, /*is_friend=*/1); else ! decl = check_classfn (ctype, decl, template_member_p); if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL) decl = DECL_TI_TEMPLATE (decl); --- 482,491 ---- validity of the declaration later. */ decl = push_template_decl_real (decl, /*is_friend=*/1); else ! decl = check_classfn (ctype, decl, ! template_member_p ! ? current_template_parms ! : NULL_TREE); if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL) decl = DECL_TI_TEMPLATE (decl); *************** do_friend (tree ctype, tree declarator, *** 410,416 **** add_friend (current_class_type, decl, /*complain=*/true); } else ! error ("member `%D' declared as friend before type `%T' defined", decl, ctype); } /* A global friend. --- 494,500 ---- add_friend (current_class_type, decl, /*complain=*/true); } else ! error ("member %qD declared as friend before type %qT defined", decl, ctype); } /* A global friend. *************** do_friend (tree ctype, tree declarator, *** 466,475 **** if (warn) { static int explained; ! warning ("friend declaration `%#D' declares a non-template function", decl); if (! explained) { ! warning ("(if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning"); explained = 1; } } --- 550,563 ---- if (warn) { static int explained; ! warning ("friend declaration %q#D declares a non-template " ! "function", decl); if (! explained) { ! warning ("(if this is not what you intended, make sure " ! "the function template has already been declared " ! "and add <> after the function name here) " ! "-Wno-non-template-friend disables this warning"); explained = 1; } } diff -Nrcpad gcc-3.4.3/gcc/cp/g++spec.c gcc-4.0.0/gcc/cp/g++spec.c *** gcc-3.4.3/gcc/cp/g++spec.c Wed Sep 29 02:18:58 2004 --- gcc-4.0.0/gcc/cp/g++spec.c Thu Nov 25 11:13:33 2004 *************** *** 1,5 **** /* Specific flags and argument handling of the C++ front-end. ! Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. --- 1,5 ---- /* Specific flags and argument handling of the C++ front-end. ! Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 36,49 **** #define MATH_LIBRARY "-lm" #endif #ifndef MATH_LIBRARY_PROFILE ! #define MATH_LIBRARY_PROFILE "-lm" #endif #ifndef LIBSTDCXX #define LIBSTDCXX "-lstdc++" #endif #ifndef LIBSTDCXX_PROFILE ! #define LIBSTDCXX_PROFILE "-lstdc++" #endif void --- 36,49 ---- #define MATH_LIBRARY "-lm" #endif #ifndef MATH_LIBRARY_PROFILE ! #define MATH_LIBRARY_PROFILE MATH_LIBRARY #endif #ifndef LIBSTDCXX #define LIBSTDCXX "-lstdc++" #endif #ifndef LIBSTDCXX_PROFILE ! #define LIBSTDCXX_PROFILE LIBSTDCXX #endif void *************** lang_specific_driver (int *in_argc, cons *** 136,145 **** { library = -1; } ! else if (strcmp (argv[i], "-lm") == 0 ! || strcmp (argv[i], "-lmath") == 0 ! || strcmp (argv[i], MATH_LIBRARY) == 0 ! ) { args[i] |= MATHLIB; need_math = 0; --- 136,142 ---- { library = -1; } ! else if (strcmp (argv[i], MATH_LIBRARY) == 0) { args[i] |= MATHLIB; need_math = 0; *************** lang_specific_driver (int *in_argc, cons *** 167,178 **** } saw_speclang = 1; } /* Unrecognized libraries (e.g. -lfoo) may require libstdc++. */ else if (strncmp (argv[i], "-l", 2) == 0) library = (library == 0) ? 1 : library; else if (((argv[i][2] == '\0' && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL) - || strcmp (argv[i], "-Xlinker") == 0 || strcmp (argv[i], "-Tdata") == 0)) quote = argv[i]; else if ((argv[i][2] == '\0' --- 164,184 ---- } saw_speclang = 1; } + /* Arguments that go directly to the linker might be .o files, + or something, and so might cause libstdc++ to be needed. */ + else if (strcmp (argv[i], "-Xlinker") == 0) + { + quote = argv[i]; + if (library == 0) + library = 1; + } + else if (strncmp (argv[i], "-Wl,", 4) == 0) + library = (library == 0) ? 1 : library; /* Unrecognized libraries (e.g. -lfoo) may require libstdc++. */ else if (strncmp (argv[i], "-l", 2) == 0) library = (library == 0) ? 1 : library; else if (((argv[i][2] == '\0' && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL) || strcmp (argv[i], "-Tdata") == 0)) quote = argv[i]; else if ((argv[i][2] == '\0' *************** lang_specific_driver (int *in_argc, cons *** 229,235 **** } if (quote) ! fatal ("argument to `%s' missing\n", quote); /* If we know we don't have to do anything, bail now. */ if (! added && library <= 0) --- 235,241 ---- } if (quote) ! fatal ("argument to '%s' missing\n", quote); /* If we know we don't have to do anything, bail now. */ if (! added && library <= 0) *************** lang_specific_driver (int *in_argc, cons *** 290,296 **** arglist[j++] = "-xc++-header"; break; default: ! abort (); } arglist[j++] = argv[i]; arglist[j] = "-xnone"; --- 296,302 ---- arglist[j++] = "-xc++-header"; break; default: ! gcc_unreachable (); } arglist[j++] = argv[i]; arglist[j] = "-xnone"; *************** lang_specific_driver (int *in_argc, cons *** 303,317 **** /* Add `-lstdc++' if we haven't already done so. */ if (library > 0) { ! arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX; ! added_libraries++; } if (saw_math) arglist[j++] = saw_math; else if (library > 0 && need_math) { ! arglist[j++] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY; ! added_libraries++; } if (saw_libc) arglist[j++] = saw_libc; --- 309,327 ---- /* Add `-lstdc++' if we haven't already done so. */ if (library > 0) { ! arglist[j] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX; ! if (arglist[j][0] != '-' || arglist[j][1] == 'l') ! added_libraries++; ! j++; } if (saw_math) arglist[j++] = saw_math; else if (library > 0 && need_math) { ! arglist[j] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY; ! if (arglist[j][0] != '-' || arglist[j][1] == 'l') ! added_libraries++; ! j++; } if (saw_libc) arglist[j++] = saw_libc; diff -Nrcpad gcc-3.4.3/gcc/cp/init.c gcc-4.0.0/gcc/cp/init.c *** gcc-3.4.3/gcc/cp/init.c Wed Jul 28 14:55:06 2004 --- gcc-4.0.0/gcc/cp/init.c Wed Apr 6 05:35:31 2005 *************** *** 1,6 **** /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,6 ---- /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 34,39 **** --- 34,40 ---- #include "output.h" #include "except.h" #include "toplev.h" + #include "target.h" static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); *************** static tree get_temp_regvar (tree, tree) *** 52,58 **** static tree dfs_initialize_vtbl_ptrs (tree, void *); static tree build_default_init (tree, tree); static tree build_new_1 (tree); - static tree get_cookie_size (tree); static tree build_dtor_call (tree, special_function_kind, int); static tree build_field_list (tree, tree, int *); static tree build_vtbl_address (tree); --- 53,58 ---- *************** begin_init_stmts (tree *stmt_expr_p, tre *** 72,78 **** bool is_global = !building_stmt_tree (); *stmt_expr_p = begin_stmt_expr (); ! *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/true); return is_global; } --- 72,78 ---- bool is_global = !building_stmt_tree (); *stmt_expr_p = begin_stmt_expr (); ! *compound_stmt_p = begin_compound_stmt (BCS_NO_SCOPE); return is_global; } *************** finish_init_stmts (bool is_global, tree *** 87,93 **** stmt_expr = finish_stmt_expr (stmt_expr, true); ! my_friendly_assert (!building_stmt_tree () == is_global, 20030726); return stmt_expr; } --- 87,93 ---- stmt_expr = finish_stmt_expr (stmt_expr, true); ! gcc_assert (!building_stmt_tree () == is_global); return stmt_expr; } *************** finish_init_stmts (bool is_global, tree *** 101,108 **** static tree dfs_initialize_vtbl_ptrs (tree binfo, void *data) { ! if ((!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) ! && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) { tree base_ptr = TREE_VALUE ((tree) data); --- 101,110 ---- static tree dfs_initialize_vtbl_ptrs (tree binfo, void *data) { ! if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) ! return dfs_skip_bases; ! ! if (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo)) { tree base_ptr = TREE_VALUE ((tree) data); *************** dfs_initialize_vtbl_ptrs (tree binfo, vo *** 111,118 **** expand_virtual_init (binfo, base_ptr); } - BINFO_MARKED (binfo) = 1; - return NULL_TREE; } --- 113,118 ---- *************** initialize_vtbl_ptrs (tree addr) *** 132,140 **** 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, ! NULL, unmarkedp, list); ! dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type); } /* Return an expression for the zero-initialization of an object with --- 132,138 ---- 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_once (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, NULL, list); } /* Return an expression for the zero-initialization of an object with *************** build_zero_init (tree type, tree nelts, *** 171,178 **** -- 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) ; --- 169,175 ---- -- if T is a reference type, no initialization is performed. */ ! gcc_assert (nelts == NULL_TREE || TREE_CODE (nelts) == INTEGER_CST); if (type == error_mark_node) ; *************** build_zero_init (tree type, tree nelts, *** 217,223 **** } else if (TREE_CODE (type) == ARRAY_TYPE) { - tree index; tree max_index; tree inits; --- 214,219 ---- *************** build_zero_init (tree type, tree nelts, *** 225,254 **** init = build_constructor (type, 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); /* A zero-sized array, which is accepted as an extension, will have an upper bound of -1. */ if (!tree_int_cst_equal (max_index, integer_minus_one_node)) ! 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) - ; else ! abort (); /* In all cases, the initializer is a constant. */ if (init) ! TREE_CONSTANT (init) = 1; return init; } --- 221,262 ---- init = build_constructor (type, NULL_TREE); /* Iterate over the array elements, building initializations. */ inits = NULL_TREE; ! if (nelts) ! max_index = fold (build2 (MINUS_EXPR, TREE_TYPE (nelts), ! nelts, integer_one_node)); ! else ! max_index = array_type_nelts (type); ! gcc_assert (TREE_CODE (max_index) == INTEGER_CST); /* A zero-sized array, which is accepted as an extension, will have an upper bound of -1. */ if (!tree_int_cst_equal (max_index, integer_minus_one_node)) ! { ! tree elt_init = build_zero_init (TREE_TYPE (type), ! /*nelts=*/NULL_TREE, ! static_storage_p); ! tree range; ! ! /* If this is a one element array, we just use a regular init. */ ! if (tree_int_cst_equal (size_zero_node, max_index)) ! range = size_zero_node; ! else ! range = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); ! ! inits = tree_cons (range, elt_init, inits); ! } ! CONSTRUCTOR_ELTS (init) = nreverse (inits); } else ! gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); /* In all cases, the initializer is a constant. */ if (init) ! { ! TREE_CONSTANT (init) = 1; ! TREE_INVARIANT (init) = 1; ! } return init; } *************** perform_member_init (tree member, tree i *** 315,323 **** /* 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; --- 323,330 ---- /* Effective C++ rule 12 requires that all data members be initialized. */ if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE) ! warning ("%J%qD should be initialized in the member initialization " ! "list", current_function_decl, member); if (init == void_type_node) init = NULL_TREE; *************** perform_member_init (tree member, tree i *** 336,347 **** { if (init) { ! init = build (INIT_EXPR, type, decl, TREE_VALUE (init)); finish_expr_stmt (init); } } ! else if (TYPE_NEEDS_CONSTRUCTING (type) ! || (init && TYPE_HAS_CONSTRUCTOR (type))) { if (explicit && TREE_CODE (type) == ARRAY_TYPE --- 343,353 ---- { if (init) { ! init = build2 (INIT_EXPR, type, decl, TREE_VALUE (init)); finish_expr_stmt (init); } } ! else if (TYPE_NEEDS_CONSTRUCTING (type)) { if (explicit && TREE_CODE (type) == ARRAY_TYPE *************** perform_member_init (tree member, tree i *** 364,379 **** { init = build_default_init (type, /*nelts=*/NULL_TREE); if (TREE_CODE (type) == REFERENCE_TYPE) ! warning ! ("default-initialization of `%#D', which has reference type", ! member); } /* member traversal: note it leaves init NULL */ else if (TREE_CODE (type) == REFERENCE_TYPE) ! pedwarn ("uninitialized reference member `%D'", member); else if (CP_TYPE_CONST_P (type)) ! pedwarn ("uninitialized member `%D' with `const' type `%T'", ! member, type); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work --- 370,386 ---- { init = build_default_init (type, /*nelts=*/NULL_TREE); if (TREE_CODE (type) == REFERENCE_TYPE) ! warning ("%Jdefault-initialization of %q#D, " ! "which has reference type", ! current_function_decl, member); } /* member traversal: note it leaves init NULL */ else if (TREE_CODE (type) == REFERENCE_TYPE) ! pedwarn ("%Juninitialized reference member %qD", ! current_function_decl, member); else if (CP_TYPE_CONST_P (type)) ! pedwarn ("%Juninitialized member %qD with % type %qT", ! current_function_decl, member, type); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work *************** static tree *** 455,463 **** sort_mem_initializers (tree t, tree mem_inits) { tree init; ! tree base; tree sorted_inits; tree next_subobject; int i; int uses_unions_p; --- 462,471 ---- sort_mem_initializers (tree t, tree mem_inits) { tree init; ! tree base, binfo, base_binfo; tree sorted_inits; tree next_subobject; + VEC (tree) *vbases; int i; int uses_unions_p; *************** sort_mem_initializers (tree t, tree mem_ *** 466,481 **** 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 --- 474,491 ---- TREE_VALUE will be the constructor arguments, or NULL if no explicit initialization was provided. */ sorted_inits = NULL_TREE; + /* Process the virtual bases. */ ! for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0; ! VEC_iterate (tree, vbases, i, base); i++) ! sorted_inits = tree_cons (base, NULL_TREE, sorted_inits); ! /* Process the direct bases. */ ! for (binfo = TYPE_BINFO (t), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) ! if (!BINFO_VIRTUAL_P (base_binfo)) ! sorted_inits = tree_cons (base_binfo, 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 *************** sort_mem_initializers (tree t, tree mem_ *** 507,526 **** break; /* Issue a warning if the explicit initializer order does not ! match that which will actually occur. */ if (warn_reorder && !subobject_init) { 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); ! warning (" when initialized here"); } /* Look again, from the beginning of the list. */ --- 517,537 ---- break; /* Issue a warning if the explicit initializer order does not ! match that which will actually occur. ! ??? Are all these on the correct lines? */ if (warn_reorder && !subobject_init) { if (TREE_CODE (TREE_PURPOSE (next_subobject)) == FIELD_DECL) ! cp_warning_at ("%qD will be initialized after", TREE_PURPOSE (next_subobject)); else ! warning ("base %qT will be initialized after", TREE_PURPOSE (next_subobject)); if (TREE_CODE (subobject) == FIELD_DECL) ! cp_warning_at (" %q#D", subobject); else ! warning (" base %qT", subobject); ! warning ("%J when initialized here", current_function_decl); } /* Look again, from the beginning of the list. */ *************** sort_mem_initializers (tree t, tree mem_ *** 536,545 **** if (TREE_VALUE (subobject_init)) { if (TREE_CODE (subobject) == FIELD_DECL) ! error ("multiple initializations given for `%D'", subobject); else ! error ("multiple initializations given for base `%T'", ! subobject); } /* Record the initialization. */ --- 547,557 ---- if (TREE_VALUE (subobject_init)) { if (TREE_CODE (subobject) == FIELD_DECL) ! error ("%Jmultiple initializations given for %qD", ! current_function_decl, subobject); else ! error ("%Jmultiple initializations given for base %qT", ! current_function_decl, subobject); } /* Record the initialization. */ *************** sort_mem_initializers (tree t, tree mem_ *** 605,612 **** if (same_type_p (last_field_type, field_type)) { if (TREE_CODE (field_type) == UNION_TYPE) ! error ("initializations for multiple members of `%T'", ! last_field_type); done = 1; break; } --- 617,624 ---- if (same_type_p (last_field_type, field_type)) { if (TREE_CODE (field_type) == UNION_TYPE) ! error ("%Jinitializations for multiple members of %qT", ! current_function_decl, last_field_type); done = 1; break; } *************** sort_mem_initializers (tree t, tree mem_ *** 643,648 **** --- 655,665 ---- void emit_mem_initializers (tree mem_inits) { + /* We will already have issued an error message about the fact that + the type is incomplete. */ + if (!COMPLETE_TYPE_P (current_class_type)) + return; + /* Sort the mem-initializers into the order in which the initializations should be performed. */ mem_inits = sort_mem_initializers (current_class_type, mem_inits); *************** emit_mem_initializers (tree mem_inits) *** 662,670 **** 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. */ --- 679,687 ---- if (extra_warnings && !arguments && DECL_COPY_CONSTRUCTOR_P (current_function_decl) && TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (subobject))) ! warning ("%Jbase class %q#T should be explicitly initialized in the " "copy constructor", ! current_function_decl, BINFO_TYPE (subobject)); /* If an explicit -- but empty -- initializer list was present, treat it just like default initialization at this point. */ *************** emit_mem_initializers (tree mem_inits) *** 672,678 **** arguments = NULL_TREE; /* Initialize the base. */ ! if (TREE_VIA_VIRTUAL (subobject)) construct_virtual_base (subobject, arguments); else { --- 689,695 ---- arguments = NULL_TREE; /* Initialize the base. */ ! if (BINFO_VIRTUAL_P (subobject)) construct_virtual_base (subobject, arguments); else { *************** build_vtbl_address (tree binfo) *** 712,726 **** tree binfo_for = binfo; tree vtbl; ! if (BINFO_VPTR_INDEX (binfo) && TREE_VIA_VIRTUAL (binfo) ! && BINFO_PRIMARY_P (binfo)) /* If this is a virtual primary base, then the vtable we want to store is that for the base this is being used as the primary base of. We can't simply skip the initialization, because we may be expanding the inits of a subobject constructor where the virtual base layout can be different. */ ! while (BINFO_PRIMARY_BASE_OF (binfo_for)) ! binfo_for = BINFO_PRIMARY_BASE_OF (binfo_for); /* Figure out what vtable BINFO's vtable is based on, and mark it as used. */ --- 729,742 ---- tree binfo_for = binfo; tree vtbl; ! if (BINFO_VPTR_INDEX (binfo) && BINFO_VIRTUAL_P (binfo)) /* If this is a virtual primary base, then the vtable we want to store is that for the base this is being used as the primary base of. We can't simply skip the initialization, because we may be expanding the inits of a subobject constructor where the virtual base layout can be different. */ ! while (BINFO_PRIMARY_P (binfo_for)) ! binfo_for = BINFO_INHERITANCE_CHAIN (binfo_for); /* Figure out what vtable BINFO's vtable is based on, and mark it as used. */ *************** build_vtbl_address (tree binfo) *** 729,740 **** TREE_USED (vtbl) = 1; /* Now compute the address to use when initializing the vptr. */ ! vtbl = BINFO_VTABLE (binfo_for); if (TREE_CODE (vtbl) == VAR_DECL) ! { ! vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); ! TREE_CONSTANT (vtbl) = 1; ! } return vtbl; } --- 745,753 ---- TREE_USED (vtbl) = 1; /* Now compute the address to use when initializing the vptr. */ ! vtbl = unshare_expr (BINFO_VTABLE (binfo_for)); if (TREE_CODE (vtbl) == VAR_DECL) ! vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); return vtbl; } *************** expand_virtual_init (tree binfo, tree de *** 764,790 **** /* Compute the value to use, when there's a VTT. */ vtt_parm = current_vtt_parm; ! vtbl2 = build (PLUS_EXPR, ! TREE_TYPE (vtt_parm), ! vtt_parm, ! vtt_index); ! vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject constructor. In maybe_clone_body we'll substitute NULL for the vtt_parm in the case of the non-subobject constructor. */ ! vtbl = build (COND_EXPR, ! TREE_TYPE (vtbl), ! build (EQ_EXPR, boolean_type_node, ! current_in_charge_parm, integer_zero_node), ! vtbl2, ! vtbl); } /* Compute the location of the vtpr. */ vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL), TREE_TYPE (binfo)); ! my_friendly_assert (vtbl_ptr != error_mark_node, 20010730); /* Assign the vtable to the vptr. */ vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); --- 777,804 ---- /* Compute the value to use, when there's a VTT. */ vtt_parm = current_vtt_parm; ! vtbl2 = build2 (PLUS_EXPR, ! TREE_TYPE (vtt_parm), ! vtt_parm, ! vtt_index); ! vtbl2 = build_indirect_ref (vtbl2, NULL); ! vtbl2 = convert (TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject constructor. In maybe_clone_body we'll substitute NULL for the vtt_parm in the case of the non-subobject constructor. */ ! vtbl = build3 (COND_EXPR, ! TREE_TYPE (vtbl), ! build2 (EQ_EXPR, boolean_type_node, ! current_in_charge_parm, integer_zero_node), ! vtbl2, ! vtbl); } /* Compute the location of the vtpr. */ vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL), TREE_TYPE (binfo)); ! gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); *************** expand_cleanup_for_base (tree binfo, tre *** 812,820 **** binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); if (flag) ! expr = fold (build (COND_EXPR, void_type_node, ! c_common_truthvalue_conversion (flag), ! expr, integer_zero_node)); finish_eh_cleanup (expr); } --- 826,834 ---- binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); if (flag) ! expr = fold (build3 (COND_EXPR, void_type_node, ! c_common_truthvalue_conversion (flag), ! expr, integer_zero_node)); finish_eh_cleanup (expr); } *************** static void *** 826,832 **** construct_virtual_base (tree vbase, tree arguments) { tree inner_if_stmt; - tree compound_stmt; tree exp; tree flag; --- 840,845 ---- *************** construct_virtual_base (tree vbase, tree *** 847,853 **** 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=*/true); /* Compute the location of the virtual base. If we're constructing virtual bases, then we must be the most derived --- 860,865 ---- *************** construct_virtual_base (tree vbase, tree *** 857,865 **** expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, LOOKUP_COMPLAIN); - finish_compound_stmt (compound_stmt); finish_then_clause (inner_if_stmt); ! finish_if_stmt (); expand_cleanup_for_base (vbase, flag); } --- 869,876 ---- expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, LOOKUP_COMPLAIN); finish_then_clause (inner_if_stmt); ! finish_if_stmt (inner_if_stmt); expand_cleanup_for_base (vbase, flag); } *************** member_init_ok_or_else (tree field, tree *** 892,917 **** return 0; if (!field) { ! error ("class `%T' does not have any field named `%D'", type, member_name); return 0; } if (TREE_CODE (field) == VAR_DECL) { ! error ("`%#D' is a static data member; it can only be " "initialized at its definition", field); return 0; } if (TREE_CODE (field) != FIELD_DECL) { ! error ("`%#D' is not a non-static data member of `%T'", field, type); return 0; } if (initializing_context (field) != type) { ! error ("class `%T' does not have any field named `%D'", type, member_name); return 0; } --- 903,928 ---- return 0; if (!field) { ! error ("class %qT does not have any field named %qD", type, member_name); return 0; } if (TREE_CODE (field) == VAR_DECL) { ! error ("%q#D is a static data member; it can only be " "initialized at its definition", field); return 0; } if (TREE_CODE (field) != FIELD_DECL) { ! error ("%q#D is not a non-static data member of %qT", field, type); return 0; } if (initializing_context (field) != type) { ! error ("class %qT does not have any field named %qD", type, member_name); return 0; } *************** expand_member_init (tree name) *** 941,957 **** { /* This is an obsolete unnamed base class initializer. The parser will already have warned about its use. */ ! switch (CLASSTYPE_N_BASECLASSES (current_class_type)) { case 0: ! error ("unnamed initializer for `%T', which has no base classes", current_class_type); return NULL_TREE; case 1: ! basetype = TYPE_BINFO_BASETYPE (current_class_type, 0); break; default: ! error ("unnamed initializer for `%T', which uses multiple inheritance", current_class_type); return NULL_TREE; } --- 952,969 ---- { /* This is an obsolete unnamed base class initializer. The parser will already have warned about its use. */ ! switch (BINFO_N_BASE_BINFOS (TYPE_BINFO (current_class_type))) { case 0: ! error ("unnamed initializer for %qT, which has no base classes", current_class_type); return NULL_TREE; case 1: ! basetype = BINFO_TYPE ! (BINFO_BASE_BINFO (TYPE_BINFO (current_class_type), 0)); break; default: ! error ("unnamed initializer for %qT, which uses multiple inheritance", current_class_type); return NULL_TREE; } *************** expand_member_init (tree name) *** 981,1003 **** virtual_binfo = NULL_TREE; /* Look for a direct base. */ ! for (i = 0; i < BINFO_N_BASETYPES (class_binfo); ++i) ! if (same_type_p (basetype, ! TYPE_BINFO_BASETYPE (current_class_type, i))) ! { ! direct_binfo = BINFO_BASETYPE (class_binfo, i); ! break; ! } /* Look for a virtual base -- unless the direct base is itself virtual. */ ! if (!direct_binfo || !TREE_VIA_VIRTUAL (direct_binfo)) ! { ! virtual_binfo ! = purpose_member (basetype, ! CLASSTYPE_VBASECLASSES (current_class_type)); ! if (virtual_binfo) ! virtual_binfo = TREE_VALUE (virtual_binfo); ! } /* [class.base.init] --- 993,1006 ---- virtual_binfo = NULL_TREE; /* Look for a direct base. */ ! for (i = 0; BINFO_BASE_ITERATE (class_binfo, i, direct_binfo); ++i) ! if (SAME_BINFO_TYPE_P (BINFO_TYPE (direct_binfo), basetype)) ! break; ! /* Look for a virtual base -- unless the direct base is itself virtual. */ ! if (!direct_binfo || !BINFO_VIRTUAL_P (direct_binfo)) ! virtual_binfo = binfo_for_vbase (basetype, current_class_type); /* [class.base.init] *************** expand_member_init (tree name) *** 1006,1023 **** base class, the mem-initializer is ill-formed. */ if (direct_binfo && virtual_binfo) { ! error ("'%D' is both a direct base and an indirect virtual base", basetype); return NULL_TREE; } if (!direct_binfo && !virtual_binfo) { ! if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! error ("type `%D' is not a direct or virtual base of `%T'", name, current_class_type); else ! error ("type `%D' is not a direct base of `%T'", name, current_class_type); return NULL_TREE; } --- 1009,1026 ---- base class, the mem-initializer is ill-formed. */ if (direct_binfo && virtual_binfo) { ! error ("%qD is both a direct base and an indirect virtual base", basetype); return NULL_TREE; } if (!direct_binfo && !virtual_binfo) { ! if (CLASSTYPE_VBASECLASSES (current_class_type)) ! error ("type %qD is not a direct or virtual base of %qT", name, current_class_type); else ! error ("type %qD is not a direct base of %qT", name, current_class_type); return NULL_TREE; } *************** build_aggr_init (tree exp, tree init, in *** 1091,1124 **** if (TREE_CODE (type) == ARRAY_TYPE) { ! /* Must arrange to initialize each element of EXP ! from elements of INIT. */ ! tree itype = init ? TREE_TYPE (init) : NULL_TREE; ! ! if (init && !itype) ! { ! /* Handle bad initializers like: ! class COMPLEX { ! public: ! double re, im; ! COMPLEX(double r = 0.0, double i = 0.0) {re = r; im = i;}; ! ~COMPLEX() {}; ! }; ! int main(int argc, char **argv) { ! COMPLEX zees(1.0, 0.0)[10]; ! } ! */ error ("bad array initializer"); return error_mark_node; } if (cp_type_quals (type) != TYPE_UNQUALIFIED) 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, NULL_TREE, init, ! init && same_type_p (TREE_TYPE (init), ! TREE_TYPE (exp))); TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; TREE_TYPE (exp) = type; --- 1094,1118 ---- if (TREE_CODE (type) == ARRAY_TYPE) { ! tree itype; ! /* An array may not be initialized use the parenthesized ! initialization form -- unless the initializer is "()". */ ! if (init && TREE_CODE (init) == TREE_LIST) ! { error ("bad array initializer"); return error_mark_node; } + /* Must arrange to initialize each element of EXP + from elements of INIT. */ + itype = init ? TREE_TYPE (init) : NULL_TREE; if (cp_type_quals (type) != TYPE_UNQUALIFIED) TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED) ! itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); stmt_expr = build_vec_init (exp, NULL_TREE, init, ! itype && same_type_p (itype, ! TREE_TYPE (exp))); TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; TREE_TYPE (exp) = type; *************** build_init (tree decl, tree init, int fl *** 1158,1167 **** else if (CLASS_TYPE_P (TREE_TYPE (decl))) expr = build_special_member_call (decl, complete_ctor_identifier, build_tree_list (NULL_TREE, init), ! TYPE_BINFO (TREE_TYPE (decl)), LOOKUP_NORMAL|flags); else ! expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init); return expr; } --- 1152,1161 ---- else if (CLASS_TYPE_P (TREE_TYPE (decl))) expr = build_special_member_call (decl, complete_ctor_identifier, build_tree_list (NULL_TREE, init), ! TREE_TYPE (decl), LOOKUP_NORMAL|flags); else ! expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init); return expr; } *************** expand_default_init (tree binfo, tree tr *** 1185,1192 **** && (flags & LOOKUP_ONLYCONVERTING)) { /* Base subobjects should only get direct-initialization. */ ! if (true_exp != exp) ! abort (); if (flags & DIRECT_BIND) /* Do nothing. We hit this in two cases: Reference initialization, --- 1179,1185 ---- && (flags & LOOKUP_ONLYCONVERTING)) { /* Base subobjects should only get direct-initialization. */ ! gcc_assert (true_exp == exp); if (flags & DIRECT_BIND) /* Do nothing. We hit this in two cases: Reference initialization, *************** expand_default_init (tree binfo, tree tr *** 1194,1204 **** 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 ! && 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 --- 1187,1196 ---- 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 (BRACE_ENCLOSED_INITIALIZER_P (init)) { /* A brace-enclosed initializer for an aggregate. */ ! gcc_assert (CP_AGGREGATE_TYPE_P (type)); init = digest_init (type, init, (tree *)NULL); } else *************** expand_default_init (tree binfo, tree tr *** 1210,1221 **** around the TARGET_EXPR for the copy constructor. See initialize_handler_parm. */ { ! TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp, ! TREE_OPERAND (init, 0)); TREE_TYPE (init) = void_type_node; } else ! init = build (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); return; --- 1202,1213 ---- around the TARGET_EXPR for the copy constructor. See initialize_handler_parm. */ { ! TREE_OPERAND (init, 0) = build2 (INIT_EXPR, TREE_TYPE (exp), exp, ! TREE_OPERAND (init, 0)); TREE_TYPE (init) = void_type_node; } else ! init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); return; *************** expand_aggr_init_1 (tree binfo, tree tru *** 1266,1273 **** { 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 --- 1258,1265 ---- { tree type = TREE_TYPE (exp); ! gcc_assert (init != error_mark_node && type != error_mark_node); ! gcc_assert (building_stmt_tree ()); /* Use a function returning the desired type to initialize EXP for us. If the function is a constructor, and its first argument is *************** is_aggr_type (tree type, int or_else) *** 1307,1348 **** && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM) { if (or_else) ! error ("`%T' is not an aggregate type", type); return 0; } return 1; } - /* Like is_aggr_typedef, but returns typedef if successful. */ - - tree - get_aggr_from_typedef (tree name, int or_else) - { - tree type; - - if (name == error_mark_node) - return NULL_TREE; - - if (IDENTIFIER_HAS_TYPE_VALUE (name)) - type = IDENTIFIER_TYPE_VALUE (name); - else - { - if (or_else) - error ("`%T' fails to be an aggregate typedef", name); - return NULL_TREE; - } - - if (! IS_AGGR_TYPE (type) - && TREE_CODE (type) != TEMPLATE_TYPE_PARM - && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM) - { - if (or_else) - error ("type `%T' is of non-aggregate type", type); - return NULL_TREE; - } - return type; - } - tree get_type_value (tree name) { --- 1299,1310 ---- && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM) { if (or_else) ! error ("%qT is not an aggregate type", type); return 0; } return 1; } tree get_type_value (tree name) { *************** build_offset_ref (tree type, tree name, *** 1399,1405 **** name = DECL_NAME (OVL_CURRENT (name)); } ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0); } if (type == NULL_TREE) --- 1361,1367 ---- name = DECL_NAME (OVL_CURRENT (name)); } ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); } if (type == NULL_TREE) *************** build_offset_ref (tree type, tree name, *** 1413,1420 **** return t; if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR) /* Reconstruct the TEMPLATE_ID_EXPR. */ ! t = build (TEMPLATE_ID_EXPR, TREE_TYPE (t), ! t, TREE_OPERAND (orig_name, 1)); if (! type_unknown_p (t)) { mark_used (t); --- 1375,1382 ---- return t; if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR) /* Reconstruct the TEMPLATE_ID_EXPR. */ ! t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t), ! t, TREE_OPERAND (orig_name, 1)); if (! type_unknown_p (t)) { mark_used (t); *************** build_offset_ref (tree type, tree name, *** 1429,1435 **** if (TREE_CODE (name) == BIT_NOT_EXPR) { if (! check_dtor_name (type, name)) ! error ("qualified type `%T' does not match destructor name `~%T'", type, TREE_OPERAND (name, 0)); name = dtor_identifier; } --- 1391,1397 ---- if (TREE_CODE (name) == BIT_NOT_EXPR) { if (! check_dtor_name (type, name)) ! error ("qualified type %qT does not match destructor name %<~%T%>", type, TREE_OPERAND (name, 0)); name = dtor_identifier; } *************** build_offset_ref (tree type, tree name, *** 1437,1444 **** if (!COMPLETE_TYPE_P (complete_type (type)) && !TYPE_BEING_DEFINED (type)) { ! error ("incomplete type `%T' does not have member `%D'", type, ! name); return error_mark_node; } --- 1399,1405 ---- if (!COMPLETE_TYPE_P (complete_type (type)) && !TYPE_BEING_DEFINED (type)) { ! error ("incomplete type %qT does not have member %qD", type, name); return error_mark_node; } *************** build_offset_ref (tree type, tree name, *** 1457,1474 **** if (!member) { ! error ("`%D' is not a member of type `%T'", name, type); return error_mark_node; } - if (processing_template_decl) - { - if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR) - return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name); - else - return build_min (SCOPE_REF, TREE_TYPE (member), type, name); - } - if (TREE_CODE (member) == TYPE_DECL) { TREE_USED (member) = 1; --- 1418,1427 ---- if (!member) { ! error ("%qD is not a member of type %qT", name, type); return error_mark_node; } if (TREE_CODE (member) == TYPE_DECL) { TREE_USED (member) = 1; *************** build_offset_ref (tree type, tree name, *** 1484,1490 **** if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) { ! error ("invalid pointer to bit-field `%D'", member); return error_mark_node; } --- 1437,1443 ---- if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) { ! error ("invalid pointer to bit-field %qD", member); return error_mark_node; } *************** build_offset_ref (tree type, tree name, *** 1509,1517 **** expects to encounter OVERLOADs, not raw functions. */ t = ovl_cons (t, NULL_TREE); ! t = build (TEMPLATE_ID_EXPR, TREE_TYPE (t), t, ! TREE_OPERAND (orig_name, 1)); ! t = build (OFFSET_REF, unknown_type_node, decl, t); PTRMEM_OK_P (t) = 1; --- 1462,1470 ---- expects to encounter OVERLOADs, not raw functions. */ t = ovl_cons (t, NULL_TREE); ! t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t), t, ! TREE_OPERAND (orig_name, 1)); ! t = build2 (OFFSET_REF, unknown_type_node, decl, t); PTRMEM_OK_P (t) = 1; *************** build_offset_ref (tree type, tree name, *** 1578,1584 **** /* Build a representation of a the qualified name suitable for use as the operand to "&" -- even though the "&" is not actually present. */ ! member = build (OFFSET_REF, TREE_TYPE (member), decl, member); /* In Microsoft mode, treat a non-static member function as if it were a pointer-to-member. */ if (flag_ms_extensions) --- 1531,1537 ---- /* Build a representation of a the qualified name suitable for use as the operand to "&" -- even though the "&" is not actually present. */ ! member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member); /* In Microsoft mode, treat a non-static member function as if it were a pointer-to-member. */ if (flag_ms_extensions) *************** build_offset_ref (tree type, tree name, *** 1586,1650 **** PTRMEM_OK_P (member) = 1; return build_unary_op (ADDR_EXPR, member, 0); } ! error ("invalid use of non-static member function `%D'", TREE_OPERAND (member, 1)); return member; } else if (TREE_CODE (member) == FIELD_DECL) { ! error ("invalid use of non-static data member `%D'", member); return error_mark_node; } return member; } ! /* In member functions, the form `type::name' is no longer ! equivalent to `this->type::name', at least not until ! resolve_offset_ref. */ ! member = build (OFFSET_REF, TREE_TYPE (member), decl, member); PTRMEM_OK_P (member) = 1; return member; } ! /* If DECL is a `const' declaration, and its value is a known ! constant, then return that value. */ tree ! decl_constant_value (tree decl) { ! /* When we build a COND_EXPR, we don't know whether it will be used ! as an lvalue or as an rvalue. If it is an lvalue, it's not safe ! to replace the second and third operands with their ! initializers. So, we do that here. */ ! if (TREE_CODE (decl) == COND_EXPR) ! { ! tree d1; ! tree d2; ! ! d1 = decl_constant_value (TREE_OPERAND (decl, 1)); ! d2 = decl_constant_value (TREE_OPERAND (decl, 2)); ! if (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2)) ! return build (COND_EXPR, ! TREE_TYPE (decl), ! TREE_OPERAND (decl, 0), d1, d2); ! } ! if (DECL_P (decl) ! && (/* Enumeration constants are constant. */ ! TREE_CODE (decl) == CONST_DECL /* And so are variables with a 'const' type -- unless they ! are also 'volatile'. */ ! || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))) && DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node ! /* This is invalid if initial value is not constant. ! If it has either a function call, a memory reference, ! or a variable, then re-evaluating it could give different results. */ ! && TREE_CONSTANT (DECL_INITIAL (decl)) ! /* Check for cases where this is sub-optimal, even though valid. */ ! && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) return DECL_INITIAL (decl); return decl; } --- 1539,1603 ---- PTRMEM_OK_P (member) = 1; return build_unary_op (ADDR_EXPR, member, 0); } ! error ("invalid use of non-static member function %qD", TREE_OPERAND (member, 1)); return member; } else if (TREE_CODE (member) == FIELD_DECL) { ! error ("invalid use of non-static data member %qD", member); return error_mark_node; } return member; } ! member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member); PTRMEM_OK_P (member) = 1; return member; } ! /* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by ! constant of integral or enumeration type, then return that value. ! These are those variables permitted in constant expressions by ! [5.19/1]. FIXME:If we did lazy folding, this could be localized. */ tree ! integral_constant_value (tree decl) { ! while ((TREE_CODE (decl) == CONST_DECL ! || (TREE_CODE (decl) == VAR_DECL ! /* And so are variables with a 'const' type -- unless they ! are also 'volatile'. */ ! && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)) ! && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))) ! && DECL_INITIAL (decl) ! && DECL_INITIAL (decl) != error_mark_node ! && TREE_TYPE (DECL_INITIAL (decl)) ! && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) ! decl = DECL_INITIAL (decl); ! return decl; ! } ! /* A more relaxed version of integral_constant_value, for which type ! is not considered. This is used by the common C/C++ code, and not ! directly by the C++ front end. */ ! tree ! decl_constant_value (tree decl) ! { ! if ((TREE_CODE (decl) == CONST_DECL ! || (TREE_CODE (decl) == VAR_DECL /* And so are variables with a 'const' type -- unless they ! are also 'volatile'. */ ! && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))) && DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node ! /* This is invalid if initial value is not constant. If it has ! either a function call, a memory reference, or a variable, ! then re-evaluating it could give different results. */ ! && TREE_CONSTANT (DECL_INITIAL (decl))) return DECL_INITIAL (decl); + return decl; } *************** build_builtin_delete_call (tree addr) *** 1659,1815 **** return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr)); } ! /* Generate a C++ "new" expression. DECL is either a TREE_LIST ! (which needs to go through some sort of groktypename) or it ! is the name of the class we are newing. INIT is an initialization value. ! It is either an EXPRLIST, an EXPR_NO_COMMAS, or something in braces. ! If INIT is void_type_node, it means do *not* call a constructor ! for this instance. ! ! For types with constructors, the data returned is initialized ! by the appropriate constructor. ! ! Whether the type has a constructor or not, if it has a pointer ! to a virtual function table, then that pointer is set up ! here. ! ! Unless I am mistaken, a call to new () will return initialized ! data regardless of whether the constructor itself is private or ! not. NOPE; new fails if the constructor is private (jcm). ! ! Note that build_new does nothing to assure that any special ! alignment requirements of the type are met. Rather, it leaves ! it up to malloc to do the right thing. Otherwise, folding to ! the right alignment cal cause problems if the user tries to later ! free the memory returned by `new'. ! ! PLACEMENT is the `placement' list for user-defined operator new (). */ tree ! build_new (tree placement, tree decl, tree init, int use_global_new) { ! tree type, rval; ! tree nelts = NULL_TREE, t; ! int has_array = 0; ! if (decl == error_mark_node) return error_mark_node; - if (TREE_CODE (decl) == TREE_LIST) - { - tree absdcl = TREE_VALUE (decl); - tree last_absdcl = NULL_TREE; - - if (current_function_decl - && DECL_CONSTRUCTOR_P (current_function_decl)) - my_friendly_assert (immediate_size_expand == 0, 19990926); - - nelts = integer_one_node; - - if (absdcl && TREE_CODE (absdcl) == CALL_EXPR) - abort (); - while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF) - { - last_absdcl = absdcl; - absdcl = TREE_OPERAND (absdcl, 0); - } - - if (absdcl && TREE_CODE (absdcl) == ARRAY_REF) - { - /* Probably meant to be a vec new. */ - tree this_nelts; - - while (TREE_OPERAND (absdcl, 0) - && TREE_CODE (TREE_OPERAND (absdcl, 0)) == ARRAY_REF) - { - last_absdcl = absdcl; - absdcl = TREE_OPERAND (absdcl, 0); - } - - has_array = 1; - this_nelts = TREE_OPERAND (absdcl, 1); - if (this_nelts != error_mark_node) - { - if (this_nelts == NULL_TREE) - error ("new of array type fails to specify size"); - else if (processing_template_decl) - { - nelts = this_nelts; - absdcl = TREE_OPERAND (absdcl, 0); - } - else - { - if (build_expr_type_conversion (WANT_INT | WANT_ENUM, - this_nelts, false) - == NULL_TREE) - pedwarn ("size in array new must have integral type"); - - this_nelts = save_expr (cp_convert (sizetype, this_nelts)); - absdcl = TREE_OPERAND (absdcl, 0); - if (this_nelts == integer_zero_node) - { - warning ("zero size array reserves no space"); - nelts = integer_zero_node; - } - else - nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts); - } - } - else - nelts = integer_zero_node; - } - - if (last_absdcl) - TREE_OPERAND (last_absdcl, 0) = absdcl; - else - TREE_VALUE (decl) = absdcl; - - type = groktypename (decl); - if (! type || type == error_mark_node) - return error_mark_node; - } - else if (TREE_CODE (decl) == IDENTIFIER_NODE) - { - if (IDENTIFIER_HAS_TYPE_VALUE (decl)) - { - /* An aggregate type. */ - type = IDENTIFIER_TYPE_VALUE (decl); - decl = TYPE_MAIN_DECL (type); - } - else - { - /* A builtin type. */ - decl = lookup_name (decl, 1); - my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215); - type = TREE_TYPE (decl); - } - } - else if (TREE_CODE (decl) == TYPE_DECL) - { - type = TREE_TYPE (decl); - } - else - { - type = decl; - decl = TYPE_MAIN_DECL (type); - } - if (processing_template_decl) { - if (has_array) - t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE), - build_min_nt (ARRAY_REF, NULL_TREE, nelts), - NULL_TREE); - else - t = type; - rval = build_min (NEW_EXPR, build_pointer_type (type), ! placement, t, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; return rval; } /* ``A reference cannot be created by the new operator. A reference is not an object (8.2.2, 8.4.3), so a pointer to it could not be returned by new.'' ARM 5.3.3 */ --- 1612,1653 ---- return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr)); } ! /* Generate a representation for a C++ "new" expression. PLACEMENT is ! a TREE_LIST of placement-new arguments (or NULL_TREE if none). If ! NELTS is NULL, TYPE is the type of the storage to be allocated. If ! NELTS is not NULL, then this is an array-new allocation; TYPE is ! the type of the elements in the array and NELTS is the number of ! elements in the array. INIT, if non-NULL, is the initializer for ! the new object. If USE_GLOBAL_NEW is true, then the user ! explicitly wrote "::new" rather than just "new". */ tree ! build_new (tree placement, tree type, tree nelts, tree init, ! int use_global_new) { ! tree rval; ! if (type == error_mark_node) return error_mark_node; if (processing_template_decl) { rval = build_min (NEW_EXPR, build_pointer_type (type), ! placement, type, nelts, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; return rval; } + if (nelts) + { + if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false)) + pedwarn ("size in array new must have integral type"); + nelts = save_expr (cp_convert (sizetype, nelts)); + if (nelts == integer_zero_node) + warning ("zero size array reserves no space"); + } + /* ``A reference cannot be created by the new operator. A reference is not an object (8.2.2, 8.4.3), so a pointer to it could not be returned by new.'' ARM 5.3.3 */ *************** build_new (tree placement, tree decl, tr *** 1825,1846 **** return error_mark_node; } ! /* When the object being created is an array, the new-expression yields a ! pointer to the initial element (if any) of the array. For example, ! both new int and new int[10] return an int*. 5.3.4. */ ! if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0) ! { ! nelts = array_type_nelts_top (type); ! has_array = 1; ! type = TREE_TYPE (type); ! } ! ! if (has_array) ! t = build_nt (ARRAY_REF, type, nelts); ! else ! t = type; ! ! rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; rval = build_new_1 (rval); --- 1663,1670 ---- return error_mark_node; } ! rval = build4 (NEW_EXPR, build_pointer_type (type), placement, type, ! nelts, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; rval = build_new_1 (rval); *************** build_new (tree placement, tree decl, tr *** 1849,1855 **** /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); ! TREE_NO_UNUSED_WARNING (rval) = 1; return rval; } --- 1673,1679 ---- /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); ! TREE_NO_WARNING (rval) = 1; return rval; } *************** build_java_class_ref (tree type) *** 1867,1873 **** { jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass")); if (jclass_node == NULL_TREE) ! fatal_error ("call to Java constructor, while `jclass' undefined"); jclass_node = TREE_TYPE (jclass_node); } --- 1691,1697 ---- { jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass")); if (jclass_node == NULL_TREE) ! fatal_error ("call to Java constructor, while % undefined"); jclass_node = TREE_TYPE (jclass_node); } *************** build_java_class_ref (tree type) *** 1896,1929 **** DECL_ARTIFICIAL (class_decl) = 1; DECL_IGNORED_P (class_decl) = 1; pushdecl_top_level (class_decl); ! make_decl_rtl (class_decl, NULL); } return class_decl; } - /* Returns the size of the cookie to use when allocating an array - whose elements have the indicated TYPE. Assumes that it is already - known that a cookie is needed. */ - - static tree - get_cookie_size (tree type) - { - tree cookie_size; - - /* We need to allocate an additional max (sizeof (size_t), alignof - (true_type)) bytes. */ - tree sizetype_size; - tree type_align; - - sizetype_size = size_in_bytes (sizetype); - type_align = size_int (TYPE_ALIGN_UNIT (type)); - if (INT_CST_LT_UNSIGNED (type_align, sizetype_size)) - cookie_size = sizetype_size; - else - cookie_size = type_align; - - return cookie_size; - } /* Called from cplus_expand_expr when expanding a NEW_EXPR. The return value is immediately handed to expand_expr. */ --- 1720,1730 ---- DECL_ARTIFICIAL (class_decl) = 1; DECL_IGNORED_P (class_decl) = 1; pushdecl_top_level (class_decl); ! make_decl_rtl (class_decl); } return class_decl; } /* Called from cplus_expand_expr when expanding a NEW_EXPR. The return value is immediately handed to expand_expr. */ *************** static tree *** 1932,1947 **** build_new_1 (tree exp) { tree placement, init; ! tree true_type, size, rval; /* The type of the new-expression. (This type is always a pointer type.) */ tree pointer_type; ! /* The type pointed to by POINTER_TYPE. */ tree type; ! /* The type being allocated. For "new T[...]" this will be an ! ARRAY_TYPE. */ ! tree full_type; ! /* A pointer type pointing to to the FULL_TYPE. */ tree full_pointer_type; tree outer_nelts = NULL_TREE; tree nelts = NULL_TREE; --- 1733,1762 ---- build_new_1 (tree exp) { tree placement, init; ! tree size, rval; ! /* True iff this is a call to "operator new[]" instead of just ! "operator new". */ ! bool array_p = false; ! /* True iff ARRAY_P is true and the bound of the array type is ! not necessarily a compile time constant. For example, VLA_P is ! true for "new int[f()]". */ ! bool vla_p = false; ! /* The type being allocated. If ARRAY_P is true, this will be an ! ARRAY_TYPE. */ ! tree full_type; ! /* If ARRAY_P is true, the element type of the array. This is an ! never ARRAY_TYPE; for something like "new int[3][4]", the ! ELT_TYPE is "int". If ARRAY_P is false, this is the same type as ! FULL_TYPE. */ ! tree elt_type; /* The type of the new-expression. (This type is always a pointer type.) */ tree pointer_type; ! /* The type pointed to by POINTER_TYPE. This type may be different ! from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an ! ARRAY_TYPE, but TYPE may be an ARRAY_TYPE. */ tree type; ! /* A pointer type pointing to the FULL_TYPE. */ tree full_pointer_type; tree outer_nelts = NULL_TREE; tree nelts = NULL_TREE; *************** build_new_1 (tree exp) *** 1951,1958 **** tree alloc_node; tree alloc_fn; tree cookie_expr, init_expr; - int has_array = 0; - enum tree_code code; int nothrow, check_new; /* Nonzero if the user wrote `::new' rather than just `new'. */ int globally_qualified_p; --- 1766,1771 ---- *************** build_new_1 (tree exp) *** 1977,2099 **** placement = TREE_OPERAND (exp, 0); type = TREE_OPERAND (exp, 1); ! init = TREE_OPERAND (exp, 2); globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp); ! if (TREE_CODE (type) == ARRAY_REF) { ! has_array = 1; ! nelts = outer_nelts = TREE_OPERAND (type, 1); ! type = TREE_OPERAND (type, 0); ! /* Use an incomplete array type to avoid VLA headaches. */ full_type = build_cplus_array_type (type, NULL_TREE); } else ! full_type = type; ! ! true_type = type; ! ! code = has_array ? VEC_NEW_EXPR : NEW_EXPR; /* If our base type is an array, then make sure we know how many elements it has. */ ! while (TREE_CODE (true_type) == ARRAY_TYPE) ! { ! tree this_nelts = array_type_nelts_top (true_type); ! nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts); ! true_type = TREE_TYPE (true_type); ! } ! if (!complete_type_or_else (true_type, exp)) return error_mark_node; ! if (TREE_CODE (true_type) == VOID_TYPE) { ! error ("invalid type `void' for new"); return error_mark_node; } ! if (abstract_virtuals_error (NULL_TREE, true_type)) return error_mark_node; ! is_initialized = (TYPE_NEEDS_CONSTRUCTING (type) || init); ! if (CP_TYPE_CONST_P (true_type) && !is_initialized) { ! error ("uninitialized const in `new' of `%#T'", true_type); return error_mark_node; } ! size = size_in_bytes (true_type); ! if (has_array) ! size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); /* Allocate the object. */ ! if (! placement && TYPE_FOR_JAVA (true_type)) { tree class_addr, alloc_decl; ! tree class_decl = build_java_class_ref (true_type); ! tree class_size = size_in_bytes (true_type); static const char alloc_name[] = "_Jv_AllocObject"; use_java_new = 1; if (!get_global_value_if_present (get_identifier (alloc_name), &alloc_decl)) { ! error ("call to Java constructor with `%s' undefined", alloc_name); return error_mark_node; } else if (really_overloaded_fn (alloc_decl)) { ! error ("`%D' should never be overloaded", alloc_decl); return error_mark_node; } alloc_decl = OVL_CURRENT (alloc_decl); class_addr = build1 (ADDR_EXPR, jclass_node, class_decl); alloc_call = (build_function_call (alloc_decl, ! tree_cons (NULL_TREE, class_addr, ! build_tree_list (NULL_TREE, class_size)))); } else { tree fnname; tree fns; ! fnname = ansi_opname (code); if (!globally_qualified_p ! && CLASS_TYPE_P (true_type) ! && (has_array ! ? TYPE_HAS_ARRAY_NEW_OPERATOR (true_type) ! : TYPE_HAS_NEW_OPERATOR (true_type))) { /* Use a class-specific operator new. */ /* If a cookie is required, add some extra space. */ ! if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)) { ! cookie_size = get_cookie_size (true_type); size = size_binop (PLUS_EXPR, size, cookie_size); } /* Create the argument list. */ args = tree_cons (NULL_TREE, size, placement); /* Do name-lookup to find the appropriate operator. */ ! fns = lookup_fnfields (true_type, fnname, /*protect=*/2); ! if (!fns) ! { ! /* See PR 15967. This should never happen (and it is ! fixed correctly in mainline), but on the release branch ! we prefer this less-intrusive approacch. */ ! error ("no suitable or ambiguous `%D' found in class `%T'", ! fnname, true_type); ! return error_mark_node; ! } if (TREE_CODE (fns) == TREE_LIST) { ! error ("request for member `%D' is ambiguous", fnname); print_candidates (fns); return error_mark_node; } ! alloc_call = build_new_method_call (build_dummy_object (true_type), fns, args, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL); --- 1790,1929 ---- placement = TREE_OPERAND (exp, 0); type = TREE_OPERAND (exp, 1); ! nelts = TREE_OPERAND (exp, 2); ! init = TREE_OPERAND (exp, 3); globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp); ! if (nelts) { ! tree index; ! outer_nelts = nelts; ! array_p = true; ! ! /* ??? The middle-end will error on us for building a VLA outside a ! function context. Methinks that's not it's purvey. So we'll do ! our own VLA layout later. */ ! vla_p = true; full_type = build_cplus_array_type (type, NULL_TREE); + index = convert (sizetype, nelts); + index = size_binop (MINUS_EXPR, index, size_one_node); + TYPE_DOMAIN (full_type) = build_index_type (index); } else ! { ! full_type = type; ! if (TREE_CODE (type) == ARRAY_TYPE) ! { ! array_p = true; ! nelts = array_type_nelts_top (type); ! outer_nelts = nelts; ! type = TREE_TYPE (type); ! } ! } /* If our base type is an array, then make sure we know how many elements it has. */ ! for (elt_type = type; ! TREE_CODE (elt_type) == ARRAY_TYPE; ! elt_type = TREE_TYPE (elt_type)) ! nelts = cp_build_binary_op (MULT_EXPR, nelts, ! array_type_nelts_top (elt_type)); ! if (!complete_type_or_else (elt_type, exp)) return error_mark_node; ! if (TREE_CODE (elt_type) == VOID_TYPE) { ! error ("invalid type % for new"); return error_mark_node; } ! if (abstract_virtuals_error (NULL_TREE, elt_type)) return error_mark_node; ! is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init); ! if (CP_TYPE_CONST_P (elt_type) && !is_initialized) { ! error ("uninitialized const in % of %q#T", elt_type); return error_mark_node; } ! size = size_in_bytes (elt_type); ! if (array_p) ! { ! size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); ! if (vla_p) ! { ! tree n, bitsize; ! ! /* Do our own VLA layout. Setting TYPE_SIZE/_UNIT is ! necessary in order for the > to be valid. */ ! TYPE_SIZE_UNIT (full_type) = size; ! n = convert (bitsizetype, nelts); ! bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n); ! TYPE_SIZE (full_type) = bitsize; ! } ! } /* Allocate the object. */ ! if (! placement && TYPE_FOR_JAVA (elt_type)) { tree class_addr, alloc_decl; ! tree class_decl = build_java_class_ref (elt_type); static const char alloc_name[] = "_Jv_AllocObject"; + use_java_new = 1; + alloc_decl = NULL; if (!get_global_value_if_present (get_identifier (alloc_name), &alloc_decl)) { ! error ("call to Java constructor with %qs undefined", alloc_name); return error_mark_node; } else if (really_overloaded_fn (alloc_decl)) { ! error ("%qD should never be overloaded", alloc_decl); return error_mark_node; } alloc_decl = OVL_CURRENT (alloc_decl); class_addr = build1 (ADDR_EXPR, jclass_node, class_decl); alloc_call = (build_function_call (alloc_decl, ! build_tree_list (NULL_TREE, class_addr))); } else { tree fnname; tree fns; ! fnname = ansi_opname (array_p ? VEC_NEW_EXPR : NEW_EXPR); if (!globally_qualified_p ! && CLASS_TYPE_P (elt_type) ! && (array_p ! ? TYPE_HAS_ARRAY_NEW_OPERATOR (elt_type) ! : TYPE_HAS_NEW_OPERATOR (elt_type))) { /* Use a class-specific operator new. */ /* If a cookie is required, add some extra space. */ ! if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) { ! cookie_size = targetm.cxx.get_cookie_size (elt_type); size = size_binop (PLUS_EXPR, size, cookie_size); } /* Create the argument list. */ args = tree_cons (NULL_TREE, size, placement); /* Do name-lookup to find the appropriate operator. */ ! fns = lookup_fnfields (elt_type, fnname, /*protect=*/2); if (TREE_CODE (fns) == TREE_LIST) { ! error ("request for member %qD is ambiguous", fnname); print_candidates (fns); return error_mark_node; } ! alloc_call = build_new_method_call (build_dummy_object (elt_type), fns, args, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL); *************** build_new_1 (tree exp) *** 2102,2109 **** { /* Use a global operator new. */ /* See if a cookie might be required. */ ! if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)) ! cookie_size = get_cookie_size (true_type); else cookie_size = NULL_TREE; --- 1932,1939 ---- { /* Use a global operator new. */ /* See if a cookie might be required. */ ! if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) ! cookie_size = targetm.cxx.get_cookie_size (elt_type); else cookie_size = NULL_TREE; *************** build_new_1 (tree exp) *** 2131,2137 **** while (TREE_CODE (alloc_call) == COMPOUND_EXPR) alloc_call = TREE_OPERAND (alloc_call, 1); alloc_fn = get_callee_fndecl (alloc_call); ! my_friendly_assert (alloc_fn != NULL_TREE, 20020325); /* Now, check to see if this function is actually a placement allocation function. This can happen even when PLACEMENT is NULL --- 1961,1967 ---- while (TREE_CODE (alloc_call) == COMPOUND_EXPR) alloc_call = TREE_OPERAND (alloc_call, 1); alloc_fn = get_callee_fndecl (alloc_call); ! gcc_assert (alloc_fn != NULL_TREE); /* Now, check to see if this function is actually a placement allocation function. This can happen even when PLACEMENT is NULL *************** build_new_1 (tree exp) *** 2154,2161 **** tree inits; stabilize_call (alloc_call, &inits); if (inits) ! alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits, ! alloc_expr); } /* unless an allocation function is declared with an empty excep- --- 1984,1991 ---- tree inits; stabilize_call (alloc_call, &inits); if (inits) ! alloc_expr = build2 (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits, ! alloc_expr); } /* unless an allocation function is declared with an empty excep- *************** build_new_1 (tree exp) *** 2174,2192 **** if (cookie_size) { tree cookie; /* Adjust so we're pointing to the start of the object. */ ! data_addr = get_target_expr (build (PLUS_EXPR, full_pointer_type, ! alloc_node, cookie_size)); /* Store the number of bytes allocated so that we can know how many elements to destroy later. We use the last sizeof (size_t) bytes to store the number of elements. */ ! cookie = build (MINUS_EXPR, build_pointer_type (sizetype), ! data_addr, size_in_bytes (sizetype)); ! cookie = build_indirect_ref (cookie, NULL); ! cookie_expr = build (MODIFY_EXPR, sizetype, cookie, nelts); data_addr = TARGET_EXPR_SLOT (data_addr); } else --- 2004,2035 ---- if (cookie_size) { tree cookie; + tree cookie_ptr; /* Adjust so we're pointing to the start of the object. */ ! data_addr = get_target_expr (build2 (PLUS_EXPR, full_pointer_type, ! alloc_node, cookie_size)); /* Store the number of bytes allocated so that we can know how many elements to destroy later. We use the last sizeof (size_t) bytes to store the number of elements. */ ! cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype), ! data_addr, size_in_bytes (sizetype)); ! cookie = build_indirect_ref (cookie_ptr, NULL); ! cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts); ! ! if (targetm.cxx.cookie_has_size ()) ! { ! /* Also store the element size. */ ! cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype), ! cookie_ptr, size_in_bytes (sizetype)); ! cookie = build_indirect_ref (cookie_ptr, NULL); ! cookie = build2 (MODIFY_EXPR, sizetype, cookie, ! size_in_bytes(elt_type)); ! cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr), ! cookie, cookie_expr); ! } data_addr = TARGET_EXPR_SLOT (data_addr); } else *************** build_new_1 (tree exp) *** 2208,2217 **** if (init == void_zero_node) init = build_default_init (full_type, nelts); ! else if (init && has_array) pedwarn ("ISO C++ forbids initialization in array new"); ! if (has_array) { init_expr = build_vec_init (init_expr, --- 2051,2060 ---- if (init == void_zero_node) init = build_default_init (full_type, nelts); ! else if (init && array_p) pedwarn ("ISO C++ forbids initialization in array new"); ! if (array_p) { init_expr = build_vec_init (init_expr, *************** build_new_1 (tree exp) *** 2228,2234 **** { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, ! init, TYPE_BINFO (true_type), LOOKUP_NORMAL); stable = stabilize_init (init_expr, &init_preeval_expr); } --- 2071,2077 ---- { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, ! init, elt_type, LOOKUP_NORMAL); stable = stabilize_init (init_expr, &init_preeval_expr); } *************** build_new_1 (tree exp) *** 2240,2248 **** if (TREE_CODE (init) == TREE_LIST) init = build_x_compound_expr_from_list (init, "new initializer"); ! else if (TREE_CODE (init) == CONSTRUCTOR ! && TREE_TYPE (init) == NULL_TREE) ! abort (); init_expr = build_modify_expr (init_expr, INIT_EXPR, init); stable = stabilize_init (init_expr, &init_preeval_expr); --- 2083,2091 ---- if (TREE_CODE (init) == TREE_LIST) init = build_x_compound_expr_from_list (init, "new initializer"); ! else ! gcc_assert (TREE_CODE (init) != CONSTRUCTOR ! || TREE_TYPE (init) != NULL_TREE); init_expr = build_modify_expr (init_expr, INIT_EXPR, init); stable = stabilize_init (init_expr, &init_preeval_expr); *************** build_new_1 (tree exp) *** 2261,2277 **** freed. */ if (flag_exceptions && ! use_java_new) { ! enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR; tree cleanup; - int flags = (LOOKUP_NORMAL - | (globally_qualified_p * LOOKUP_GLOBAL)); /* The Standard is unclear here, but the right thing to do is to use the same method for finding deallocation functions that we use for finding allocation functions. */ ! flags |= LOOKUP_SPECULATIVELY; ! ! cleanup = build_op_delete_call (dcode, alloc_node, size, flags, (placement_allocation_fn_p ? alloc_call : NULL_TREE)); --- 2104,2117 ---- freed. */ if (flag_exceptions && ! use_java_new) { ! enum tree_code dcode = array_p ? VEC_DELETE_EXPR : DELETE_EXPR; tree cleanup; /* The Standard is unclear here, but the right thing to do is to use the same method for finding deallocation functions that we use for finding allocation functions. */ ! cleanup = build_op_delete_call (dcode, alloc_node, size, ! globally_qualified_p, (placement_allocation_fn_p ? alloc_call : NULL_TREE)); *************** build_new_1 (tree exp) *** 2280,2287 **** else if (stable) /* This is much simpler if we were able to preevaluate all of the arguments to the constructor call. */ ! init_expr = build (TRY_CATCH_EXPR, void_type_node, ! init_expr, cleanup); else /* Ack! First we allocate the memory. Then we set our sentry variable to true, and expand a cleanup that deletes the --- 2120,2127 ---- else if (stable) /* This is much simpler if we were able to preevaluate all of the arguments to the constructor call. */ ! init_expr = build2 (TRY_CATCH_EXPR, void_type_node, ! init_expr, cleanup); else /* Ack! First we allocate the memory. Then we set our sentry variable to true, and expand a cleanup that deletes the *************** build_new_1 (tree exp) *** 2302,2317 **** sentry = TARGET_EXPR_SLOT (begin); TARGET_EXPR_CLEANUP (begin) ! = build (COND_EXPR, void_type_node, sentry, ! cleanup, void_zero_node); ! end = build (MODIFY_EXPR, TREE_TYPE (sentry), ! sentry, boolean_false_node); init_expr ! = build (COMPOUND_EXPR, void_type_node, begin, ! build (COMPOUND_EXPR, void_type_node, init_expr, ! end)); } } --- 2142,2157 ---- sentry = TARGET_EXPR_SLOT (begin); TARGET_EXPR_CLEANUP (begin) ! = build3 (COND_EXPR, void_type_node, sentry, ! cleanup, void_zero_node); ! end = build2 (MODIFY_EXPR, TREE_TYPE (sentry), ! sentry, boolean_false_node); init_expr ! = build2 (COMPOUND_EXPR, void_type_node, begin, ! build2 (COMPOUND_EXPR, void_type_node, init_expr, ! end)); } } *************** build_new_1 (tree exp) *** 2324,2332 **** rval = data_addr; if (init_expr) ! rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_expr, rval); if (cookie_expr) ! rval = build (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval); if (rval == alloc_node) /* If we don't have an initializer or a cookie, strip the TARGET_EXPR --- 2164,2172 ---- rval = data_addr; if (init_expr) ! rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_expr, rval); if (cookie_expr) ! rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval); if (rval == alloc_node) /* If we don't have an initializer or a cookie, strip the TARGET_EXPR *************** build_new_1 (tree exp) *** 2343,2353 **** /* Perform the allocation before anything else, so that ALLOC_NODE has been initialized before we start using it. */ ! rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); } if (init_preeval_expr) ! rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval); /* Convert to the final type. */ rval = build_nop (pointer_type, rval); --- 2183,2193 ---- /* Perform the allocation before anything else, so that ALLOC_NODE has been initialized before we start using it. */ ! rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); } if (init_preeval_expr) ! rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval); /* Convert to the final type. */ rval = build_nop (pointer_type, rval); *************** build_vec_delete_1 (tree base, tree maxi *** 2387,2394 **** tree controller = NULL_TREE; /* We should only have 1-D arrays here. */ ! if (TREE_CODE (type) == ARRAY_TYPE) ! abort (); if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) goto no_destructor; --- 2227,2233 ---- tree controller = NULL_TREE; /* We should only have 1-D arrays here. */ ! gcc_assert (TREE_CODE (type) != ARRAY_TYPE); if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) goto no_destructor; *************** build_vec_delete_1 (tree base, tree maxi *** 2399,2421 **** tbase = create_temporary_var (ptype); tbase_init = build_modify_expr (tbase, NOP_EXPR, ! fold (build (PLUS_EXPR, ptype, ! base, ! virtual_size))); DECL_REGISTER (tbase) = 1; ! controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; ! body = build (EXIT_EXPR, void_type_node, ! build (EQ_EXPR, boolean_type_node, base, tbase)); body = build_compound_expr (body, build_modify_expr (tbase, NOP_EXPR, ! build (MINUS_EXPR, ptype, tbase, size_exp))); body = build_compound_expr (body, build_delete (ptype, tbase, sfk_complete_destructor, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1)); ! loop = build (LOOP_EXPR, void_type_node, body); loop = build_compound_expr (tbase_init, loop); no_destructor: --- 2238,2261 ---- tbase = create_temporary_var (ptype); tbase_init = build_modify_expr (tbase, NOP_EXPR, ! fold (build2 (PLUS_EXPR, ptype, ! base, ! virtual_size))); DECL_REGISTER (tbase) = 1; ! controller = build3 (BIND_EXPR, void_type_node, tbase, ! NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; ! body = build1 (EXIT_EXPR, void_type_node, ! build2 (EQ_EXPR, boolean_type_node, base, tbase)); body = build_compound_expr (body, build_modify_expr (tbase, NOP_EXPR, ! build2 (MINUS_EXPR, ptype, tbase, size_exp))); body = build_compound_expr (body, build_delete (ptype, tbase, sfk_complete_destructor, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1)); ! loop = build1 (LOOP_EXPR, void_type_node, body); loop = build_compound_expr (tbase_init, loop); no_destructor: *************** build_vec_delete_1 (tree base, tree maxi *** 2436,2442 **** { tree cookie_size; ! cookie_size = get_cookie_size (type); base_tbd = cp_convert (ptype, cp_build_binary_op (MINUS_EXPR, --- 2276,2282 ---- { tree cookie_size; ! cookie_size = targetm.cxx.get_cookie_size (type); base_tbd = cp_convert (ptype, cp_build_binary_op (MINUS_EXPR, *************** build_vec_delete_1 (tree base, tree maxi *** 2465,2474 **** body = integer_zero_node; /* Outermost wrapper: If pointer is null, punt. */ ! body = fold (build (COND_EXPR, void_type_node, ! fold (build (NE_EXPR, boolean_type_node, base, ! integer_zero_node)), ! body, integer_zero_node)); body = build1 (NOP_EXPR, void_type_node, body); if (controller) --- 2305,2315 ---- body = integer_zero_node; /* Outermost wrapper: If pointer is null, punt. */ ! body = fold (build3 (COND_EXPR, void_type_node, ! fold (build2 (NE_EXPR, boolean_type_node, base, ! convert (TREE_TYPE (base), ! integer_zero_node))), ! body, integer_zero_node)); body = build1 (NOP_EXPR, void_type_node, body); if (controller) *************** build_vec_delete_1 (tree base, tree maxi *** 2479,2485 **** if (TREE_CODE (base) == SAVE_EXPR) /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */ ! body = build (COMPOUND_EXPR, void_type_node, base, body); return convert_to_void (body, /*implicit=*/NULL); } --- 2320,2326 ---- if (TREE_CODE (base) == SAVE_EXPR) /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */ ! body = build2 (COMPOUND_EXPR, void_type_node, base, body); return convert_to_void (body, /*implicit=*/NULL); } *************** create_temporary_var (tree type) *** 2494,2501 **** decl = build_decl (VAR_DECL, NULL_TREE, type); TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; - DECL_SOURCE_LOCATION (decl) = input_location; DECL_IGNORED_P (decl) = 1; DECL_CONTEXT (decl) = current_function_decl; return decl; --- 2335,2342 ---- decl = build_decl (VAR_DECL, NULL_TREE, type); TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; + DECL_SOURCE_LOCATION (decl) = input_location; DECL_CONTEXT (decl) = current_function_decl; return decl; *************** get_temp_regvar (tree type, tree init) *** 2514,2520 **** tree decl; decl = create_temporary_var (type); ! add_decl_stmt (decl); finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); --- 2355,2361 ---- tree decl; decl = create_temporary_var (type); ! add_decl_expr (decl); finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); *************** build_vec_init (tree base, tree maxindex *** 2549,2561 **** tree atype = TREE_TYPE (base); /* The type of an element in the array. */ tree type = TREE_TYPE (atype); /* The type of a pointer to an element in the array. */ tree ptype; tree stmt_expr; tree compound_stmt; int destroy_temps; tree try_block = NULL_TREE; - tree try_body = NULL_TREE; int num_initialized_elts = 0; bool is_global; --- 2390,2404 ---- tree atype = TREE_TYPE (base); /* The type of an element in the array. */ tree type = TREE_TYPE (atype); + /* The element type reached after removing all outer array + types. */ + tree inner_elt_type; /* The type of a pointer to an element in the array. */ tree ptype; tree stmt_expr; tree compound_stmt; int destroy_temps; tree try_block = NULL_TREE; int num_initialized_elts = 0; bool is_global; *************** build_vec_init (tree base, tree maxindex *** 2565,2586 **** if (maxindex == NULL_TREE || maxindex == error_mark_node) return error_mark_node; 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. */ && (CONSTRUCTOR_ELTS (init) == NULL_TREE ! || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (target_type (type)))) || from_array)) { /* Do non-default initialization of POD arrays resulting from brace-enclosed initializers. In this case, digest_init and store_constructor will handle the semantics for us. */ ! stmt_expr = build (INIT_EXPR, atype, base, init); return stmt_expr; } --- 2408,2431 ---- if (maxindex == NULL_TREE || maxindex == error_mark_node) return error_mark_node; + inner_elt_type = strip_array_types (atype); if (init && (from_array == 2 ! ? (!CLASS_TYPE_P (inner_elt_type) ! || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_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. */ && (CONSTRUCTOR_ELTS (init) == NULL_TREE ! || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type))) || from_array)) { /* Do non-default initialization of POD arrays resulting from brace-enclosed initializers. In this case, digest_init and store_constructor will handle the semantics for us. */ ! stmt_expr = build2 (INIT_EXPR, atype, base, init); return stmt_expr; } *************** build_vec_init (tree base, tree maxindex *** 2634,2640 **** && from_array != 2) { try_block = begin_try_block (); - try_body = begin_compound_stmt (/*has_no_scope=*/true); } if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) --- 2479,2484 ---- *************** build_vec_init (tree base, tree maxindex *** 2703,2722 **** /* If the ITERATOR is equal to -1, then we don't have to loop; we've already initialized all the elements. */ tree for_stmt; - tree for_body; tree elt_init; for_stmt = begin_for_stmt (); finish_for_init_stmt (for_stmt); ! finish_for_cond (build (NE_EXPR, boolean_type_node, ! iterator, integer_minus_one_node), for_stmt); finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0), for_stmt); - /* Otherwise, loop through the elements. */ - for_body = begin_compound_stmt (/*has_no_scope=*/true); - if (from_array) { tree to = build1 (INDIRECT_REF, type, base); --- 2547,2562 ---- /* If the ITERATOR is equal to -1, then we don't have to loop; we've already initialized all the elements. */ tree for_stmt; tree elt_init; for_stmt = begin_for_stmt (); finish_for_init_stmt (for_stmt); ! finish_for_cond (build2 (NE_EXPR, boolean_type_node, ! iterator, integer_minus_one_node), for_stmt); finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0), for_stmt); if (from_array) { tree to = build1 (INDIRECT_REF, type, base); *************** build_vec_init (tree base, tree maxindex *** 2734,2740 **** else if (from) elt_init = build_modify_expr (to, NOP_EXPR, from); else ! abort (); } else if (TREE_CODE (type) == ARRAY_TYPE) { --- 2574,2580 ---- else if (from) elt_init = build_modify_expr (to, NOP_EXPR, from); else ! gcc_unreachable (); } else if (TREE_CODE (type) == ARRAY_TYPE) { *************** build_vec_init (tree base, tree maxindex *** 2756,2762 **** if (base2) finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0)); - finish_compound_stmt (for_body); finish_for_stmt (for_stmt); } --- 2596,2601 ---- *************** build_vec_init (tree base, tree maxindex *** 2770,2791 **** /* Flatten multi-dimensional array since build_vec_delete only expects one-dimensional array. */ if (TREE_CODE (type) == ARRAY_TYPE) ! { ! m = cp_build_binary_op (MULT_EXPR, m, ! array_type_nelts_total (type)); ! type = strip_array_types (type); ! } - finish_compound_stmt (try_body); finish_cleanup_try_block (try_block); ! e = build_vec_delete_1 (rval, m, type, sfk_base_destructor, /*use_global_delete=*/0); finish_cleanup (e, try_block); } /* The value of the array initialization is the array itself, RVAL is a pointer to the first element. */ ! finish_stmt_expr_expr (rval); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); --- 2609,2627 ---- /* Flatten multi-dimensional array since build_vec_delete only expects one-dimensional array. */ if (TREE_CODE (type) == ARRAY_TYPE) ! m = cp_build_binary_op (MULT_EXPR, m, ! array_type_nelts_total (type)); finish_cleanup_try_block (try_block); ! e = build_vec_delete_1 (rval, m, ! inner_elt_type, sfk_base_destructor, /*use_global_delete=*/0); finish_cleanup (e, try_block); } /* The value of the array initialization is the array itself, RVAL is a pointer to the first element. */ ! finish_stmt_expr_expr (rval, stmt_expr); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); *************** build_x_delete (tree addr, int which_del *** 2818,2826 **** int use_global_delete = which_delete & 1; int use_vec_delete = !!(which_delete & 2); enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; - int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL); ! return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE); } /* Call the DTOR_KIND destructor for EXP. FLAGS are as for --- 2654,2662 ---- int use_global_delete = which_delete & 1; int use_vec_delete = !!(which_delete & 2); enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; ! return build_op_delete_call (code, addr, virtual_size, use_global_delete, ! NULL_TREE); } /* Call the DTOR_KIND destructor for EXP. FLAGS are as for *************** build_dtor_call (tree exp, special_funct *** 2846,2855 **** break; default: ! abort (); } - - exp = convert_from_reference (exp); fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2); return build_new_method_call (exp, fn, /*args=*/NULL_TREE, --- 2682,2689 ---- break; default: ! gcc_unreachable (); } fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2); return build_new_method_call (exp, fn, /*args=*/NULL_TREE, *************** build_delete (tree type, tree addr, spec *** 2943,2949 **** addr = convert_force (build_pointer_type (type), addr, 0); } ! my_friendly_assert (IS_AGGR_TYPE (type), 220); if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) { --- 2777,2783 ---- addr = convert_force (build_pointer_type (type), addr, 0); } ! gcc_assert (IS_AGGR_TYPE (type)); if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) { *************** build_delete (tree type, tree addr, spec *** 2951,2958 **** return void_zero_node; return build_op_delete_call ! (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), ! LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL), NULL_TREE); } else --- 2785,2791 ---- return void_zero_node; return build_op_delete_call ! (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete, NULL_TREE); } else *************** build_delete (tree type, tree addr, spec *** 2960,2966 **** tree do_delete = NULL_TREE; tree ifexp; ! my_friendly_assert (TYPE_HAS_DESTRUCTOR (type), 20011213); /* For `::delete x', we must not use the deleting destructor since then we would not be sure to get the global `operator --- 2793,2800 ---- tree do_delete = NULL_TREE; tree ifexp; ! if (CLASSTYPE_LAZY_DESTRUCTOR (type)) ! lazily_declare_fn (sfk_destructor, type); /* For `::delete x', we must not use the deleting destructor since then we would not be sure to get the global `operator *************** build_delete (tree type, tree addr, spec *** 2987,2993 **** do_delete = build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), ! LOOKUP_NORMAL, NULL_TREE); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; --- 2821,2827 ---- do_delete = build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), ! /*global_p=*/false, NULL_TREE); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; *************** build_delete (tree type, tree addr, spec *** 2998,3010 **** /* 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, cxx_sizeof_nowarn (type), ! LOOKUP_NORMAL, NULL_TREE); } expr = build_dtor_call (build_indirect_ref (addr, NULL), auto_delete, flags); if (do_delete) ! expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); if (flags & LOOKUP_DESTRUCTOR) /* Explicit destructor call; don't check for null pointer. */ --- 2832,2844 ---- /* 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, cxx_sizeof_nowarn (type), ! /*global_p=*/false, NULL_TREE); } expr = build_dtor_call (build_indirect_ref (addr, NULL), auto_delete, flags); if (do_delete) ! expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete); if (flags & LOOKUP_DESTRUCTOR) /* Explicit destructor call; don't check for null pointer. */ *************** build_delete (tree type, tree addr, spec *** 3014,3021 **** ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node)); if (ifexp != integer_one_node) ! expr = build (COND_EXPR, void_type_node, ! ifexp, expr, void_zero_node); return expr; } --- 2848,2855 ---- ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node)); if (ifexp != integer_one_node) ! expr = build3 (COND_EXPR, void_type_node, ! ifexp, expr, void_zero_node); return expr; } *************** build_delete (tree type, tree addr, spec *** 3029,3081 **** void push_base_cleanups (void) { ! tree binfos; ! int i, n_baseclasses; tree member; tree expr; /* Run destructors for all virtual baseclasses. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) { - tree vbases; tree cond = (condition_conversion ! (build (BIT_AND_EXPR, integer_type_node, ! current_in_charge_parm, ! integer_two_node))); ! vbases = CLASSTYPE_VBASECLASSES (current_class_type); ! /* The CLASSTYPE_VBASECLASSES list is in initialization order, which is also the right order for pushing cleanups. */ ! for (; vbases; ! vbases = TREE_CHAIN (vbases)) { ! tree vbase = TREE_VALUE (vbases); ! tree base_type = BINFO_TYPE (vbase); ! ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type)) { 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); finish_decl_cleanup (NULL_TREE, expr); } } } - 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, --- 2863,2908 ---- void push_base_cleanups (void) { ! tree binfo, base_binfo; ! int i; tree member; tree expr; + VEC (tree) *vbases; /* Run destructors for all virtual baseclasses. */ ! if (CLASSTYPE_VBASECLASSES (current_class_type)) { tree cond = (condition_conversion ! (build2 (BIT_AND_EXPR, integer_type_node, ! current_in_charge_parm, ! integer_two_node))); ! /* The CLASSTYPE_VBASECLASSES vector is in initialization order, which is also the right order for pushing cleanups. */ ! for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; ! VEC_iterate (tree, vbases, i, base_binfo); i++) { ! if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))) { expr = build_special_member_call (current_class_ref, base_dtor_identifier, NULL_TREE, ! base_binfo, (LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); ! expr = build3 (COND_EXPR, void_type_node, cond, ! expr, void_zero_node); finish_decl_cleanup (NULL_TREE, expr); } } } /* Take care of the remaining baseclasses. */ ! for (binfo = TYPE_BINFO (current_class_type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) ! || BINFO_VIRTUAL_P (base_binfo)) continue; expr = build_special_member_call (current_class_ref, *************** push_base_cleanups (void) *** 3106,3136 **** } } - /* For type TYPE, delete the virtual baseclass objects of DECL. */ - - tree - build_vbase_delete (tree type, tree decl) - { - tree vbases = CLASSTYPE_VBASECLASSES (type); - tree result; - tree addr = build_unary_op (ADDR_EXPR, decl, 0); - - my_friendly_assert (addr != error_mark_node, 222); - - for (result = convert_to_void (integer_zero_node, NULL); - vbases; vbases = TREE_CHAIN (vbases)) - { - tree base_addr = convert_force - (build_pointer_type (BINFO_TYPE (TREE_VALUE (vbases))), addr, 0); - tree base_delete = build_delete - (TREE_TYPE (base_addr), base_addr, sfk_base_destructor, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - - result = build_compound_expr (result, base_delete); - } - return result; - } - /* Build a C++ vector delete expression. MAXINDEX is the number of elements to be deleted. ELT_SIZE is the nominal size of each element in the vector. --- 2933,2938 ---- *************** build_vec_delete (tree base, tree maxind *** 3168,3177 **** base = TARGET_EXPR_SLOT (base_init); } type = strip_array_types (TREE_TYPE (type)); ! cookie_addr = build (MINUS_EXPR, ! build_pointer_type (sizetype), ! base, ! TYPE_SIZE_UNIT (sizetype)); maxindex = build_indirect_ref (cookie_addr, NULL); } else if (TREE_CODE (type) == ARRAY_TYPE) --- 2970,2979 ---- base = TARGET_EXPR_SLOT (base_init); } type = strip_array_types (TREE_TYPE (type)); ! cookie_addr = build2 (MINUS_EXPR, ! build_pointer_type (sizetype), ! base, ! TYPE_SIZE_UNIT (sizetype)); maxindex = build_indirect_ref (cookie_addr, NULL); } else if (TREE_CODE (type) == ARRAY_TYPE) *************** build_vec_delete (tree base, tree maxind *** 3197,3203 **** rval = build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete); if (base_init) ! rval = build (COMPOUND_EXPR, TREE_TYPE (rval), base_init, rval); return rval; } --- 2999,3005 ---- rval = build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete); if (base_init) ! rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), base_init, rval); return rval; } diff -Nrcpad gcc-3.4.3/gcc/cp/lang-specs.h gcc-4.0.0/gcc/cp/lang-specs.h *** gcc-3.4.3/gcc/cp/lang-specs.h Fri May 23 20:57:11 2003 --- gcc-4.0.0/gcc/cp/lang-specs.h Sun May 30 18:04:30 2004 *************** *** 1,6 **** /* Definitions for specs for C++. Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, ! 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. --- 1,6 ---- /* Definitions for specs for C++. Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, ! 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 26,40 **** #define CPLUSPLUS_CPP_SPEC 0 #endif ! {".cc", "@c++", 0}, ! {".cp", "@c++", 0}, ! {".cxx", "@c++", 0}, ! {".cpp", "@c++", 0}, ! {".c++", "@c++", 0}, ! {".C", "@c++", 0}, ! {".CPP", "@c++", 0}, ! {".H", "@c++-header", 0}, ! {".hh", "@c++-header", 0}, {"@c++-header", "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}\ %{!E:%{!M:%{!MM:\ --- 26,40 ---- #define CPLUSPLUS_CPP_SPEC 0 #endif ! {".cc", "@c++", 0, 0, 0}, ! {".cp", "@c++", 0, 0, 0}, ! {".cxx", "@c++", 0, 0, 0}, ! {".cpp", "@c++", 0, 0, 0}, ! {".c++", "@c++", 0, 0, 0}, ! {".C", "@c++", 0, 0, 0}, ! {".CPP", "@c++", 0, 0, 0}, ! {".H", "@c++-header", 0, 0, 0}, ! {".hh", "@c++-header", 0, 0, 0}, {"@c++-header", "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}\ %{!E:%{!M:%{!MM:\ *************** Boston, MA 02111-1307, USA. */ *** 44,50 **** %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\ %(cc1_options) %2 %{+e1*}\ -o %g.s %{!o*:--output-pch=%i.gch} %W{o*:--output-pch=%*}%V}}}", ! CPLUSPLUS_CPP_SPEC}, {"@c++", "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}\ %{!E:%{!M:%{!MM:\ --- 44,50 ---- %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\ %(cc1_options) %2 %{+e1*}\ -o %g.s %{!o*:--output-pch=%i.gch} %W{o*:--output-pch=%*}%V}}}", ! CPLUSPLUS_CPP_SPEC, 0, 0}, {"@c++", "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}\ %{!E:%{!M:%{!MM:\ *************** Boston, MA 02111-1307, USA. */ *** 54,62 **** %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\ %(cc1_options) %2 %{+e1*}\ %{!fsyntax-only:%(invoke_as)}}}}", ! CPLUSPLUS_CPP_SPEC}, ! {".ii", "@c++-cpp-output", 0}, {"@c++-cpp-output", "%{!M:%{!MM:%{!E:\ cc1plus -fpreprocessed %i %(cc1_options) %2 %{+e*}\ ! %{!fsyntax-only:%(invoke_as)}}}}", 0}, --- 54,62 ---- %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\ %(cc1_options) %2 %{+e1*}\ %{!fsyntax-only:%(invoke_as)}}}}", ! CPLUSPLUS_CPP_SPEC, 0, 0}, ! {".ii", "@c++-cpp-output", 0, 0, 0}, {"@c++-cpp-output", "%{!M:%{!MM:%{!E:\ cc1plus -fpreprocessed %i %(cc1_options) %2 %{+e*}\ ! %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, diff -Nrcpad gcc-3.4.3/gcc/cp/lex.c gcc-4.0.0/gcc/cp/lex.c *** gcc-3.4.3/gcc/cp/lex.c Wed Jun 9 18:32:04 2004 --- gcc-4.0.0/gcc/cp/lex.c Thu Nov 25 11:13:34 2004 *************** Boston, MA 02111-1307, USA. */ *** 31,37 **** #include "tree.h" #include "cp-tree.h" #include "cpplib.h" - #include "lex.h" #include "flags.h" #include "c-pragma.h" #include "toplev.h" --- 31,36 ---- *************** struct impl_files *** 83,150 **** static struct impl_files *impl_file_chain; - /* Return something to represent absolute declarators containing a *. - TARGET is the absolute declarator that the * contains. - CV_QUALIFIERS is a list of modifiers such as const or volatile - to apply to the pointer type, represented as identifiers. - - We return an INDIRECT_REF whose "contents" are TARGET - and whose type is the modifier list. */ - - tree - make_pointer_declarator (tree cv_qualifiers, tree target) - { - if (target && TREE_CODE (target) == IDENTIFIER_NODE - && ANON_AGGRNAME_P (target)) - error ("type name expected before `*'"); - target = build_nt (INDIRECT_REF, target); - TREE_TYPE (target) = cv_qualifiers; - return target; - } - - /* Return something to represent absolute declarators containing a &. - TARGET is the absolute declarator that the & contains. - CV_QUALIFIERS is a list of modifiers such as const or volatile - to apply to the reference type, represented as identifiers. - - We return an ADDR_EXPR whose "contents" are TARGET - and whose type is the modifier list. */ - - tree - make_reference_declarator (tree cv_qualifiers, tree target) - { - target = build_nt (ADDR_EXPR, target); - TREE_TYPE (target) = cv_qualifiers; - return target; - } - - tree - make_call_declarator (tree target, tree parms, tree cv_qualifiers, - tree exception_specification) - { - target = build_nt (CALL_EXPR, target, - tree_cons (parms, cv_qualifiers, NULL_TREE), - /* The third operand is really RTL. We - shouldn't put anything there. */ - NULL_TREE); - CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification; - return target; - } - - void - set_quals_and_spec (tree call_declarator, tree cv_qualifiers, - tree exception_specification) - { - CALL_DECLARATOR_QUALS (call_declarator) = cv_qualifiers; - CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification; - } - - int interface_only; /* whether or not current file is only for - interface definitions. */ - int interface_unknown; /* whether or not we know this class - to behave according to #pragma interface. */ - - void cxx_finish (void) { --- 82,87 ---- *************** init_operators (void) *** 207,213 **** operator_name_info [(int) ABS_EXPR].name = "abs"; operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&"; operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||"; - operator_name_info [(int) IN_EXPR].name = "in"; operator_name_info [(int) RANGE_EXPR].name = "..."; operator_name_info [(int) CONVERT_EXPR].name = "+"; --- 144,149 ---- *************** static const struct resword reswords[] = *** 253,258 **** --- 189,195 ---- { "__asm__", RID_ASM, 0 }, { "__attribute", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 }, + { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, *************** static const struct resword reswords[] = *** 266,273 **** { "__inline__", RID_INLINE, 0 }, { "__label__", RID_LABEL, 0 }, { "__null", RID_NULL, 0 }, - { "__offsetof", RID_OFFSETOF, 0 }, - { "__offsetof__", RID_OFFSETOF, 0 }, { "__real", RID_REALPART, 0 }, { "__real__", RID_REALPART, 0 }, { "__restrict", RID_RESTRICT, 0 }, --- 203,208 ---- *************** cxx_init (void) *** 394,400 **** /* We cannot just assign to input_filename because it has already been initialized and will be used later as an N_BINCL for stabs+ debugging. */ ! push_srcloc ("", 0); init_reswords (); init_tree (); --- 329,339 ---- /* We cannot just assign to input_filename because it has already been initialized and will be used later as an N_BINCL for stabs+ debugging. */ ! #ifdef USE_MAPPED_LOCATION ! push_srcloc (BUILTINS_LOCATION); ! #else ! push_srcloc ("", 0); ! #endif init_reswords (); init_tree (); *************** cxx_init (void) *** 409,420 **** cxx_init_decl_processing (); ! /* Create the built-in __null node. */ ! null_node = build_int_2 (0, 0); TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0); - ridpointers[RID_NULL] = null_node; ! interface_unknown = 1; if (c_common_init () == false) { --- 348,368 ---- cxx_init_decl_processing (); ! /* Create the built-in __null node. It is important that this is ! not shared. */ ! null_node = make_node (INTEGER_CST); TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0); ! /* The fact that G++ uses COMDAT for many entities (inline ! functions, template instantiations, virtual tables, etc.) mean ! that it is fundamentally unreliable to try to make decisions ! about whether or not to output a particular entity until the end ! of the compilation. However, the inliner requires that functions ! be provided to the back end if they are to be inlined. ! Therefore, we always use unit-at-a-time mode; in that mode, we ! can provide entities to the back end and it will decide what to ! emit based on what is actually needed. */ ! flag_unit_at_a_time = 1; if (c_common_init () == false) { *************** cxx_init (void) *** 424,448 **** init_cp_pragma (); ! init_repo (main_input_filename); pop_srcloc(); return true; } - /* Helper function to load global variables with interface - information. */ - - void - extract_interface_info (void) - { - struct c_fileinfo *finfo; - - finfo = get_fileinfo (input_filename); - interface_only = finfo->interface_only; - interface_unknown = finfo->interface_unknown; - } - /* Return nonzero if S is not considered part of an INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */ --- 372,383 ---- init_cp_pragma (); ! init_repo (); pop_srcloc(); return true; } /* Return nonzero if S is not considered part of an INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */ *************** handle_pragma_interface (cpp_reader* dfi *** 528,543 **** { tree fname = parse_strconst_pragma ("interface", 1); struct c_fileinfo *finfo; ! const char *main_filename; if (fname == (tree)-1) return; else if (fname == 0) ! main_filename = lbasename (input_filename); else ! main_filename = TREE_STRING_POINTER (fname); ! finfo = get_fileinfo (input_filename); if (impl_file_chain == 0) { --- 463,478 ---- { tree fname = parse_strconst_pragma ("interface", 1); struct c_fileinfo *finfo; ! const char *filename; if (fname == (tree)-1) return; else if (fname == 0) ! filename = lbasename (input_filename); else ! filename = ggc_strdup (TREE_STRING_POINTER (fname)); ! finfo = get_fileinfo (filename); if (impl_file_chain == 0) { *************** handle_pragma_interface (cpp_reader* dfi *** 547,560 **** main_input_filename = input_filename; } ! interface_only = interface_strcmp (main_filename); ! #ifdef MULTIPLE_SYMBOL_SPACES ! if (! interface_only) ! #endif ! interface_unknown = 0; ! ! finfo->interface_only = interface_only; ! finfo->interface_unknown = interface_unknown; } /* Note that we have seen a #pragma implementation for the key MAIN_FILENAME. --- 482,492 ---- main_input_filename = input_filename; } ! finfo->interface_only = interface_strcmp (filename); ! /* If MULTIPLE_SYMBOL_SPACES is set, we cannot assume that we can see ! a definition in another file. */ ! if (!MULTIPLE_SYMBOL_SPACES || !finfo->interface_only) ! finfo->interface_unknown = 0; } /* Note that we have seen a #pragma implementation for the key MAIN_FILENAME. *************** handle_pragma_interface (cpp_reader* dfi *** 562,575 **** in older compilers and it seems reasonable to allow it in the headers themselves, too. It only needs to precede the matching #p interface. ! We don't touch interface_only or interface_unknown; the user must specify ! a matching #p interface for this to have any effect. */ static void handle_pragma_implementation (cpp_reader* dfile ATTRIBUTE_UNUSED ) { tree fname = parse_strconst_pragma ("implementation", 1); ! const char *main_filename; struct impl_files *ifiles = impl_file_chain; if (fname == (tree)-1) --- 494,508 ---- in older compilers and it seems reasonable to allow it in the headers themselves, too. It only needs to precede the matching #p interface. ! We don't touch finfo->interface_only or finfo->interface_unknown; ! the user must specify a matching #p interface for this to have ! any effect. */ static void handle_pragma_implementation (cpp_reader* dfile ATTRIBUTE_UNUSED ) { tree fname = parse_strconst_pragma ("implementation", 1); ! const char *filename; struct impl_files *ifiles = impl_file_chain; if (fname == (tree)-1) *************** handle_pragma_implementation (cpp_reader *** 578,605 **** if (fname == 0) { if (main_input_filename) ! main_filename = main_input_filename; else ! main_filename = input_filename; ! main_filename = lbasename (main_filename); } else { ! main_filename = TREE_STRING_POINTER (fname); ! if (cpp_included (parse_in, main_filename)) ! warning ("#pragma implementation for %s appears after file is included", ! main_filename); } for (; ifiles; ifiles = ifiles->next) { ! if (! strcmp (ifiles->filename, main_filename)) break; } if (ifiles == 0) { ifiles = xmalloc (sizeof (struct impl_files)); ! ifiles->filename = main_filename; ifiles->next = impl_file_chain; impl_file_chain = ifiles; } --- 511,546 ---- if (fname == 0) { if (main_input_filename) ! filename = main_input_filename; else ! filename = input_filename; ! filename = lbasename (filename); } else { ! filename = ggc_strdup (TREE_STRING_POINTER (fname)); ! #if 0 ! /* We currently cannot give this diagnostic, as we reach this point ! only after cpplib has scanned the entire translation unit, so ! cpp_included always returns true. A plausible fix is to compare ! the current source-location cookie with the first source-location ! cookie (if any) of the filename, but this requires completing the ! --enable-mapped-location project first. See PR 17577. */ ! if (cpp_included (parse_in, filename)) ! warning ("#pragma implementation for %qs appears after " ! "file is included", filename); ! #endif } for (; ifiles; ifiles = ifiles->next) { ! if (! strcmp (ifiles->filename, filename)) break; } if (ifiles == 0) { ifiles = xmalloc (sizeof (struct impl_files)); ! ifiles->filename = filename; ifiles->next = impl_file_chain; impl_file_chain = ifiles; } *************** unqualified_name_lookup_error (tree name *** 625,652 **** 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); } return error_mark_node; --- 566,588 ---- if (IDENTIFIER_OPNAME_P (name)) { if (name != ansi_opname (ERROR_MARK)) ! error ("%qD not defined", name); } else { ! error ("%qD was not declared in this scope", name); ! /* Prevent repeated error messages by creating a VAR_DECL with ! this NAME in the innermost block scope. */ ! if (current_function_decl) { ! tree decl; ! decl = build_decl (VAR_DECL, name, error_mark_node); ! DECL_CONTEXT (decl) = current_function_decl; ! push_local_binding (name, decl, 0); ! /* Mark the variable as used so that we do not get warnings ! about it being unused later. */ ! TREE_USED (decl) = 1; } } return error_mark_node; *************** unqualified_fn_lookup_error (tree name) *** 671,678 **** Note that we have the exact wording of the following message in the manual (trouble.texi, node "Name lookup"), so they need to be kept in synch. */ ! pedwarn ("there are no arguments to `%D' that depend on a template " ! "parameter, so a declaration of `%D' must be available", name, name); if (!flag_permissive) --- 607,614 ---- Note that we have the exact wording of the following message in the manual (trouble.texi, node "Name lookup"), so they need to be kept in synch. */ ! pedwarn ("there are no arguments to %qD that depend on a template " ! "parameter, so a declaration of %qD must be available", name, name); if (!flag_permissive) *************** unqualified_fn_lookup_error (tree name) *** 680,687 **** static bool hint; if (!hint) { ! error ("(if you use `-fpermissive', G++ will accept your code, " ! "but allowing the use of an undeclared name is " "deprecated)"); hint = true; } --- 616,623 ---- static bool hint; if (!hint) { ! error ("(if you use %<-fpermissive%>, G++ will accept your " ! "code, but allowing the use of an undeclared name is " "deprecated)"); hint = true; } *************** build_lang_decl (enum tree_code code, tr *** 700,705 **** --- 636,646 ---- t = build_decl (code, name, type); retrofit_lang_decl (t); + /* All nesting of C++ functions is lexical; there is never a "static + chain" in the sense of GNU C nested functions. */ + if (code == FUNCTION_DECL) + DECL_NO_STATIC_CHAIN (t) = 1; + return t; } *************** retrofit_lang_decl (tree t) *** 717,723 **** else size = sizeof (struct lang_decl_flags); ! ld = 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; --- 658,664 ---- else size = sizeof (struct lang_decl_flags); ! ld = GGC_CNEWVAR (struct lang_decl, 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; *************** retrofit_lang_decl (tree t) *** 733,739 **** SET_DECL_LANGUAGE (t, lang_c); else if (current_lang_name == lang_name_java) SET_DECL_LANGUAGE (t, lang_java); ! else abort (); #ifdef GATHER_STATISTICS tree_node_counts[(int)lang_decl] += 1; --- 674,681 ---- SET_DECL_LANGUAGE (t, lang_c); else if (current_lang_name == lang_name_java) SET_DECL_LANGUAGE (t, lang_java); ! else ! gcc_unreachable (); #ifdef GATHER_STATISTICS tree_node_counts[(int)lang_decl] += 1; *************** cxx_dup_lang_specific_decl (tree node) *** 754,760 **** size = sizeof (struct lang_decl_flags); else size = sizeof (struct lang_decl); ! ld = ggc_alloc (size); memcpy (ld, DECL_LANG_SPECIFIC (node), size); DECL_LANG_SPECIFIC (node) = ld; --- 696,702 ---- size = sizeof (struct lang_decl_flags); else size = sizeof (struct lang_decl); ! ld = GGC_NEWVAR (struct lang_decl, size); memcpy (ld, DECL_LANG_SPECIFIC (node), size); DECL_LANG_SPECIFIC (node) = ld; *************** copy_lang_type (tree node) *** 791,797 **** size = sizeof (struct lang_type); else size = sizeof (struct lang_type_ptrmem); ! lt = ggc_alloc (size); memcpy (lt, TYPE_LANG_SPECIFIC (node), size); TYPE_LANG_SPECIFIC (node) = lt; --- 733,739 ---- size = sizeof (struct lang_type); else size = sizeof (struct lang_type_ptrmem); ! lt = GGC_NEWVAR (struct lang_type, size); memcpy (lt, TYPE_LANG_SPECIFIC (node), size); TYPE_LANG_SPECIFIC (node) = lt; *************** cxx_make_type (enum tree_code code) *** 822,830 **** if (IS_AGGR_TYPE_CODE (code) || code == BOUND_TEMPLATE_TEMPLATE_PARM) { ! struct lang_type *pi; ! ! pi = ggc_alloc_cleared (sizeof (struct lang_type)); TYPE_LANG_SPECIFIC (t) = pi; pi->u.c.h.is_lang_type_class = 1; --- 764,770 ---- if (IS_AGGR_TYPE_CODE (code) || code == BOUND_TEMPLATE_TEMPLATE_PARM) { ! struct lang_type *pi = GGC_CNEW (struct lang_type); TYPE_LANG_SPECIFIC (t) = pi; pi->u.c.h.is_lang_type_class = 1; *************** cxx_make_type (enum tree_code code) *** 838,865 **** /* Set up some flags that give proper default behavior. */ if (IS_AGGR_TYPE_CODE (code)) { ! SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); ! CLASSTYPE_INTERFACE_ONLY (t) = interface_only; ! ! /* Make sure this is laid out, for ease of use later. In the ! presence of parse errors, the normal was of assuring this ! might not ever get executed, so we lay it out *immediately*. */ ! build_pointer_type (t); } - else - /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But, - TYPE_ALIAS_SET is initialized to -1 by default, so we must - clear it here. */ - TYPE_ALIAS_SET (t) = 0; - - /* We need to allocate a TYPE_BINFO even for TEMPLATE_TYPE_PARMs - since they can be virtual base types, and we then need a - canonical binfo for them. Ideally, this would be done lazily for - all types. */ - if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM - || code == BOUND_TEMPLATE_TEMPLATE_PARM - || code == TYPENAME_TYPE) - TYPE_BINFO (t) = make_binfo (size_zero_node, t, NULL_TREE, NULL_TREE); return t; } --- 778,787 ---- /* Set up some flags that give proper default behavior. */ if (IS_AGGR_TYPE_CODE (code)) { ! struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename)); ! SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown); ! CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only; } return t; } *************** make_aggr_type (enum tree_code code) *** 874,893 **** return t; } - - /* Return the type-qualifier corresponding to the identifier given by - RID. */ - - int - cp_type_qual_from_rid (tree rid) - { - if (rid == ridpointers[(int) RID_CONST]) - return TYPE_QUAL_CONST; - else if (rid == ridpointers[(int) RID_VOLATILE]) - return TYPE_QUAL_VOLATILE; - else if (rid == ridpointers[(int) RID_RESTRICT]) - return TYPE_QUAL_RESTRICT; - - abort (); - return TYPE_UNQUALIFIED; - } --- 796,798 ---- diff -Nrcpad gcc-3.4.3/gcc/cp/lex.h gcc-4.0.0/gcc/cp/lex.h *** gcc-3.4.3/gcc/cp/lex.h Thu Jan 2 11:39:47 2003 --- gcc-4.0.0/gcc/cp/lex.h Thu Jan 1 00:00:00 1970 *************** *** 1,68 **** - /* Define constants and variables for communication with the parser. - Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - Hacked by Michael Tiemann (tiemann@cygnus.com) - and by Brendan Kehoe (brendan@cygnus.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; 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_LEX_H - #define GCC_CP_LEX_H - - #if 0 - /* Formerly, the RID_* values used as mask bits did not fit into a - single 32-bit word. Now they do, but let's preserve the old logic - in case they ever stop fitting again. -zw, 8 Aug 2000 */ - - /* The type that can represent all values of RIDBIT. */ - /* We assume that we can stick in at least 32 bits into this. */ - typedef struct { unsigned long idata[2]; } - RID_BIT_TYPE; - - /* Be careful, all these modify N twice. */ - #define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32)) \ - & (V).idata[(N)/32]) - #define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV)) - #define RIDBIT_SET(N, V) do { \ - (V).idata[(N)/32] \ - |= ((unsigned long)1 << (int) ((N)%32)); \ - } while (0) - #define RIDBIT_RESET(N, V) do { \ - (V).idata[(N)/32] \ - &= ~((unsigned long)1 << (int) ((N)%32)); \ - } while (0) - #define RIDBIT_RESET_ALL(V) do { \ - (V).idata[0] = 0; \ - (V).idata[1] = 0; \ - } while (0) - #define RIDBIT_ANY_SET(V) ((V).idata[0] || (V).idata[1]) - #else - typedef unsigned long RID_BIT_TYPE; /* assumed at least 32 bits */ - #define RIDBIT_OF(R) ((unsigned long)1 << (int) (R)) - - #define RIDBIT_SETP(N, V) ((V) & RIDBIT_OF (N)) - #define RIDBIT_NOTSETP(N, V) (! ((V) & RIDBIT_OF (N))) - #define RIDBIT_ANY_SET(V) (V) - - #define RIDBIT_SET(N, V) do { (V) |= RIDBIT_OF (N); } while (0) - #define RIDBIT_RESET(N, V) do { (V) &= ~RIDBIT_OF (N); } while (0) - #define RIDBIT_RESET_ALL(V) do { (V) = 0; } while (0) - #endif - - #endif /* ! GCC_CP_LEX_H */ --- 0 ---- diff -Nrcpad gcc-3.4.3/gcc/cp/mangle.c gcc-4.0.0/gcc/cp/mangle.c *** gcc-3.4.3/gcc/cp/mangle.c Mon Aug 23 18:03:06 2004 --- gcc-4.0.0/gcc/cp/mangle.c Thu Feb 24 21:55:15 2005 *************** *** 92,113 **** && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))))) /* Things we only need one of. This module is not reentrant. */ ! static struct globals { - /* The name in which we're building the mangled name. */ - struct obstack name_obstack; - /* An array of the current substitution candidates, in the order we've seen them. */ varray_type substitutions; /* The entity that is being mangled. */ ! tree entity; /* True if the mangling will be different in a future version of the ABI. */ bool need_abi_warning; ! } G; /* Indices into subst_identifiers. These are identifiers used in special substitution rules. */ --- 92,130 ---- && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))))) /* Things we only need one of. This module is not reentrant. */ ! typedef struct globals GTY(()) { /* An array of the current substitution candidates, in the order we've seen them. */ varray_type substitutions; /* The entity that is being mangled. */ ! tree GTY ((skip)) entity; /* True if the mangling will be different in a future version of the ABI. */ bool need_abi_warning; ! } globals; ! ! static GTY (()) globals G; ! ! /* The obstack on which we build mangled names. */ ! static struct obstack *mangle_obstack; ! ! /* The obstack on which we build mangled names that are not going to ! be IDENTIFIER_NODEs. */ ! static struct obstack name_obstack; ! ! /* The first object on the name_obstack; we use this to free memory ! allocated on the name_obstack. */ ! static void *name_base; ! ! /* An incomplete mangled name. There will be no NUL terminator. If ! there is no incomplete mangled name, this variable is NULL. */ ! static char *partially_mangled_name; ! ! /* The number of characters in the PARTIALLY_MANGLED_NAME. */ ! static size_t partially_mangled_name_len; /* Indices into subst_identifiers. These are identifiers used in special substitution rules. */ *************** static const char *mangle_decl_string (c *** 206,212 **** /* Control functions. */ ! static inline void start_mangling (const tree); static inline const char *finish_mangling (const bool); static tree mangle_special_for_type (const tree, const char *); --- 223,229 ---- /* Control functions. */ ! static inline void start_mangling (const tree, bool); static inline const char *finish_mangling (const bool); static tree mangle_special_for_type (const tree, const char *); *************** static void write_java_integer_type_code *** 217,232 **** /* Append a single character to the end of the mangled representation. */ #define write_char(CHAR) \ ! obstack_1grow (&G.name_obstack, (CHAR)) /* Append a sized buffer to the end of the mangled representation. */ #define write_chars(CHAR, LEN) \ ! obstack_grow (&G.name_obstack, (CHAR), (LEN)) /* Append a NUL-terminated string to the end of the mangled representation. */ #define write_string(STRING) \ ! obstack_grow (&G.name_obstack, (STRING), strlen (STRING)) /* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the same purpose (context, which may be a type) and value (template --- 234,249 ---- /* Append a single character to the end of the mangled representation. */ #define write_char(CHAR) \ ! obstack_1grow (mangle_obstack, (CHAR)) /* Append a sized buffer to the end of the mangled representation. */ #define write_chars(CHAR, LEN) \ ! obstack_grow (mangle_obstack, (CHAR), (LEN)) /* Append a NUL-terminated string to the end of the mangled representation. */ #define write_string(STRING) \ ! obstack_grow (mangle_obstack, (STRING), strlen (STRING)) /* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the same purpose (context, which may be a type) and value (template *************** static void write_java_integer_type_code *** 244,249 **** --- 261,302 ---- #define write_unsigned_number(NUMBER) \ write_number ((NUMBER), /*unsigned_p=*/1, 10) + /* Save the current (incomplete) mangled name and release the obstack + storage holding it. This function should be used during mangling + when making a call that could result in a call to get_identifier, + as such a call will clobber the same obstack being used for + mangling. This function may not be called twice without an + intervening call to restore_partially_mangled_name. */ + + static void + save_partially_mangled_name (void) + { + if (mangle_obstack == &ident_hash->stack) + { + gcc_assert (!partially_mangled_name); + partially_mangled_name_len = obstack_object_size (mangle_obstack); + partially_mangled_name = xmalloc (partially_mangled_name_len); + memcpy (partially_mangled_name, obstack_base (mangle_obstack), + partially_mangled_name_len); + obstack_free (mangle_obstack, obstack_finish (mangle_obstack)); + } + } + + /* Restore the incomplete mangled name saved with + save_partially_mangled_name. */ + + static void + restore_partially_mangled_name (void) + { + if (partially_mangled_name) + { + obstack_grow (mangle_obstack, partially_mangled_name, + partially_mangled_name_len); + free (partially_mangled_name); + partially_mangled_name = NULL; + } + } + /* 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. */ *************** add_substitution (tree node) *** 363,374 **** for (i = VARRAY_ACTIVE_SIZE (G.substitutions); --i >= 0; ) { const tree candidate = VARRAY_TREE (G.substitutions, i); ! if ((DECL_P (node) ! && node == candidate) ! || (TYPE_P (node) ! && TYPE_P (candidate) ! && same_type_p (node, candidate))) ! abort (); } } #endif /* ENABLE_CHECKING */ --- 416,425 ---- for (i = VARRAY_ACTIVE_SIZE (G.substitutions); --i >= 0; ) { const tree candidate = VARRAY_TREE (G.substitutions, i); ! ! gcc_assert (!(DECL_P (node) && node == candidate)); ! gcc_assert (!(TYPE_P (node) && TYPE_P (candidate) ! && same_type_p (node, candidate))); } } #endif /* ENABLE_CHECKING */ *************** write_encoding (const tree decl) *** 694,700 **** --- 745,757 ---- if (decl_is_template_id (decl, NULL)) { + save_partially_mangled_name (); fn_type = get_mostly_instantiated_function_type (decl); + restore_partially_mangled_name (); + /* FN_TYPE will not have parameter types for in-charge or + VTT parameters. Therefore, we pass NULL_TREE to + write_bare_function_type -- otherwise, it will get + confused about which artificial parameters to skip. */ d = NULL_TREE; } else *************** write_unscoped_name (const tree decl) *** 818,831 **** write_string ("St"); write_unqualified_name (decl); } ! /* If not, it should be either in the global namespace, or directly ! in a local function scope. */ ! else if (context == global_namespace ! || context == NULL ! || TREE_CODE (context) == FUNCTION_DECL) ! write_unqualified_name (decl); ! else ! abort (); } /* ::= --- 875,890 ---- write_string ("St"); write_unqualified_name (decl); } ! else ! { ! /* If not, it should be either in the global namespace, or directly ! in a local function scope. */ ! gcc_assert (context == global_namespace ! || context == NULL ! || TREE_CODE (context) == FUNCTION_DECL); ! ! write_unqualified_name (decl); ! } } /* ::= *************** write_template_prefix (const tree node) *** 970,980 **** /* Find the template decl. */ if (decl_is_template_id (decl, &template_info)) template = TI_TEMPLATE (template_info); - else if (CLASSTYPE_TEMPLATE_ID_P (type)) - template = TYPE_TI_TEMPLATE (type); else ! /* Oops, not a template. */ ! abort (); /* For a member template, though, the template name for the innermost name must have all the outer template levels --- 1029,1040 ---- /* Find the template decl. */ if (decl_is_template_id (decl, &template_info)) template = TI_TEMPLATE (template_info); else ! { ! gcc_assert (CLASSTYPE_TEMPLATE_ID_P (type)); ! ! template = TYPE_TI_TEMPLATE (type); ! } /* For a member template, though, the template name for the innermost name must have all the outer template levels *************** write_unqualified_name (const tree decl) *** 1048,1054 **** tree type; if (decl_is_template_id (decl, NULL)) { ! tree fn_type = get_mostly_instantiated_function_type (decl); type = TREE_TYPE (fn_type); } else --- 1108,1117 ---- tree type; if (decl_is_template_id (decl, NULL)) { ! tree fn_type; ! save_partially_mangled_name (); ! fn_type = get_mostly_instantiated_function_type (decl); ! restore_partially_mangled_name (); type = TREE_TYPE (fn_type); } else *************** write_integer_cst (const tree cst) *** 1179,1187 **** } 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; if (sign < 0) { --- 1242,1250 ---- } type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst)); ! base = build_int_cstu (type, chunk); ! n = build_int_cst_wide (type, ! TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst)); if (sign < 0) { *************** write_integer_cst (const tree cst) *** 1190,1203 **** } do { ! tree d = fold (build (FLOOR_DIV_EXPR, type, n, base)); ! tree tmp = fold (build (MULT_EXPR, type, d, base)); unsigned c; done = integer_zerop (d); ! tmp = fold (build (MINUS_EXPR, type, n, tmp)); c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr, ! done ? 1 : chunk_digits); ptr -= c; count += c; n = d; --- 1253,1266 ---- } do { ! tree d = fold (build2 (FLOOR_DIV_EXPR, type, n, base)); ! tree tmp = fold (build2 (MULT_EXPR, type, d, base)); unsigned c; done = integer_zerop (d); ! tmp = fold (build2 (MINUS_EXPR, type, n, tmp)); c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr, ! done ? 1 : chunk_digits); ptr -= c; count += c; n = d; *************** write_identifier (const char *identifier *** 1311,1326 **** static void write_special_name_constructor (const tree ctor) { ! if (DECL_COMPLETE_CONSTRUCTOR_P (ctor) ! /* Even though we don't ever emit a definition of the ! old-style destructor, we still have to consider entities ! (like static variables) nested inside it. */ ! || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor)) ! write_string ("C1"); ! else if (DECL_BASE_CONSTRUCTOR_P (ctor)) write_string ("C2"); else ! abort (); } /* Handle destructor productions of non-terminal . --- 1374,1391 ---- static void write_special_name_constructor (const tree ctor) { ! if (DECL_BASE_CONSTRUCTOR_P (ctor)) write_string ("C2"); else ! { ! gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor) ! /* Even though we don't ever emit a definition of ! the old-style destructor, we still have to ! consider entities (like static variables) nested ! inside it. */ ! || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor)); ! write_string ("C1"); ! } } /* Handle destructor productions of non-terminal . *************** write_special_name_destructor (const tre *** 1339,1354 **** { if (DECL_DELETING_DESTRUCTOR_P (dtor)) write_string ("D0"); - else if (DECL_COMPLETE_DESTRUCTOR_P (dtor) - /* Even though we don't ever emit a definition of the - old-style destructor, we still have to consider entities - (like static variables) nested inside it. */ - || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor)) - write_string ("D1"); else if (DECL_BASE_DESTRUCTOR_P (dtor)) write_string ("D2"); else ! abort (); } /* Return the discriminator for ENTITY appearing inside --- 1404,1421 ---- { if (DECL_DELETING_DESTRUCTOR_P (dtor)) write_string ("D0"); else if (DECL_BASE_DESTRUCTOR_P (dtor)) write_string ("D2"); else ! { ! gcc_assert (DECL_COMPLETE_DESTRUCTOR_P (dtor) ! /* Even though we don't ever emit a definition of ! the old-style destructor, we still have to ! consider entities (like static variables) nested ! inside it. */ ! || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor)); ! write_string ("D1"); ! } } /* Return the discriminator for ENTITY appearing inside *************** write_type (tree type) *** 1576,1582 **** break; default: ! abort (); } } --- 1643,1649 ---- break; default: ! gcc_unreachable (); } } *************** write_builtin_type (tree type) *** 1689,1702 **** if (itk == itk_none) { tree t = c_common_type_for_mode (TYPE_MODE (type), ! TREE_UNSIGNED (type)); if (type == t) { ! if (TYPE_PRECISION (type) == 128) ! write_char (TREE_UNSIGNED (type) ? 'o' : 'n'); ! else ! /* Couldn't find this type. */ ! abort (); } else { --- 1756,1766 ---- if (itk == itk_none) { tree t = c_common_type_for_mode (TYPE_MODE (type), ! TYPE_UNSIGNED (type)); if (type == t) { ! gcc_assert (TYPE_PRECISION (type) == 128); ! write_char (TYPE_UNSIGNED (type) ? 'o' : 'n'); } else { *************** write_builtin_type (tree type) *** 1717,1727 **** else if (type == long_double_type_node) write_char ('e'); else ! abort (); break; default: ! abort (); } } --- 1781,1791 ---- else if (type == long_double_type_node) write_char ('e'); else ! gcc_unreachable (); break; default: ! gcc_unreachable (); } } *************** write_method_parms (tree parm_types, con *** 1839,1845 **** fixed-length. */ varargs_p = 0; /* A void type better be the last one. */ ! my_friendly_assert (TREE_CHAIN (parm_types) == NULL, 20000523); } else write_type (parm); --- 1903,1909 ---- fixed-length. */ varargs_p = 0; /* A void type better be the last one. */ ! gcc_assert (TREE_CHAIN (parm_types) == NULL); } else write_type (parm); *************** write_template_args (tree args) *** 1873,1879 **** write_char ('I'); ! my_friendly_assert (length > 0, 20000422); if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) { --- 1937,1943 ---- write_char ('I'); ! gcc_assert (length > 0); if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) { *************** write_expression (tree expr) *** 1905,1910 **** --- 1969,1984 ---- code = TREE_CODE (expr); + /* Skip NOP_EXPRs. They can occur when (say) a pointer argument + is converted (via qualification conversions) to another + type. */ + while (TREE_CODE (expr) == NOP_EXPR + || TREE_CODE (expr) == NON_LVALUE_EXPR) + { + expr = TREE_OPERAND (expr, 0); + code = TREE_CODE (expr); + } + /* Handle pointers-to-members by making them look like expression nodes. */ if (code == PTRMEM_CST) *************** write_expression (tree expr) *** 1916,1931 **** code = TREE_CODE (expr); } - /* Skip NOP_EXPRs. They can occur when (say) a pointer argument - is converted (via qualification conversions) to another - type. */ - while (TREE_CODE (expr) == NOP_EXPR - || TREE_CODE (expr) == NON_LVALUE_EXPR) - { - expr = TREE_OPERAND (expr, 0); - code = TREE_CODE (expr); - } - /* Handle template parameters. */ if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM --- 1990,1995 ---- *************** write_expression (tree expr) *** 1933,1939 **** || code == TEMPLATE_PARM_INDEX) write_template_param (expr); /* Handle literals. */ ! 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)) --- 1997,2003 ---- || code == TEMPLATE_PARM_INDEX) write_template_param (expr); /* Handle literals. */ ! else if (TREE_CODE_CLASS (code) == tcc_constant || (abi_version_at_least (2) && code == CONST_DECL)) write_template_arg_literal (expr); else if (DECL_P (expr)) *************** write_expression (tree expr) *** 2052,2058 **** case CAST_EXPR: write_type (TREE_TYPE (expr)); ! write_expression (TREE_VALUE (TREE_OPERAND (expr, 0))); break; case STATIC_CAST_EXPR: --- 2116,2128 ---- case CAST_EXPR: write_type (TREE_TYPE (expr)); ! /* There is no way to mangle a zero-operand cast like ! "T()". */ ! if (!TREE_OPERAND (expr, 0)) ! sorry ("zero-operand casts cannot be mangled due to a defect " ! "in the C++ ABI"); ! else ! write_expression (TREE_VALUE (TREE_OPERAND (expr, 0))); break; case STATIC_CAST_EXPR: *************** write_expression (tree expr) *** 2075,2082 **** template_id = TREE_OPERAND (expr, 1); name = TREE_OPERAND (template_id, 0); /* FIXME: What about operators? */ ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, ! 20030707); write_source_name (TREE_OPERAND (template_id, 0)); write_template_args (TREE_OPERAND (template_id, 1)); } --- 2145,2151 ---- template_id = TREE_OPERAND (expr, 1); name = TREE_OPERAND (template_id, 0); /* FIXME: What about operators? */ ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); write_source_name (TREE_OPERAND (template_id, 0)); write_template_args (TREE_OPERAND (template_id, 1)); } *************** write_expression (tree expr) *** 2100,2106 **** expression without extending the C++ ABI. */ if (code == COND_EXPR && i == 1 && !operand) { ! error ("omitted middle operand to `?:' operand " "cannot be mangled"); continue; } --- 2169,2175 ---- expression without extending the C++ ABI. */ if (code == COND_EXPR && i == 1 && !operand) { ! error ("omitted middle operand to % operand " "cannot be mangled"); continue; } *************** write_expression (tree expr) *** 2120,2154 **** static void write_template_arg_literal (const tree value) { - tree type = TREE_TYPE (value); write_char ('L'); ! write_type (type); ! if (TREE_CODE (value) == CONST_DECL) ! write_integer_cst (DECL_INITIAL (value)); ! else if (TREE_CODE (value) == INTEGER_CST) { ! if (same_type_p (type, boolean_type_node)) ! { ! if (integer_zerop (value)) ! write_unsigned_number (0); ! else if (integer_onep (value)) ! write_unsigned_number (1); ! else ! abort (); ! } ! else ! write_integer_cst (value); ! } ! else if (TREE_CODE (value) == REAL_CST) ! write_real_cst (value); ! else ! abort (); write_char ('E'); } ! /* Non-terminal . ::= # type ::= L E # literal --- 2189,2221 ---- static void write_template_arg_literal (const tree value) { write_char ('L'); ! write_type (TREE_TYPE (value)); ! switch (TREE_CODE (value)) { ! case CONST_DECL: ! write_integer_cst (DECL_INITIAL (value)); ! break; ! ! case INTEGER_CST: ! gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node) ! || integer_zerop (value) || integer_onep (value)); ! write_integer_cst (value); ! break; + case REAL_CST: + write_real_cst (value); + break; + + default: + gcc_unreachable (); + } + write_char ('E'); } ! /* Non-terminal . ::= # type ::= L E # literal *************** write_template_arg (tree node) *** 2163,2169 **** MANGLE_TRACE_TREE ("template-arg", node); /* A template template parameter's argument list contains TREE_LIST ! nodes of which the value field is the the actual argument. */ if (code == TREE_LIST) { node = TREE_VALUE (node); --- 2230,2236 ---- MANGLE_TRACE_TREE ("template-arg", node); /* A template template parameter's argument list contains TREE_LIST ! nodes of which the value field is the actual argument. */ if (code == TREE_LIST) { node = TREE_VALUE (node); *************** write_template_arg (tree node) *** 2181,2188 **** /* Template parameters can be of reference type. To maintain internal consistency, such arguments use a conversion from address of object to reference type. */ ! my_friendly_assert (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR, ! 20031215); if (abi_version_at_least (2)) node = TREE_OPERAND (TREE_OPERAND (node, 0), 0); else --- 2248,2254 ---- /* Template parameters can be of reference type. To maintain internal consistency, such arguments use a conversion from address of object to reference type. */ ! gcc_assert (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR); if (abi_version_at_least (2)) node = TREE_OPERAND (TREE_OPERAND (node, 0), 0); else *************** write_template_arg (tree node) *** 2194,2210 **** 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 ! enumeration type using their names. */ ! if (code == CONST_DECL) G.need_abi_warning = 1; write_char ('L'); ! write_char ('Z'); write_encoding (node); write_char ('E'); } --- 2260,2284 ---- 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) == tcc_constant && code != PTRMEM_CST) || (abi_version_at_least (2) && code == CONST_DECL)) write_template_arg_literal (node); else if (DECL_P (node)) { ! /* Until ABI version 2, non-type template arguments of ! enumeration type were mangled using their names. */ ! if (code == CONST_DECL && !abi_version_at_least (2)) G.need_abi_warning = 1; write_char ('L'); ! /* Until ABI version 3, the underscore before the mangled name ! was incorrectly omitted. */ ! if (!abi_version_at_least (3)) ! { ! G.need_abi_warning = 1; ! write_char ('Z'); ! } ! else ! write_string ("_Z"); write_encoding (node); write_char ('E'); } *************** write_template_param (const tree parm) *** 2326,2332 **** break; default: ! abort (); } write_char ('T'); --- 2400,2406 ---- break; default: ! gcc_unreachable (); } write_char ('T'); *************** write_substitution (const int seq_id) *** 2383,2394 **** /* Start mangling ENTITY. */ static inline void ! start_mangling (const 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. If WARN is --- 2457,2474 ---- /* Start mangling ENTITY. */ static inline void ! start_mangling (const tree entity, const bool ident_p) { G.entity = entity; G.need_abi_warning = false; ! if (!ident_p) ! { ! obstack_free (&name_obstack, name_base); ! mangle_obstack = &name_obstack; ! name_base = obstack_alloc (&name_obstack, 0); ! } ! else ! mangle_obstack = &ident_hash->stack; } /* Done with mangling. Return the generated mangled name. If WARN is *************** static inline const char * *** 2399,2415 **** finish_mangling (const bool warn) { if (warn_abi && warn && G.need_abi_warning) ! warning ("the mangled name of `%D' will change in a future " "version of GCC", G.entity); /* Clear all the substitutions. */ ! G.substitutions = 0; /* Null-terminate the string. */ write_char ('\0'); ! return (const char *) obstack_base (&G.name_obstack); } /* Initialize data structures for mangling. */ --- 2479,2495 ---- finish_mangling (const bool warn) { if (warn_abi && warn && G.need_abi_warning) ! warning ("the mangled name of %qD will change in a future " "version of GCC", G.entity); /* Clear all the substitutions. */ ! VARRAY_CLEAR (G.substitutions); /* Null-terminate the string. */ write_char ('\0'); ! return (const char *) obstack_finish (mangle_obstack); } /* Initialize data structures for mangling. */ *************** finish_mangling (const bool warn) *** 2417,2423 **** void init_mangle (void) { ! gcc_obstack_init (&G.name_obstack); /* Cache these identifiers for quick comparison when checking for standard substitutions. */ --- 2497,2505 ---- void init_mangle (void) { ! gcc_obstack_init (&name_obstack); ! name_base = obstack_alloc (&name_obstack, 0); ! VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions"); /* Cache these identifiers for quick comparison when checking for standard substitutions. */ *************** mangle_decl_string (const tree decl) *** 2436,2442 **** { const char *result; ! start_mangling (decl); if (TREE_CODE (decl) == TYPE_DECL) write_type (TREE_TYPE (decl)); --- 2518,2524 ---- { const char *result; ! start_mangling (decl, /*ident_p=*/true); if (TREE_CODE (decl) == TYPE_DECL) write_type (TREE_TYPE (decl)); *************** mangle_decl_string (const tree decl) *** 2449,2462 **** return result; } /* Create an identifier for the external mangled name of DECL. */ void mangle_decl (const tree decl) { ! tree id = get_identifier (mangle_decl_string (decl)); ! ! SET_DECL_ASSEMBLER_NAME (decl, id); } /* Generate the mangled representation of TYPE. */ --- 2531,2554 ---- return result; } + /* Like get_identifier, except that NAME is assumed to have been + allocated on the obstack used by the identifier hash table. */ + + static inline tree + get_identifier_nocopy (const char *name) + { + hashnode ht_node = ht_lookup (ident_hash, (const unsigned char *) name, + strlen (name), HT_ALLOCED); + return HT_IDENT_TO_GCC_IDENT (ht_node); + } + /* Create an identifier for the external mangled name of DECL. */ void mangle_decl (const tree decl) { ! SET_DECL_ASSEMBLER_NAME (decl, ! get_identifier_nocopy (mangle_decl_string (decl))); } /* Generate the mangled representation of TYPE. */ *************** mangle_type_string (const tree type) *** 2466,2472 **** { const char *result; ! start_mangling (type); write_type (type); result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) --- 2558,2564 ---- { const char *result; ! start_mangling (type, /*ident_p=*/false); write_type (type); result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) *************** mangle_type_string (const tree type) *** 2474,2487 **** return result; } - /* Create an identifier for the mangled representation of TYPE. */ - - tree - mangle_type (const tree type) - { - return get_identifier (mangle_type_string (type)); - } - /* Create an identifier for the mangled name of a special component for belonging to TYPE. CODE is the ABI-specified code for this component. */ --- 2566,2571 ---- *************** mangle_special_for_type (const tree type *** 2493,2499 **** /* We don't have an actual decl here for the special component, so we can't just process the . Instead, fake it. */ ! start_mangling (type); /* Start the mangling. */ write_string ("_Z"); --- 2577,2583 ---- /* We don't have an actual decl here for the special component, so we can't just process the . Instead, fake it. */ ! start_mangling (type, /*ident_p=*/true); /* Start the mangling. */ write_string ("_Z"); *************** mangle_special_for_type (const tree type *** 2506,2512 **** if (DEBUG_MANGLE) fprintf (stderr, "mangle_special_for_type = %s\n\n", result); ! return get_identifier (result); } /* Create an identifier for the mangled representation of the typeinfo --- 2590,2596 ---- if (DEBUG_MANGLE) fprintf (stderr, "mangle_special_for_type = %s\n\n", result); ! return get_identifier_nocopy (result); } /* Create an identifier for the mangled representation of the typeinfo *************** mangle_ctor_vtbl_for_type (const tree ty *** 2562,2568 **** { const char *result; ! start_mangling (type); write_string ("_Z"); write_string ("TC"); --- 2646,2652 ---- { const char *result; ! start_mangling (type, /*ident_p=*/true); write_string ("_Z"); write_string ("TC"); *************** mangle_ctor_vtbl_for_type (const tree ty *** 2574,2580 **** result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n", result); ! return get_identifier (result); } /* Mangle a this pointer or result pointer adjustment. --- 2658,2664 ---- result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n", result); ! return get_identifier_nocopy (result); } /* Mangle a this pointer or result pointer adjustment. *************** mangle_thunk (tree fn_decl, const int th *** 2619,2625 **** { const char *result; ! start_mangling (fn_decl); write_string ("_Z"); write_char ('T'); --- 2703,2709 ---- { const char *result; ! start_mangling (fn_decl, /*ident_p=*/true); write_string ("_Z"); write_char ('T'); *************** mangle_thunk (tree fn_decl, const int th *** 2653,2659 **** result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) fprintf (stderr, "mangle_thunk = %s\n\n", result); ! return get_identifier (result); } /* This hash table maps TYPEs to the IDENTIFIER for a conversion --- 2737,2743 ---- result = finish_mangling (/*warn=*/false); if (DEBUG_MANGLE) fprintf (stderr, "mangle_thunk = %s\n\n", result); ! return get_identifier_nocopy (result); } /* This hash table maps TYPEs to the IDENTIFIER for a conversion *************** mangle_conv_op_name_for_type (const tree *** 2722,2728 **** tree mangle_guard_variable (const tree variable) { ! start_mangling (variable); write_string ("_ZGV"); if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) /* The name of a guard variable for a reference temporary should refer --- 2806,2812 ---- tree mangle_guard_variable (const tree variable) { ! start_mangling (variable, /*ident_p=*/true); write_string ("_ZGV"); if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) /* The name of a guard variable for a reference temporary should refer *************** mangle_guard_variable (const tree variab *** 2730,2736 **** write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); else write_name (variable, /*ignore_local_scope=*/0); ! return get_identifier (finish_mangling (/*warn=*/false)); } /* Return an identifier for the name of a temporary variable used to --- 2814,2820 ---- write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); else write_name (variable, /*ignore_local_scope=*/0); ! return get_identifier_nocopy (finish_mangling (/*warn=*/false)); } /* Return an identifier for the name of a temporary variable used to *************** mangle_guard_variable (const tree variab *** 2740,2749 **** tree mangle_ref_init_variable (const tree variable) { ! start_mangling (variable); write_string ("_ZGR"); write_name (variable, /*ignore_local_scope=*/0); ! return get_identifier (finish_mangling (/*warn=*/false)); } --- 2824,2833 ---- tree mangle_ref_init_variable (const tree variable) { ! start_mangling (variable, /*ident_p=*/true); write_string ("_ZGR"); write_name (variable, /*ignore_local_scope=*/0); ! return get_identifier_nocopy (finish_mangling (/*warn=*/false)); } *************** write_java_integer_type_codes (const tre *** 2767,2773 **** else if (type == java_boolean_type_node) write_char ('b'); else ! abort (); } #include "gt-cp-mangle.h" --- 2851,2857 ---- else if (type == java_boolean_type_node) write_char ('b'); else ! gcc_unreachable (); } #include "gt-cp-mangle.h" diff -Nrcpad gcc-3.4.3/gcc/cp/method.c gcc-4.0.0/gcc/cp/method.c *** gcc-3.4.3/gcc/cp/method.c Tue Jun 8 06:30:32 2004 --- gcc-4.0.0/gcc/cp/method.c Tue Mar 1 10:00:32 2005 *************** *** 1,7 **** /* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. --- 1,7 ---- /* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ! 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. *************** static tree synthesize_exception_spec (t *** 62,70 **** static tree locate_dtor (tree, void *); static tree locate_ctor (tree, void *); static tree locate_copy (tree, void *); - #ifdef ASM_OUTPUT_DEF static tree make_alias_for_thunk (tree); - #endif /* Called once to initialize method.c. */ --- 62,68 ---- *************** init_method (void) *** 73,92 **** { init_mangle (); } - - - /* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ - - void - set_mangled_name_for_decl (tree decl) - { - if (processing_template_decl) - /* There's no need to mangle the name of a template function. */ - return; - - mangle_decl (decl); - } - /* Return a this or result adjusting thunk to FUNCTION. THIS_ADJUSTING indicates whether it is a this or result adjusting thunk. --- 71,76 ---- *************** make_thunk (tree function, bool this_adj *** 104,114 **** HOST_WIDE_INT d; tree thunk; ! my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025); /* We can have this thunks to covariant thunks, but not vice versa. */ ! my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127); ! my_friendly_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting, ! 20031123); /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ if (this_adjusting && virtual_offset) --- 88,97 ---- HOST_WIDE_INT d; tree thunk; ! gcc_assert (TREE_CODE (function) == FUNCTION_DECL); /* We can have this thunks to covariant thunks, but not vice versa. */ ! gcc_assert (!DECL_THIS_THUNK_P (function)); ! gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting); /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ if (this_adjusting && virtual_offset) *************** make_thunk (tree function, bool this_adj *** 137,148 **** /* 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); /* Likewise, we can only be adding thunks to a function declared in the class currently being laid out. */ ! my_friendly_assert (TYPE_SIZE (DECL_CONTEXT (function)) ! && TYPE_BEING_DEFINED (DECL_CONTEXT (function)), ! 20031211); thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); --- 120,130 ---- /* 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. */ ! gcc_assert (!TREE_ASM_WRITTEN (function)); /* Likewise, we can only be adding thunks to a function declared in the class currently being laid out. */ ! gcc_assert (TYPE_SIZE (DECL_CONTEXT (function)) ! && TYPE_BEING_DEFINED (DECL_CONTEXT (function))); thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); *************** make_thunk (tree function, bool this_adj *** 168,175 **** 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 --- 150,155 ---- *************** finish_thunk (tree thunk) *** 198,204 **** tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk)); tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk); ! my_friendly_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk), 20021127); if (virtual_offset && DECL_RESULT_THUNK_P (thunk)) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); function = THUNK_TARGET (thunk); --- 178,184 ---- tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk)); tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk); ! gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk)); if (virtual_offset && DECL_RESULT_THUNK_P (thunk)) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); function = THUNK_TARGET (thunk); *************** finish_thunk (tree thunk) *** 218,224 **** cov_probe; cov_probe = TREE_CHAIN (cov_probe)) if (DECL_NAME (cov_probe) == name) { ! my_friendly_assert (!DECL_THUNKS (thunk), 20031023); THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe) ? THUNK_ALIAS (cov_probe) : cov_probe); break; --- 198,204 ---- cov_probe; cov_probe = TREE_CHAIN (cov_probe)) if (DECL_NAME (cov_probe) == name) { ! gcc_assert (!DECL_THUNKS (thunk)); THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe) ? THUNK_ALIAS (cov_probe) : cov_probe); break; *************** thunk_adjust (tree ptr, bool this_adjust *** 240,247 **** { if (this_adjusting) /* Adjust the pointer by the constant. */ ! ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr, ! ssize_int (fixed_offset))); /* If there's a virtual offset, look up that value in the vtable and adjust the pointer again. */ --- 220,227 ---- { if (this_adjusting) /* Adjust the pointer by the constant. */ ! ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, ! ssize_int (fixed_offset))); /* If there's a virtual offset, look up that value in the vtable and adjust the pointer again. */ *************** thunk_adjust (tree ptr, bool this_adjust *** 258,282 **** /* Form the vtable address. */ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); /* Find the entry with the vcall offset. */ ! vtable = build (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset); /* Get the offset itself. */ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); /* Adjust the `this' pointer. */ ! ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable)); } if (!this_adjusting) /* Adjust the pointer by the constant. */ ! ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr, ! ssize_int (fixed_offset))); return ptr; } - /* Garbage collector tables contains thunk_labelno even when places - inside ifdef block. */ static GTY (()) int thunk_labelno; - #ifdef ASM_OUTPUT_DEF /* Create a static alias to function. */ --- 238,259 ---- /* Form the vtable address. */ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); /* Find the entry with the vcall offset. */ ! vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset); /* Get the offset itself. */ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); /* Adjust the `this' pointer. */ ! ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable)); } if (!this_adjusting) /* Adjust the pointer by the constant. */ ! ptr = fold (build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, ! ssize_int (fixed_offset))); return ptr; } static GTY (()) int thunk_labelno; /* Create a static alias to function. */ *************** make_alias_for_thunk (tree function) *** 286,296 **** tree alias; char buf[256]; - #if defined (TARGET_IS_PE_COFF) - if (DECL_ONE_ONLY (function)) - return function; - #endif - ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); thunk_labelno++; alias = build_decl (FUNCTION_DECL, get_identifier (buf), --- 263,268 ---- *************** make_alias_for_thunk (tree function) *** 327,333 **** assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); return alias; } - #endif /* Emit the definition of a C++ multiple inheritance or covariant return vtable thunk. If EMIT_P is nonzero, the thunk is emitted --- 299,304 ---- *************** make_alias_for_thunk (tree function) *** 336,352 **** void use_thunk (tree thunk_fndecl, bool emit_p) { ! tree function, alias; tree virtual_offset; HOST_WIDE_INT fixed_offset, virtual_value; bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); /* We should have called finish_thunk to give it a name. */ ! my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127); /* We should never be using an alias, always refer to the aliased thunk. */ ! my_friendly_assert (!THUNK_ALIAS (thunk_fndecl), 20031023); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; --- 307,323 ---- void use_thunk (tree thunk_fndecl, bool emit_p) { ! tree a, t, function, alias; tree virtual_offset; HOST_WIDE_INT fixed_offset, virtual_value; bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); /* We should have called finish_thunk to give it a name. */ ! gcc_assert (DECL_NAME (thunk_fndecl)); /* We should never be using an alias, always refer to the aliased thunk. */ ! gcc_assert (!THUNK_ALIAS (thunk_fndecl)); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; *************** use_thunk (tree thunk_fndecl, bool emit_ *** 357,362 **** --- 328,337 ---- There's no need to process this thunk again. */ return; + if (DECL_THUNK_P (function)) + /* The target is itself a thunk, process it now. */ + use_thunk (function, emit_p); + /* Thunks are always addressable; they only appear in vtables. */ TREE_ADDRESSABLE (thunk_fndecl) = 1; *************** use_thunk (tree thunk_fndecl, bool emit_ *** 367,377 **** if (!emit_p) return; ! #ifdef ASM_OUTPUT_DEF ! alias = make_alias_for_thunk (function); ! #else ! alias = function; ! #endif fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); --- 342,351 ---- if (!emit_p) return; ! if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) ! alias = make_alias_for_thunk (function); ! else ! alias = function; fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); *************** use_thunk (tree thunk_fndecl, bool emit_ *** 381,387 **** if (!this_adjusting) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); ! my_friendly_assert (virtual_value, 20021026); } else virtual_value = 0; --- 355,361 ---- if (!this_adjusting) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); ! gcc_assert (virtual_value); } else virtual_value = 0; *************** use_thunk (tree thunk_fndecl, bool emit_ *** 394,399 **** --- 368,377 ---- rewrite. */ TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); + DECL_VISIBILITY_SPECIFIED (thunk_fndecl) + = DECL_VISIBILITY_SPECIFIED (function); + if (flag_weak && TREE_PUBLIC (thunk_fndecl)) + comdat_linkage (thunk_fndecl); if (flag_syntax_only) { *************** use_thunk (tree thunk_fndecl, bool emit_ *** 403,411 **** push_to_top_level (); ! #if defined (ASM_OUTPUT_DEF) \ ! && !defined (TARGET_IS_PE_COFF) ! if (targetm.have_named_sections) { resolve_unique_section (function, 0, flag_function_sections); --- 381,388 ---- push_to_top_level (); ! if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) ! && targetm.have_named_sections) { resolve_unique_section (function, 0, flag_function_sections); *************** use_thunk (tree thunk_fndecl, bool emit_ *** 417,428 **** DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); } } - #endif /* The back-end expects DECL_INITIAL to contain a BLOCK, so we create one. */ DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); ! BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = DECL_ARGUMENTS (thunk_fndecl); if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, --- 394,417 ---- DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); } } /* The back-end expects DECL_INITIAL to contain a BLOCK, so we create one. */ DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); ! ! /* Set up cloned argument trees for the thunk. */ ! t = NULL_TREE; ! for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) ! { ! tree x = copy_node (a); ! TREE_CHAIN (x) = t; ! DECL_CONTEXT (x) = thunk_fndecl; ! SET_DECL_RTL (x, NULL_RTX); ! t = x; ! } ! a = nreverse (t); ! DECL_ARGUMENTS (thunk_fndecl) = a; ! BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a; if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, *************** use_thunk (tree thunk_fndecl, bool emit_ *** 443,451 **** 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 --- 432,437 ---- *************** use_thunk (tree thunk_fndecl, bool emit_ *** 455,481 **** just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ - tree a, t; - if (varargs_function_p (function)) ! error ("generic thunk code fails for method `%#D' which uses `...'", function); - /* Set up cloned argument trees for the thunk. */ - t = NULL_TREE; - for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) - { - tree x = copy_node (a); - TREE_CHAIN (x) = t; - DECL_CONTEXT (x) = thunk_fndecl; - SET_DECL_RTL (x, NULL_RTX); - t = x; - } - a = nreverse (t); - DECL_ARGUMENTS (thunk_fndecl) = a; DECL_RESULT (thunk_fndecl) = NULL_TREE; ! start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED); /* We don't bother with a body block for thunks. */ /* There's no need to check accessibility inside the thunk body. */ --- 441,453 ---- just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ if (varargs_function_p (function)) ! error ("generic thunk code fails for method %q#D which uses %<...%>", function); DECL_RESULT (thunk_fndecl) = NULL_TREE; ! start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED); /* We don't bother with a body block for thunks. */ /* There's no need to check accessibility inside the thunk body. */ *************** use_thunk (tree thunk_fndecl, bool emit_ *** 493,511 **** t = nreverse (t); t = build_call (alias, t); CALL_FROM_THUNK_P (t) = 1; - t = force_target_expr (TREE_TYPE (t), t); - if (!this_adjusting) - t = thunk_adjust (t, /*this_adjusting=*/0, - fixed_offset, virtual_offset); if (VOID_TYPE_P (TREE_TYPE (t))) finish_expr_stmt (t); else ! finish_return_stmt (t); /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ ! mark_referenced (DECL_ASSEMBLER_NAME (thunk_fndecl)); /* But we don't want debugging information about it. */ DECL_IGNORED_P (thunk_fndecl) = 1; --- 465,485 ---- t = nreverse (t); t = build_call (alias, t); CALL_FROM_THUNK_P (t) = 1; if (VOID_TYPE_P (TREE_TYPE (t))) finish_expr_stmt (t); else ! { ! t = force_target_expr (TREE_TYPE (t), t); ! if (!this_adjusting) ! t = thunk_adjust (t, /*this_adjusting=*/0, ! fixed_offset, virtual_offset); ! finish_return_stmt (t); ! } /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ ! mark_decl_referenced (thunk_fndecl); /* But we don't want debugging information about it. */ DECL_IGNORED_P (thunk_fndecl) = 1; *************** static void *** 527,533 **** do_build_copy_constructor (tree fndecl) { tree parm = FUNCTION_FIRST_USER_PARM (fndecl); - tree t; parm = convert_from_reference (parm); --- 501,506 ---- *************** do_build_copy_constructor (tree fndecl) *** 537,564 **** if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { ! t = build (INIT_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } 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 member_init_list = NULL_TREE; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; /* Initialize all the base-classes with the parameter converted to their type so that we get their copy constructor and not another constructor that takes current_class_type. We must deal with the binfo's directly as a direct base might be inaccessible due to ambiguity. */ ! for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; ! t = TREE_CHAIN (t)) { - tree binfo = TREE_VALUE (t); - member_init_list = tree_cons (binfo, build_tree_list (NULL_TREE, --- 510,535 ---- if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { ! tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); tree member_init_list = NULL_TREE; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; + tree binfo, base_binfo; + VEC (tree) *vbases; /* Initialize all the base-classes with the parameter converted to their type so that we get their copy constructor and not another constructor that takes current_class_type. We must deal with the binfo's directly as a direct base might be inaccessible due to ambiguity. */ ! for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; ! VEC_iterate (tree, vbases, i, binfo); i++) { member_init_list = tree_cons (binfo, build_tree_list (NULL_TREE, *************** do_build_copy_constructor (tree fndecl) *** 567,608 **** member_init_list); } ! for (i = 0; i < n_bases; ++i) { ! tree binfo = TREE_VEC_ELT (binfos, i); ! if (TREE_VIA_VIRTUAL (binfo)) continue; 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)) { ! tree init; tree field = fields; tree expr_type; if (TREE_CODE (field) != FIELD_DECL) continue; ! init = parm; if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; - - /* True for duplicate members. */ - if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) - continue; } ! else if ((t = TREE_TYPE (field)) != NULL_TREE ! && ANON_AGGR_TYPE_P (t) ! && TYPE_FIELDS (t) != NULL_TREE) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else --- 538,573 ---- member_init_list); } ! for (binfo = TYPE_BINFO (current_class_type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { ! if (BINFO_VIRTUAL_P (base_binfo)) continue; member_init_list ! = tree_cons (base_binfo, build_tree_list (NULL_TREE, build_base_path (PLUS_EXPR, parm, ! base_binfo, 1)), member_init_list); } for (; fields; fields = TREE_CHAIN (fields)) { ! tree init = parm; tree field = fields; tree expr_type; if (TREE_CODE (field) != FIELD_DECL) continue; ! expr_type = TREE_TYPE (field); if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } ! else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else *************** do_build_copy_constructor (tree fndecl) *** 613,626 **** the field is "T", then the type will usually be "const T". (There are no cv-qualified variants of reference types.) */ - expr_type = TREE_TYPE (field); if (TREE_CODE (expr_type) != REFERENCE_TYPE) ! expr_type = cp_build_qualified_type (expr_type, cvquals); ! init = build (COMPONENT_REF, expr_type, init, field); init = build_tree_list (NULL_TREE, init); ! member_init_list ! = tree_cons (field, init, member_init_list); } finish_mem_initializers (member_init_list); } --- 578,596 ---- the field is "T", then the type will usually be "const T". (There are no cv-qualified variants of reference types.) */ if (TREE_CODE (expr_type) != REFERENCE_TYPE) ! { ! int quals = cvquals; ! ! if (DECL_MUTABLE_P (field)) ! quals &= ~TYPE_QUAL_CONST; ! expr_type = cp_build_qualified_type (expr_type, quals); ! } ! ! init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); init = build_tree_list (NULL_TREE, init); ! member_init_list = tree_cons (field, init, member_init_list); } finish_mem_initializers (member_init_list); } *************** do_build_assign_ref (tree fndecl) *** 632,638 **** tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree compound_stmt; ! compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) --- 602,608 ---- tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree compound_stmt; ! compound_stmt = begin_compound_stmt (0); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) *************** do_build_assign_ref (tree fndecl) *** 641,647 **** if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { ! tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else --- 611,617 ---- if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { ! tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else *************** do_build_assign_ref (tree fndecl) *** 649,672 **** tree fields; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; /* Assign to each of the direct base classes. */ ! for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i) { - 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)); } --- 619,642 ---- tree fields; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; + tree binfo, base_binfo; /* Assign to each of the direct base classes. */ ! for (binfo = TYPE_BINFO (current_class_type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree converted_parm; /* 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, base_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), ! base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); } *************** do_build_assign_ref (tree fndecl) *** 675,727 **** fields; fields = TREE_CHAIN (fields)) { ! tree comp, init, t; tree field = fields; if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; ! if (CP_TYPE_CONST_P (TREE_TYPE (field))) { ! error ("non-static const member `%#D', can't use default assignment operator", field); continue; } ! else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) { ! error ("non-static reference member `%#D', can't use default assignment operator", field); continue; } - comp = current_class_ref; - init = parm; - if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; - - /* True for duplicate members. */ - if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) - continue; } ! else if ((t = TREE_TYPE (field)) != NULL_TREE ! && ANON_AGGR_TYPE_P (t) ! && TYPE_FIELDS (t) != NULL_TREE) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; ! comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); ! init = build (COMPONENT_REF, ! cp_build_qualified_type (TREE_TYPE (field), cvquals), ! init, field); if (DECL_NAME (field)) ! finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); else ! finish_expr_stmt (build (MODIFY_EXPR, TREE_TYPE (comp), comp, ! init)); } } finish_return_stmt (current_class_ref); --- 645,701 ---- fields; fields = TREE_CHAIN (fields)) { ! tree comp = current_class_ref; ! tree init = parm; tree field = fields; + tree expr_type; + int quals; if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; ! expr_type = TREE_TYPE (field); ! ! if (CP_TYPE_CONST_P (expr_type)) { ! error ("non-static const member %q#D, can't use default " ! "assignment operator", field); continue; } ! else if (TREE_CODE (expr_type) == REFERENCE_TYPE) { ! error ("non-static reference member %q#D, can't use " ! "default assignment operator", field); continue; } if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } ! else if (ANON_AGGR_TYPE_P (expr_type) ! && TYPE_FIELDS (expr_type) != NULL_TREE) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; ! comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); ! ! /* Compute the type of init->field */ ! quals = cvquals; ! if (DECL_MUTABLE_P (field)) ! quals &= ~TYPE_QUAL_CONST; ! expr_type = cp_build_qualified_type (expr_type, quals); ! ! init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); if (DECL_NAME (field)) ! init = build_modify_expr (comp, NOP_EXPR, init); else ! init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); ! finish_expr_stmt (init); } } finish_return_stmt (current_class_ref); *************** synthesize_method (tree fndecl) *** 735,749 **** tree context = decl_function_context (fndecl); bool need_body = true; tree stmt; ! ! if (at_eof) ! import_export_decl (fndecl); /* If we've been asked to synthesize a clone, just synthesize the cloned function instead. Doing so will automatically fill in the body for the clone. */ if (DECL_CLONED_FUNCTION_P (fndecl)) { synthesize_method (DECL_CLONED_FUNCTION (fndecl)); return; } --- 709,723 ---- tree context = decl_function_context (fndecl); bool need_body = true; tree stmt; ! location_t save_input_location = input_location; /* If we've been asked to synthesize a clone, just synthesize the cloned function instead. Doing so will automatically fill in the body for the clone. */ if (DECL_CLONED_FUNCTION_P (fndecl)) { + DECL_SOURCE_LOCATION (DECL_CLONED_FUNCTION (fndecl)) = + DECL_SOURCE_LOCATION (fndecl); synthesize_method (DECL_CLONED_FUNCTION (fndecl)); return; } *************** synthesize_method (tree fndecl) *** 757,773 **** else if (nested) push_function_context_to (context); ! /* Put the function definition at the position where it is needed, ! rather than within the body of the class. That way, an error ! 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. */ ! DECL_SOURCE_LOCATION (fndecl) = input_location; ! interface_unknown = 1; ! start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); ! clear_last_expr (); stmt = begin_function_body (); if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) --- 731,739 ---- else if (nested) push_function_context_to (context); ! input_location = DECL_SOURCE_LOCATION (fndecl); ! start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); stmt = begin_function_body (); if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) *************** synthesize_method (tree fndecl) *** 789,802 **** if (need_body) { tree compound_stmt; ! compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); finish_compound_stmt (compound_stmt); } finish_function_body (stmt); expand_or_defer_fn (finish_function (0)); ! extract_interface_info (); if (! context) pop_from_top_level (); else if (nested) --- 755,769 ---- if (need_body) { tree compound_stmt; ! compound_stmt = begin_compound_stmt (BCS_FN_BODY); finish_compound_stmt (compound_stmt); } finish_function_body (stmt); expand_or_defer_fn (finish_function (0)); ! input_location = save_input_location; ! if (! context) pop_from_top_level (); else if (nested) *************** synthesize_exception_spec (tree type, tr *** 817,829 **** { tree raises = empty_except_spec; tree fields = TYPE_FIELDS (type); ! int i, n_bases = CLASSTYPE_N_BASECLASSES (type); ! tree binfos = TYPE_BINFO_BASETYPES (type); ! for (i = 0; i != n_bases; i++) { ! tree base = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); ! tree fn = (*extractor) (base, client); if (fn) { tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); --- 784,796 ---- { tree raises = empty_except_spec; tree fields = TYPE_FIELDS (type); ! tree binfo, base_binfo; ! int i; ! for (binfo = TYPE_BINFO (type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { ! tree fn = (*extractor) (BINFO_TYPE (base_binfo), client); if (fn) { tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); *************** synthesize_exception_spec (tree type, tr *** 859,871 **** static tree locate_dtor (tree type, void *client ATTRIBUTE_UNUSED) { ! tree fns; ! ! if (!TYPE_HAS_DESTRUCTOR (type)) ! return NULL_TREE; ! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ! CLASSTYPE_DESTRUCTOR_SLOT); ! return fns; } /* Locate the default ctor of TYPE. */ --- 826,832 ---- static tree locate_dtor (tree type, void *client ATTRIBUTE_UNUSED) { ! return CLASSTYPE_DESTRUCTORS (type); } /* Locate the default ctor of TYPE. */ *************** locate_ctor (tree type, void *client ATT *** 877,886 **** if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) return NULL_TREE; ! ! fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ! CLASSTYPE_CONSTRUCTOR_SLOT); ! for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); --- 838,850 ---- if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) return NULL_TREE; ! ! /* Call lookup_fnfields_1 to create the constructor declarations, if ! necessary. */ ! if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) ! return lazily_declare_fn (sfk_constructor, type); ! ! for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); *************** locate_copy (tree type, void *client_) *** 906,926 **** { struct copy_data *client = (struct copy_data *)client_; tree fns; - int ix = -1; tree best = NULL_TREE; bool excess_p = false; if (client->name) { ! if (TYPE_HAS_ASSIGN_REF (type)) ! ix = lookup_fnfields_1 (type, client->name); } else if (TYPE_HAS_INIT_REF (type)) ! ix = CLASSTYPE_CONSTRUCTOR_SLOT; ! if (ix < 0) return NULL_TREE; - fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix); - for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); --- 870,896 ---- { struct copy_data *client = (struct copy_data *)client_; tree fns; tree best = NULL_TREE; bool excess_p = false; if (client->name) { ! int ix; ! ix = lookup_fnfields_1 (type, client->name); ! if (ix < 0) ! return NULL_TREE; ! fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix); } else if (TYPE_HAS_INIT_REF (type)) ! { ! /* If construction of the copy constructor was postponed, create ! it now. */ ! if (CLASSTYPE_LAZY_COPY_CTOR (type)) ! lazily_declare_fn (sfk_copy_constructor, type); ! fns = CLASSTYPE_CONSTRUCTORS (type); ! } ! else return NULL_TREE; for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); *************** locate_copy (tree type, void *client_) *** 956,985 **** /* Implicitly declare the special function indicated by KIND, as a member of TYPE. For copy constructors and assignment operators, CONST_P indicates whether these functions should take a const ! reference argument or a non-const reference. */ tree implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) { ! tree declspecs = NULL_TREE; ! tree fn, args = NULL_TREE; tree raises = empty_except_spec; ! bool retref = false; ! bool has_parm = false; ! tree name = constructor_name (type); switch (kind) { case sfk_destructor: /* Destructor. */ ! name = build_nt (BIT_NOT_EXPR, name); ! args = void_list_node; raises = synthesize_exception_spec (type, &locate_dtor, 0); break; case sfk_constructor: /* Default constructor. */ ! args = void_list_node; raises = synthesize_exception_spec (type, &locate_ctor, 0); break; --- 926,969 ---- /* Implicitly declare the special function indicated by KIND, as a member of TYPE. For copy constructors and assignment operators, CONST_P indicates whether these functions should take a const ! reference argument or a non-const reference. Returns the ! FUNCTION_DECL for the implicitly declared function. */ tree implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) { ! tree fn; ! tree parameter_types = void_list_node; ! tree return_type; ! tree fn_type; tree raises = empty_except_spec; ! tree rhs_parm_type = NULL_TREE; ! tree name; ! ! type = TYPE_MAIN_VARIANT (type); ! ! if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type)) ! { ! if (kind == sfk_destructor) ! /* See comment in check_special_function_return_type. */ ! return_type = build_pointer_type (void_type_node); ! else ! return_type = build_pointer_type (type); ! } ! else ! return_type = void_type_node; switch (kind) { case sfk_destructor: /* Destructor. */ ! name = constructor_name (type); raises = synthesize_exception_spec (type, &locate_dtor, 0); break; case sfk_constructor: /* Default constructor. */ ! name = constructor_name (type); raises = synthesize_exception_spec (type, &locate_ctor, 0); break; *************** implicitly_declare_fn (special_function_ *** 987,1044 **** case sfk_assignment_operator: { struct copy_data data; - tree argtype = type; - has_parm = true; data.name = NULL; data.quals = 0; if (kind == sfk_assignment_operator) { ! retref = true; ! declspecs = build_tree_list (NULL_TREE, type); ! name = ansi_assopname (NOP_EXPR); data.name = name; } if (const_p) { data.quals = TYPE_QUAL_CONST; ! argtype = build_qualified_type (argtype, TYPE_QUAL_CONST); } ! ! argtype = build_reference_type (argtype); ! args = build_tree_list (hash_tree_chain (argtype, NULL_TREE), ! get_identifier ("_ctor_arg")); ! args = tree_cons (NULL_TREE, args, void_list_node); ! raises = synthesize_exception_spec (type, &locate_copy, &data); break; } default: ! abort (); } ! TREE_PARMLIST (args) = 1; ! ! { ! tree declarator = make_call_declarator (name, args, NULL_TREE, raises); ! ! if (retref) ! declarator = build_nt (ADDR_EXPR, declarator); ! ! fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); ! if (has_parm) ! TREE_USED (FUNCTION_FIRST_USER_PARM (fn)) = 1; ! } ! ! my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408); DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_INLINE (fn) = 1; ! defer_fn (fn); ! return fn; } --- 971,1107 ---- case sfk_assignment_operator: { struct copy_data data; data.name = NULL; data.quals = 0; if (kind == sfk_assignment_operator) { ! return_type = build_reference_type (type); name = ansi_assopname (NOP_EXPR); data.name = name; } + else + name = constructor_name (type); + if (const_p) { data.quals = TYPE_QUAL_CONST; ! rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST); } ! else ! rhs_parm_type = type; ! rhs_parm_type = build_reference_type (rhs_parm_type); ! parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); raises = synthesize_exception_spec (type, &locate_copy, &data); break; } default: ! gcc_unreachable (); } ! /* Create the function. */ ! fn_type = build_method_type_directly (type, return_type, parameter_types); ! if (raises) ! fn_type = build_exception_variant (fn_type, raises); ! fn = build_lang_decl (FUNCTION_DECL, name, fn_type); ! DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); ! if (kind == sfk_constructor || kind == sfk_copy_constructor) ! DECL_CONSTRUCTOR_P (fn) = 1; ! else if (kind == sfk_destructor) ! DECL_DESTRUCTOR_P (fn) = 1; ! else ! { ! DECL_ASSIGNMENT_OPERATOR_P (fn) = 1; ! SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR); ! } ! /* Create the argument list. The call to "grokclassfn" will add the ! "this" parameter and any other implicit parameters. */ ! if (rhs_parm_type) ! { ! /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we ! want its type to be included in the mangled function ! name. */ ! DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type); ! TREE_READONLY (DECL_ARGUMENTS (fn)) = 1; ! } + grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL, + TYPE_UNQUALIFIED); + grok_special_member_properties (fn); + set_linkage_according_to_type (type, fn); + rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); + DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_INLINE (fn) = 1; ! gcc_assert (!TREE_USED (fn)); ! ! return fn; ! } ! ! /* Add an implicit declaration to TYPE for the kind of function ! indicated by SFK. Return the FUNCTION_DECL for the new implicit ! declaration. */ ! ! tree ! lazily_declare_fn (special_function_kind sfk, tree type) ! { ! tree fn; ! bool const_p; ! ! /* Figure out whether or not the argument has a const reference ! type. */ ! if (sfk == sfk_copy_constructor) ! const_p = TYPE_HAS_CONST_INIT_REF (type); ! else if (sfk == sfk_assignment_operator) ! const_p = TYPE_HAS_CONST_ASSIGN_REF (type); ! else ! /* In this case, CONST_P will be ignored. */ ! const_p = false; ! /* Declare the function. */ ! fn = implicitly_declare_fn (sfk, type, const_p); ! /* A destructor may be virtual. */ ! if (sfk == sfk_destructor) ! check_for_override (fn, type); ! /* Add it to CLASSTYPE_METHOD_VEC. */ ! add_method (type, fn); ! /* Add it to TYPE_METHODS. */ ! if (sfk == sfk_destructor ! && DECL_VIRTUAL_P (fn) ! && abi_version_at_least (2)) ! /* The ABI requires that a virtual destructor go at the end of the ! vtable. */ ! TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn); ! else ! { ! /* G++ 3.2 put the implicit destructor at the *beginning* of the ! TYPE_METHODS list, which cause the destructor to be emitted ! in an incorrect location in the vtable. */ ! if (warn_abi && DECL_VIRTUAL_P (fn)) ! warning ("vtable layout for class %qT may not be ABI-compliant" ! "and may change in a future version of GCC due to " ! "implicit virtual destructor", ! type); ! TREE_CHAIN (fn) = TYPE_METHODS (type); ! TYPE_METHODS (type) = fn; ! } ! maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); ! if (sfk == sfk_assignment_operator) ! CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0; ! else ! { ! /* Remember that the function has been created. */ ! if (sfk == sfk_constructor) ! CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; ! else if (sfk == sfk_copy_constructor) ! CLASSTYPE_LAZY_COPY_CTOR (type) = 0; ! else if (sfk == sfk_destructor) ! CLASSTYPE_LAZY_DESTRUCTOR (type) = 0; ! /* Create appropriate clones. */ ! clone_function_decl (fn, /*update_method_vec=*/true); ! } ! return fn; } diff -Nrcpad gcc-3.4.3/gcc/cp/name-lookup.c gcc-4.0.0/gcc/cp/name-lookup.c *** gcc-3.4.3/gcc/cp/name-lookup.c Wed Oct 27 04:32:56 2004 --- gcc-4.0.0/gcc/cp/name-lookup.c Wed Mar 2 20:02:04 2005 *************** *** 1,5 **** /* Definitions for C++ name lookup routines. ! Copyright (C) 2003, 2004 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. --- 1,5 ---- /* Definitions for C++ name lookup routines. ! Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. *************** Boston, MA 02111-1307, USA. */ *** 30,48 **** #include "timevar.h" #include "toplev.h" #include "diagnostic.h" static cxx_scope *innermost_nonclass_level (void); ! static tree select_decl (cxx_binding *, int); static cxx_binding *binding_for_name (cxx_scope *, tree); ! static tree lookup_name_current_level (tree); ! static void push_local_binding (tree, tree, int); static tree push_overloaded_decl (tree, int); ! static bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int); ! static bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int); static tree lookup_type_current_level (tree); static tree push_using_directive (tree); ! /* The :: namespace. */ --- 30,57 ---- #include "timevar.h" #include "toplev.h" #include "diagnostic.h" + #include "debug.h" + + /* The bindings for a particular name in a particular scope. */ + + struct scope_binding { + tree value; + tree type; + }; + #define EMPTY_SCOPE_BINDING { NULL_TREE, NULL_TREE } static cxx_scope *innermost_nonclass_level (void); ! static tree select_decl (const struct scope_binding *, int); static cxx_binding *binding_for_name (cxx_scope *, tree); ! static tree lookup_name_innermost_nonclass_level (tree); static tree push_overloaded_decl (tree, int); ! static bool lookup_using_namespace (tree, struct scope_binding *, tree, tree, int); ! static bool qualified_lookup_using_namespace (tree, tree, ! struct scope_binding *, int); static tree lookup_type_current_level (tree); static tree push_using_directive (tree); ! static void cp_emit_debug_info_for_using (tree, tree); /* The :: namespace. */ *************** tree global_namespace; *** 50,56 **** /* The name of the anonymous namespace, throughout this translation unit. */ ! GTY(()) tree anonymous_namespace_name; /* Compute the chain index of a binding_entry given the HASH value of its --- 59,65 ---- /* The name of the anonymous namespace, throughout this translation unit. */ ! static GTY(()) tree anonymous_namespace_name; /* Compute the chain index of a binding_entry given the HASH value of its *************** GTY(()) tree anonymous_namespace_name; *** 61,67 **** /* A free list of "binding_entry"s awaiting for re-use. */ ! static GTY((deletable(""))) binding_entry free_binding_entry = NULL; /* Create a binding_entry object for (NAME, TYPE). */ --- 70,76 ---- /* A free list of "binding_entry"s awaiting for re-use. */ ! static GTY((deletable)) binding_entry free_binding_entry = NULL; /* Create a binding_entry object for (NAME, TYPE). */ *************** binding_entry_make (tree name, tree type *** 76,82 **** free_binding_entry = entry->chain; } else ! entry = ggc_alloc (sizeof (struct binding_entry_s)); entry->name = name; entry->type = type; --- 85,91 ---- free_binding_entry = entry->chain; } else ! entry = GGC_NEW (struct binding_entry_s); entry->name = name; entry->type = type; *************** binding_entry_make (tree name, tree type *** 86,92 **** } /* Put ENTRY back on the free list. */ ! static inline void binding_entry_free (binding_entry entry) { --- 95,101 ---- } /* Put ENTRY back on the free list. */ ! #if 0 static inline void binding_entry_free (binding_entry entry) { *************** binding_entry_free (binding_entry entry) *** 95,100 **** --- 104,110 ---- entry->chain = free_binding_entry; free_binding_entry = entry; } + #endif /* The datatype used to implement the mapping from names to types at a given scope. */ *************** binding_table_construct (binding_table t *** 118,129 **** { table->chain_count = chain_count; table->entry_count = 0; ! table->chain = ggc_alloc_cleared ! (table->chain_count * sizeof (binding_entry)); } /* Make TABLE's entries ready for reuse. */ ! static void binding_table_free (binding_table table) { --- 128,138 ---- { table->chain_count = chain_count; table->entry_count = 0; ! table->chain = GGC_CNEWVEC (binding_entry, table->chain_count); } /* Make TABLE's entries ready for reuse. */ ! #if 0 static void binding_table_free (binding_table table) { *************** binding_table_free (binding_table table) *** 146,158 **** } 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)); table->chain = NULL; binding_table_construct (table, chain_count); return table; --- 155,168 ---- } table->entry_count = 0; } + #endif /* 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_NEW (struct binding_table_s); table->chain = NULL; binding_table_construct (table, chain_count); return table; *************** binding_table_find (binding_table table, *** 217,298 **** return entry; } - /* Return the binding_entry, if any, that maps NAME to an anonymous type. */ - - static 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 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 = NULL; - 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. */ - - 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 --- 227,232 ---- *************** binding_table_foreach (binding_table tab *** 317,326 **** /* A free list of "cxx_binding"s, connected by their PREVIOUS. */ ! static GTY((deletable (""))) cxx_binding *free_bindings; ! /* Zero out a cxx_binding pointed to by B. */ ! #define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding)) /* (GC)-allocate a binding object with VALUE and TYPE member initialized. */ --- 251,268 ---- /* A free list of "cxx_binding"s, connected by their PREVIOUS. */ ! static GTY((deletable)) cxx_binding *free_bindings; ! /* Initialize VALUE and TYPE field for BINDING, and set the PREVIOUS ! field to NULL. */ ! ! static inline void ! cxx_binding_init (cxx_binding *binding, tree value, tree type) ! { ! binding->value = value; ! binding->type = type; ! binding->previous = NULL; ! } /* (GC)-allocate a binding object with VALUE and TYPE member initialized. */ *************** cxx_binding_make (tree value, tree type) *** 334,344 **** free_bindings = binding->previous; } else ! binding = ggc_alloc (sizeof (cxx_binding)); ! binding->value = value; ! binding->type = type; ! binding->previous = NULL; return binding; } --- 276,284 ---- free_bindings = binding->previous; } else ! binding = GGC_NEW (cxx_binding); ! cxx_binding_init (binding, value, type); return binding; } *************** cxx_binding_free (cxx_binding *binding) *** 353,369 **** free_bindings = binding; } /* Make DECL the innermost binding for ID. The LEVEL is the binding level at which this declaration is being bound. */ static void push_binding (tree id, tree decl, cxx_scope* level) { ! cxx_binding *binding = cxx_binding_make (decl, NULL); /* Now, fill in the binding information. */ binding->previous = IDENTIFIER_BINDING (id); - binding->scope = level; INHERITED_VALUE_BINDING_P (binding) = 0; LOCAL_BINDING_P (binding) = (level != class_binding_level); --- 293,357 ---- free_bindings = binding; } + /* Create a new binding for NAME (with the indicated VALUE and TYPE + bindings) in the class scope indicated by SCOPE. */ + + static cxx_binding * + new_class_binding (tree name, tree value, tree type, cxx_scope *scope) + { + cp_class_binding *cb; + cxx_binding *binding; + + if (VEC_length (cp_class_binding, scope->class_shadowed)) + { + cp_class_binding *old_base; + old_base = VEC_index (cp_class_binding, scope->class_shadowed, 0); + if (VEC_reserve (cp_class_binding, scope->class_shadowed, -1)) + { + /* Fixup the current bindings, as they might have moved. */ + size_t i; + + for (i = 0; + VEC_iterate (cp_class_binding, scope->class_shadowed, i, cb); + i++) + { + cxx_binding **b; + b = &IDENTIFIER_BINDING (cb->identifier); + while (*b != &old_base[i].base) + b = &((*b)->previous); + *b = &cb->base; + } + } + cb = VEC_quick_push (cp_class_binding, scope->class_shadowed, NULL); + } + else + cb = VEC_safe_push (cp_class_binding, scope->class_shadowed, NULL); + + cb->identifier = name; + binding = &cb->base; + binding->scope = scope; + cxx_binding_init (binding, value, type); + return binding; + } + /* Make DECL the innermost binding for ID. The LEVEL is the binding level at which this declaration is being bound. */ static void push_binding (tree id, tree decl, cxx_scope* level) { ! cxx_binding *binding; + if (level != class_binding_level) + { + binding = cxx_binding_make (decl, NULL_TREE); + binding->scope = level; + } + else + binding = new_class_binding (id, decl, /*type=*/NULL_TREE, level); + /* Now, fill in the binding information. */ binding->previous = IDENTIFIER_BINDING (id); INHERITED_VALUE_BINDING_P (binding) = 0; LOCAL_BINDING_P (binding) = (level != class_binding_level); *************** pop_binding (tree id, tree decl) *** 389,404 **** binding = IDENTIFIER_BINDING (id); /* The name should be bound. */ ! my_friendly_assert (binding != NULL, 0); /* The DECL will be either the ordinary binding or the type binding for this identifier. Remove that binding. */ if (binding->value == decl) binding->value = NULL_TREE; - else if (binding->type == decl) - binding->type = NULL_TREE; else ! abort (); if (!binding->value && !binding->type) { --- 377,393 ---- binding = IDENTIFIER_BINDING (id); /* The name should be bound. */ ! gcc_assert (binding != NULL); /* The DECL will be either the ordinary binding or the type binding for this identifier. Remove that binding. */ if (binding->value == decl) binding->value = NULL_TREE; else ! { ! gcc_assert (binding->type == decl); ! binding->type = NULL_TREE; ! } if (!binding->value && !binding->type) { *************** supplement_binding (cxx_binding *binding *** 468,486 **** else if (TREE_CODE (bval) == TYPE_DECL && TREE_CODE (decl) == TYPE_DECL && DECL_NAME (decl) == DECL_NAME (bval) && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval)) /* If either type involves template parameters, we must wait until instantiation. */ || uses_template_parms (TREE_TYPE (decl)) || uses_template_parms (TREE_TYPE (bval)))) /* We have two typedef-names, both naming the same type to have ! the same name. This is OK because of: [dcl.typedef] In a given scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the ! type to which it already refers. */ ok = false; /* There can be two block-scope declarations of the same variable, so long as they are `extern' declarations. However, there cannot --- 457,480 ---- else if (TREE_CODE (bval) == TYPE_DECL && TREE_CODE (decl) == TYPE_DECL && DECL_NAME (decl) == DECL_NAME (bval) + && binding->scope->kind != sk_class && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval)) /* If either type involves template parameters, we must wait until instantiation. */ || uses_template_parms (TREE_TYPE (decl)) || uses_template_parms (TREE_TYPE (bval)))) /* We have two typedef-names, both naming the same type to have ! the same name. In general, this is OK because of: [dcl.typedef] In a given scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the ! type to which it already refers. ! ! However, in class scopes, this rule does not apply due to the ! stricter language in [class.mem] prohibiting redeclarations of ! members. */ ok = false; /* There can be two block-scope declarations of the same variable, so long as they are `extern' declarations. However, there cannot *************** supplement_binding (cxx_binding *binding *** 511,518 **** ok = false; else { ! error ("declaration of `%#D'", decl); ! cp_error_at ("conflicts with previous declaration `%#D'", bval); ok = false; } --- 505,512 ---- ok = false; else { ! error ("declaration of %q#D", decl); ! cp_error_at ("conflicts with previous declaration %q#D", bval); ok = false; } *************** add_decl_to_level (tree decl, cxx_scope *** 546,552 **** /* If appropriate, add decl to separate list of statics. We include extern variables because they might turn out to be static later. It's OK for this list to contain a few false ! positives. */ if (b->kind == sk_namespace) if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) --- 540,546 ---- /* If appropriate, add decl to separate list of statics. We include extern variables because they might turn out to be static later. It's OK for this list to contain a few false ! positives. */ if (b->kind == sk_namespace) if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) *************** pushdecl (tree x) *** 615,621 **** if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ()) t = namespace_binding (name, DECL_CONTEXT (x)); else ! t = lookup_name_current_level (name); /* [basic.link] If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities --- 609,615 ---- if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ()) t = namespace_binding (name, DECL_CONTEXT (x)); else ! t = lookup_name_innermost_nonclass_level (name); /* [basic.link] If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities *************** pushdecl (tree x) *** 627,633 **** && DECL_EXTERNAL (x)) { /* Look in block scope. */ ! t = IDENTIFIER_VALUE (name); /* Or in the innermost namespace. */ if (! t) t = namespace_binding (name, DECL_CONTEXT (x)); --- 621,627 ---- && DECL_EXTERNAL (x)) { /* Look in block scope. */ ! t = innermost_non_namespace_value (name); /* Or in the innermost namespace. */ if (! t) t = namespace_binding (name, DECL_CONTEXT (x)); *************** pushdecl (tree x) *** 664,692 **** t = NULL_TREE; } ! if (t == error_mark_node) ! { ! /* error_mark_node is 0 for a while during initialization! */ ! t = NULL_TREE; ! cp_error_at ("`%#D' used prior to declaration", x); ! } ! else if (t != NULL_TREE) { if (different_binding_level) { if (decls_match (x, t)) /* The standard only says that the local extern inherits linkage from the previous decl; in ! particular, default args are not shared. It would ! be nice to propagate inlining info, though. FIXME. */ ! TREE_PUBLIC (x) = TREE_PUBLIC (t); } else if (TREE_CODE (t) == PARM_DECL) { ! if (DECL_CONTEXT (t) == NULL_TREE) ! /* This is probably caused by too many errors, but calling ! abort will say that if errors have occurred. */ ! abort (); /* Check for duplicate params. */ if (duplicate_decls (x, t)) --- 658,683 ---- t = NULL_TREE; } ! if (t && t != error_mark_node) { if (different_binding_level) { if (decls_match (x, t)) /* The standard only says that the local extern inherits linkage from the previous decl; in ! particular, default args are not shared. We must ! also tell cgraph to treat these decls as the same, ! or we may neglect to emit an "unused" static - we ! do this by making the DECL_UIDs equal, which should ! be viewed as a kludge. FIXME. */ ! { ! TREE_PUBLIC (x) = TREE_PUBLIC (t); ! DECL_UID (x) = DECL_UID (t); ! } } else if (TREE_CODE (t) == PARM_DECL) { ! gcc_assert (DECL_CONTEXT (t)); /* Check for duplicate params. */ if (duplicate_decls (x, t)) *************** pushdecl (tree x) *** 699,706 **** else if (t == wchar_decl_node) { if (pedantic && ! DECL_IN_SYSTEM_HEADER (x)) ! pedwarn ("redeclaration of `wchar_t' as `%T'", ! TREE_TYPE (x)); /* Throw away the redeclaration. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); --- 690,697 ---- else if (t == wchar_decl_node) { if (pedantic && ! DECL_IN_SYSTEM_HEADER (x)) ! pedwarn ("redeclaration of % as %qT", ! TREE_TYPE (x)); /* Throw away the redeclaration. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); *************** pushdecl (tree x) *** 731,738 **** [basic.start.main] This function shall not be overloaded. */ ! cp_error_at ("invalid redeclaration of `%D'", t); ! error ("as `%D'", x); /* We don't try to push this declaration since that causes a crash. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x); --- 722,729 ---- [basic.start.main] This function shall not be overloaded. */ ! cp_error_at ("invalid redeclaration of %qD", t); ! error ("as %qD", x); /* We don't try to push this declaration since that causes a crash. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x); *************** pushdecl (tree x) *** 775,781 **** if (TREE_CODE (x) == TYPE_DECL) { tree type = TREE_TYPE (x); ! if (DECL_SOURCE_LINE (x) == 0) { if (TYPE_NAME (type) == 0) TYPE_NAME (type) = x; --- 766,772 ---- if (TREE_CODE (x) == TYPE_DECL) { tree type = TREE_TYPE (x); ! if (DECL_IS_BUILTIN (x)) { if (TYPE_NAME (type) == 0) TYPE_NAME (type) = x; *************** pushdecl (tree x) *** 788,794 **** || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))) { DECL_ORIGINAL_TYPE (x) = type; ! type = build_type_copy (type); TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); TYPE_NAME (type) = x; TREE_TYPE (x) = type; --- 779,785 ---- || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))) { DECL_ORIGINAL_TYPE (x) = type; ! type = build_variant_type_copy (type); TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); TYPE_NAME (type) = x; TREE_TYPE (x) = type; *************** pushdecl (tree x) *** 820,827 **** && TREE_CODE (decl) == TREE_CODE (x) && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl))) { ! pedwarn ("type mismatch with previous external decl of `%#D'", x); ! cp_pedwarn_at ("previous external decl of `%#D'", decl); } } --- 811,818 ---- && TREE_CODE (decl) == TREE_CODE (x) && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl))) { ! pedwarn ("type mismatch with previous external decl of %q#D", x); ! cp_pedwarn_at ("previous external decl of %q#D", decl); } } *************** pushdecl (tree x) *** 847,870 **** || TREE_CODE (x) == TEMPLATE_DECL)) SET_IDENTIFIER_NAMESPACE_VALUE (name, x); - /* Don't forget if the function was used via an implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_USED (x) = 1; - - /* Don't forget if its address was taken in that way. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_ADDRESSABLE (x) = 1; - - /* Warn about mismatches against previous implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE - /* If this real decl matches the implicit, don't complain. */ - && ! (TREE_CODE (x) == FUNCTION_DECL - && TREE_TYPE (TREE_TYPE (x)) == integer_type_node)) - warning - ("`%D' was previously implicitly declared to return `int'", x); - /* If new decl is `static' and an `extern' was seen previously, warn about it. */ if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t)) --- 838,843 ---- *************** pushdecl (tree x) *** 873,879 **** else { /* Here to install a non-global value. */ ! tree oldlocal = IDENTIFIER_VALUE (name); tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name); if (need_new_binding) --- 846,852 ---- else { /* Here to install a non-global value. */ ! tree oldlocal = innermost_non_namespace_value (name); tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name); if (need_new_binding) *************** pushdecl (tree x) *** 921,928 **** /* OK */; else { ! warning ("extern declaration of `%#D' doesn't match", x); ! cp_warning_at ("global declaration `%#D'", oldglobal); } } /* If we have a local external declaration, --- 894,901 ---- /* OK */; else { ! warning ("extern declaration of %q#D doesn't match", x); ! cp_warning_at ("global declaration %q#D", oldglobal); } } /* If we have a local external declaration, *************** pushdecl (tree x) *** 958,971 **** /* ARM $8.3 */ if (b->kind == sk_function_parms) { ! error ("declaration of '%#D' shadows a parameter", x); err = true; } } if (warn_shadow && !err) { ! warning ("declaration of '%#D' shadows a parameter", x); warning ("%Jshadowed declaration is here", oldlocal); } } --- 931,944 ---- /* ARM $8.3 */ if (b->kind == sk_function_parms) { ! error ("declaration of %q#D shadows a parameter", x); err = true; } } if (warn_shadow && !err) { ! warning ("declaration of %q#D shadows a parameter", x); warning ("%Jshadowed declaration is here", oldlocal); } } *************** pushdecl (tree x) *** 977,1001 **** /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) { ! if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE ! && current_class_ptr ! && !TREE_STATIC (name)) { /* Location of previous decl is not useful in this case. */ ! warning ("declaration of '%D' shadows a member of 'this'", x); } else if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == VAR_DECL) { ! warning ("declaration of '%D' shadows a previous local", x); warning ("%Jshadowed declaration is here", oldlocal); } else if (oldglobal != NULL_TREE && TREE_CODE (oldglobal) == VAR_DECL) /* XXX shadow warnings in outer-more namespaces */ { ! warning ("declaration of '%D' shadows a global declaration", x); warning ("%Jshadowed declaration is here", oldglobal); } --- 950,982 ---- /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) { ! tree member; ! ! if (current_class_ptr) ! member = lookup_member (current_class_type, ! name, ! /*protect=*/0, ! /*want_type=*/false); ! else ! member = NULL_TREE; ! ! if (member && !TREE_STATIC (member)) { /* Location of previous decl is not useful in this case. */ ! warning ("declaration of %qD shadows a member of 'this'", x); } else if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == VAR_DECL) { ! warning ("declaration of %qD shadows a previous local", x); warning ("%Jshadowed declaration is here", oldlocal); } else if (oldglobal != NULL_TREE && TREE_CODE (oldglobal) == VAR_DECL) /* XXX shadow warnings in outer-more namespaces */ { ! warning ("declaration of %qD shadows a global declaration", x); warning ("%Jshadowed declaration is here", oldglobal); } *************** maybe_push_decl (tree decl) *** 1052,1058 **** doesn't really belong to this binding level, that it got here through a using-declaration. */ ! static void push_local_binding (tree id, tree decl, int flags) { struct cp_binding_level *b; --- 1033,1039 ---- doesn't really belong to this binding level, that it got here through a using-declaration. */ ! void push_local_binding (tree id, tree decl, int flags) { struct cp_binding_level *b; *************** push_local_binding (tree id, tree decl, *** 1061,1067 **** push_local_binding with a friend decl of a local class. */ b = innermost_nonclass_level (); ! if (lookup_name_current_level (id)) { /* Supplement the existing binding. */ if (!supplement_binding (IDENTIFIER_BINDING (id), decl)) --- 1042,1048 ---- push_local_binding with a friend decl of a local class. */ b = innermost_nonclass_level (); ! if (lookup_name_innermost_nonclass_level (id)) { /* Supplement the existing binding. */ if (!supplement_binding (IDENTIFIER_BINDING (id), decl)) *************** push_local_binding (tree id, tree decl, *** 1085,1143 **** add_decl_to_level (decl, b); } - /* The old ARM scoping rules injected variables declared in the - initialization statement of a for-statement into the surrounding - scope. We support this usage, in order to be backward-compatible. - DECL is a just-declared VAR_DECL; if necessary inject its - declaration into the surrounding scope. */ - - void - maybe_inject_for_scope_var (tree decl) - { - timevar_push (TV_NAME_LOOKUP); - if (!DECL_NAME (decl)) - { - timevar_pop (TV_NAME_LOOKUP); - return; - } - - /* 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)) - { - timevar_pop (TV_NAME_LOOKUP); - return; - } - - if (current_binding_level->kind == sk_for) - { - struct cp_binding_level *outer - = current_binding_level->level_chain; - - /* Check to see if the same name is already bound at the outer - level, either because it was directly declared, or because a - dead for-decl got preserved. In either case, the code would - not have been valid under the ARM scope rules, so clear - is_for_scope for the current_binding_level. - - Otherwise, we need to preserve the temp slot for decl to last - into the outer binding level. */ - - cxx_binding *outer_binding - = IDENTIFIER_BINDING (DECL_NAME (decl))->previous; - - if (outer_binding && outer_binding->scope == outer - && (TREE_CODE (outer_binding->value) == VAR_DECL) - && DECL_DEAD_FOR_LOCAL (outer_binding->value)) - { - outer_binding->value = DECL_SHADOWED_FOR_VAR (outer_binding->value); - current_binding_level->kind = sk_block; - } - } - timevar_pop (TV_NAME_LOOKUP); - } - /* 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 --- 1066,1071 ---- *************** check_for_out_of_scope_variable (tree de *** 1164,1174 **** { 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; --- 1092,1101 ---- { if (!DECL_ERROR_REPORTED (decl)) { ! warning ("name lookup of %qD changed", DECL_NAME (decl)); ! cp_warning_at (" matches this %qD under ISO standard rules", shadowed); ! cp_warning_at (" matches this %qD under old rules", decl); DECL_ERROR_REPORTED (decl) = 1; } return shadowed; *************** check_for_out_of_scope_variable (tree de *** 1180,1197 **** 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; --- 1107,1129 ---- return decl; DECL_ERROR_REPORTED (decl) = 1; + + if (TREE_TYPE (decl) == error_mark_node) + return decl; + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) { ! error ("name lookup of %qD changed for new ISO % scoping", DECL_NAME (decl)); ! cp_error_at (" cannot use obsolete binding at %qD because " ! "it has a destructor", decl); return error_mark_node; } else { ! pedwarn ("name lookup of %qD changed for new ISO % scoping", DECL_NAME (decl)); ! cp_pedwarn_at (" using obsolete binding at %qD", decl); } return decl; *************** namespace_scope_ht_size (tree ns) *** 1267,1273 **** /* A chain of binding_level structures awaiting reuse. */ ! static GTY((deletable (""))) struct cp_binding_level *free_binding_level; /* Create a new KIND scope and make it the top of the active scopes stack. ENTITY is the scope of the associated C++ entity (namespace, class, --- 1199,1225 ---- /* A chain of binding_level structures awaiting reuse. */ ! static GTY((deletable)) struct cp_binding_level *free_binding_level; ! ! /* Insert SCOPE as the innermost binding level. */ ! ! void ! push_binding_level (struct cp_binding_level *scope) ! { ! /* Add it to the front of currently active scopes stack. */ ! scope->level_chain = current_binding_level; ! current_binding_level = scope; ! keep_next_level_flag = false; ! ! if (ENABLE_SCOPE_CHECKING) ! { ! scope->binding_depth = binding_depth; ! indent (binding_depth); ! cxx_scope_debug (scope, input_line, "push"); ! is_class_level = 0; ! binding_depth++; ! } ! } /* Create a new KIND scope and make it the top of the active scopes stack. ENTITY is the scope of the associated C++ entity (namespace, class, *************** begin_scope (scope_kind kind, tree entit *** 1285,1291 **** free_binding_level = scope->level_chain; } else ! scope = ggc_alloc (sizeof (cxx_scope)); memset (scope, 0, sizeof (cxx_scope)); scope->this_entity = entity; --- 1237,1243 ---- free_binding_level = scope->level_chain; } else ! scope = GGC_NEW (cxx_scope); memset (scope, 0, sizeof (cxx_scope)); scope->this_entity = entity; *************** begin_scope (scope_kind kind, tree entit *** 1311,1317 **** break; case sk_namespace: - scope->type_decls = binding_table_new (namespace_scope_ht_size (entity)); NAMESPACE_LEVEL (entity) = scope; VARRAY_TREE_INIT (scope->static_decls, DECL_NAME (entity) == std_identifier --- 1263,1268 ---- *************** begin_scope (scope_kind kind, tree entit *** 1322,1345 **** default: /* Should not happen. */ ! my_friendly_assert (false, 20030922); break; } scope->kind = kind; ! /* Add it to the front of currently active scopes stack. */ ! scope->level_chain = current_binding_level; ! current_binding_level = scope; ! keep_next_level_flag = false; ! ! if (ENABLE_SCOPE_CHECKING) ! { ! scope->binding_depth = binding_depth; ! indent (binding_depth); ! cxx_scope_debug (scope, input_location.line, "push"); ! is_class_level = 0; ! binding_depth++; ! } return scope; } --- 1273,1284 ---- default: /* Should not happen. */ ! gcc_unreachable (); break; } scope->kind = kind; ! push_binding_level (scope); return scope; } *************** leave_scope (void) *** 1357,1368 **** /* We cannot leave a scope, if there are none left. */ if (NAMESPACE_LEVEL (global_namespace)) ! my_friendly_assert (!global_scope_p (scope), 20030527); if (ENABLE_SCOPE_CHECKING) { indent (--binding_depth); ! cxx_scope_debug (scope, input_location.line, "leave"); if (is_class_level != (scope == class_binding_level)) { indent (binding_depth); --- 1296,1307 ---- /* We cannot leave a scope, if there are none left. */ if (NAMESPACE_LEVEL (global_namespace)) ! gcc_assert (!global_scope_p (scope)); if (ENABLE_SCOPE_CHECKING) { indent (--binding_depth); ! cxx_scope_debug (scope, input_line, "leave"); if (is_class_level != (scope == class_binding_level)) { indent (binding_depth); *************** leave_scope (void) *** 1374,1403 **** /* Move one nesting level up. */ current_binding_level = scope->level_chain; ! /* Namespace-scopes are left most probably temporarily, not completely; ! they can be reopen later, e.g. in namespace-extension or any name ! binding activity that requires us to resume a namespace. For other scopes, we just make the structure available for reuse. */ ! if (scope->kind != sk_namespace) { scope->level_chain = free_binding_level; ! if (scope->kind == sk_class) ! scope->type_decls = NULL; ! else ! binding_table_free (scope->type_decls); ! my_friendly_assert (!ENABLE_SCOPE_CHECKING ! || scope->binding_depth == binding_depth, ! 20030529); free_binding_level = scope; } /* Find the innermost enclosing class scope, and reset CLASS_BINDING_LEVEL appropriately. */ ! for (scope = current_binding_level; ! scope && scope->kind != sk_class; ! scope = scope->level_chain) ! ; ! class_binding_level = scope && scope->kind == sk_class ? scope : NULL; return current_binding_level; } --- 1313,1344 ---- /* Move one nesting level up. */ current_binding_level = scope->level_chain; ! /* Namespace-scopes are left most probably temporarily, not ! completely; they can be reopen later, e.g. in namespace-extension ! or any name binding activity that requires us to resume a ! namespace. For classes, we cache some binding levels. For other scopes, we just make the structure available for reuse. */ ! if (scope->kind != sk_namespace ! && scope->kind != sk_class) { scope->level_chain = free_binding_level; ! gcc_assert (!ENABLE_SCOPE_CHECKING ! || scope->binding_depth == binding_depth); free_binding_level = scope; } /* Find the innermost enclosing class scope, and reset CLASS_BINDING_LEVEL appropriately. */ ! if (scope->kind == sk_class) ! { ! class_binding_level = NULL; ! for (scope = current_binding_level; scope; scope = scope->level_chain) ! if (scope->kind == sk_class) ! { ! class_binding_level = scope; ! break; ! } ! } return current_binding_level; } *************** resume_scope (struct cp_binding_level* b *** 1407,1421 **** { /* Resuming binding levels is meant only for namespaces, and those cannot nest into classes. */ ! my_friendly_assert(!class_binding_level, 386); /* Also, resuming a non-directly nested namespace is a no-no. */ ! my_friendly_assert(b->level_chain == current_binding_level, 386); current_binding_level = b; if (ENABLE_SCOPE_CHECKING) { b->binding_depth = binding_depth; indent (binding_depth); ! cxx_scope_debug (b, input_location.line, "resume"); is_class_level = 0; binding_depth++; } --- 1348,1362 ---- { /* Resuming binding levels is meant only for namespaces, and those cannot nest into classes. */ ! gcc_assert (!class_binding_level); /* Also, resuming a non-directly nested namespace is a no-no. */ ! gcc_assert (b->level_chain == current_binding_level); current_binding_level = b; if (ENABLE_SCOPE_CHECKING) { b->binding_depth = binding_depth; indent (binding_depth); ! cxx_scope_debug (b, input_line, "resume"); is_class_level = 0; binding_depth++; } *************** maybe_push_cleanup_level (tree type) *** 1447,1454 **** && current_binding_level->more_cleanups_ok == 0) { begin_scope (sk_cleanup, NULL); ! clear_last_expr (); ! add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); } } --- 1388,1394 ---- && current_binding_level->more_cleanups_ok == 0) { begin_scope (sk_cleanup, NULL); ! current_binding_level->statement_list = push_stmt_list (); } } *************** kept_level_p (void) *** 1494,1501 **** return (current_binding_level->blocks != NULL_TREE || current_binding_level->keep || current_binding_level->kind == sk_cleanup ! || current_binding_level->names != NULL_TREE ! || current_binding_level->type_decls != NULL); } /* Returns the kind of the innermost scope. */ --- 1434,1440 ---- return (current_binding_level->blocks != NULL_TREE || current_binding_level->keep || current_binding_level->kind == sk_cleanup ! || current_binding_level->names != NULL_TREE); } /* Returns the kind of the innermost scope. */ *************** getdecls (void) *** 1535,1593 **** return current_binding_level->names; } - /* 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 - cxx_remember_type_decls (binding_table table) - { - current_binding_level->type_decls = table; - } - /* 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 - bt_print_entry (binding_entry entry, void *data) - { - int *p = (int *) data; - int len; - - if (entry->name == NULL) - len = 3; - else if (entry->name == TYPE_IDENTIFIER (entry->type)) - len = 2; - else - len = 4; - len = 4; - - *p += len; - - if (*p > 5) - { - fprintf (stderr, "\n\t"); - *p = len; - } - if (entry->name == NULL) - { - print_node_brief (stderr, "type, 0); - fprintf (stderr, ">"); - } - else if (entry->name == TYPE_IDENTIFIER (entry->type)) - print_node_brief (stderr, "", entry->type, 0); - else - { - print_node_brief (stderr, "name, 0); - print_node_brief (stderr, "", entry->type, 0); - fprintf (stderr, ">"); - } - } - - void print_binding_level (struct cp_binding_level* lvl) { tree t; --- 1474,1484 ---- *************** print_binding_level (struct cp_binding_l *** 1608,1614 **** continue; if (no_print_builtins && (TREE_CODE (t) == TYPE_DECL) ! && (!strcmp (DECL_SOURCE_FILE (t),""))) continue; /* Function decls tend to have longer names. */ --- 1499,1505 ---- continue; if (no_print_builtins && (TREE_CODE (t) == TYPE_DECL) ! && DECL_IS_BUILTIN (t)) continue; /* Function decls tend to have longer names. */ *************** print_binding_level (struct cp_binding_l *** 1629,1649 **** if (i) fprintf (stderr, "\n"); } ! if (lvl->type_decls) ! { ! fprintf (stderr, " tags:\t"); ! i = 0; ! binding_table_foreach (lvl->type_decls, bt_print_entry, &i); ! if (i) ! fprintf (stderr, "\n"); ! } ! if (lvl->class_shadowed) { fprintf (stderr, " class-shadowed:"); ! for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t)) ! { ! fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); ! } fprintf (stderr, "\n"); } if (lvl->type_shadowed) --- 1520,1534 ---- if (i) fprintf (stderr, "\n"); } ! if (VEC_length (cp_class_binding, lvl->class_shadowed)) { + size_t i; + cp_class_binding *b; fprintf (stderr, " class-shadowed:"); ! for (i = 0; ! VEC_iterate(cp_class_binding, lvl->class_shadowed, i, b); ! ++i) ! fprintf (stderr, " %s ", IDENTIFIER_POINTER (b->identifier)); fprintf (stderr, "\n"); } if (lvl->type_shadowed) *************** identifier_type_value (tree id) *** 1708,1714 **** 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. */ ! id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN); if (id) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id)); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); --- 1593,1599 ---- 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. */ ! id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); if (id) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id)); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); *************** set_identifier_type_value_with_scope (tr *** 1740,1759 **** b->type_shadowed = tree_cons (id, old_type_value, b->type_shadowed); type = decl ? TREE_TYPE (decl) : NULL_TREE; } else { cxx_binding *binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), id); ! if (decl) ! { ! if (binding->value) ! supplement_binding (binding, decl); ! else ! binding->value = decl; ! } else ! abort (); /* Store marker instead of real type. */ type = global_type_node; } --- 1625,1642 ---- b->type_shadowed = tree_cons (id, old_type_value, b->type_shadowed); type = decl ? TREE_TYPE (decl) : NULL_TREE; + TREE_TYPE (b->type_shadowed) = type; } else { cxx_binding *binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), id); ! gcc_assert (decl); ! if (binding->value) ! supplement_binding (binding, decl); else ! binding->value = decl; ! /* Store marker instead of real type. */ type = global_type_node; } *************** set_identifier_type_value (tree id, tree *** 1773,1787 **** specified class TYPE. When given a template, this routine doesn't lose the specialization. */ ! tree constructor_name_full (tree type) { ! type = TYPE_MAIN_VARIANT (type); ! if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type) ! && TYPE_HAS_CONSTRUCTOR (type)) ! return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type))); ! else ! return TYPE_IDENTIFIER (type); } /* Return the name for the constructor (or destructor) for the --- 1656,1665 ---- specified class TYPE. When given a template, this routine doesn't lose the specialization. */ ! static inline tree constructor_name_full (tree type) { ! return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type)); } /* Return the name for the constructor (or destructor) for the *************** make_anon_name (void) *** 1836,1862 **** return get_identifier (buf); } - /* Clear the TREE_PURPOSE slot of UTDs which have anonymous typenames. - This keeps dbxout from getting confused. */ - - void - clear_anon_tags (void) - { - struct cp_binding_level *b; - static int last_cnt = 0; - - /* Fast out if no new anon names were declared. */ - if (last_cnt == anon_cnt) - return; - - b = current_binding_level; - while (b->kind == sk_cleanup) - b = b->level_chain; - if (b->type_decls != NULL) - binding_table_remove_anonymous_types (b->type_decls); - last_cnt = anon_cnt; - } - /* Return (from the stack of) the BINDING, if any, established at SCOPE. */ static inline cxx_binding * --- 1714,1719 ---- *************** push_using_decl (tree scope, tree name) *** 1919,1926 **** 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; --- 1776,1783 ---- tree decl; timevar_push (TV_NAME_LOOKUP); ! gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL); ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl)) if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name) break; *************** push_overloaded_decl (tree decl, int fla *** 1994,2000 **** if (doing_global) old = namespace_binding (name, DECL_CONTEXT (decl)); else ! old = lookup_name_current_level (name); if (old) { --- 1851,1857 ---- if (doing_global) old = namespace_binding (name, DECL_CONTEXT (decl)); else ! old = lookup_name_innermost_nonclass_level (name); if (old) { *************** push_overloaded_decl (tree decl, int fla *** 2004,2010 **** if (IS_AGGR_TYPE (t) && warn_shadow && (! DECL_IN_SYSTEM_HEADER (decl) || ! DECL_IN_SYSTEM_HEADER (old))) ! warning ("`%#D' hides constructor for `%#T'", decl, t); old = NULL_TREE; } else if (is_overloaded_fn (old)) --- 1861,1867 ---- if (IS_AGGR_TYPE (t) && warn_shadow && (! DECL_IN_SYSTEM_HEADER (decl) || ! DECL_IN_SYSTEM_HEADER (old))) ! warning ("%q#D hides constructor for %q#T", decl, t); old = NULL_TREE; } else if (is_overloaded_fn (old)) *************** push_overloaded_decl (tree decl, int fla *** 2018,2026 **** if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp) && !(flags & PUSH_USING) && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), ! TYPE_ARG_TYPES (TREE_TYPE (decl)))) ! error ("`%#D' conflicts with previous using declaration `%#D'", ! decl, fn); if (duplicate_decls (decl, fn) == fn) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn); --- 1875,1884 ---- if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp) && !(flags & PUSH_USING) && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), ! TYPE_ARG_TYPES (TREE_TYPE (decl))) ! && ! decls_match (fn, decl)) ! error ("%q#D conflicts with previous using declaration %q#D", ! decl, fn); if (duplicate_decls (decl, fn) == fn) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn); *************** push_overloaded_decl (tree decl, int fla *** 2031,2038 **** old = NULL_TREE; else { ! cp_error_at ("previous non-function declaration `%#D'", old); ! error ("conflicts with function declaration `%#D'", decl); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl); } } --- 1889,1896 ---- old = NULL_TREE; else { ! cp_error_at ("previous non-function declaration %q#D", old); ! error ("conflicts with function declaration %q#D", decl); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl); } } *************** push_overloaded_decl (tree decl, int fla *** 2089,2095 **** } /* We should always find a previous binding in this case. */ ! abort (); } /* Install the new binding. */ --- 1947,1953 ---- } /* We should always find a previous binding in this case. */ ! gcc_unreachable (); } /* Install the new binding. */ *************** push_overloaded_decl (tree decl, int fla *** 2105,2121 **** static tree validate_nonmember_using_decl (tree decl, tree scope, tree name) { if (TREE_CODE (decl) == TEMPLATE_ID_EXPR) { /* 7.3.3/5 A using-declaration shall not name a template-id. */ ! error ("a using-declaration cannot specify a template-id. Try `using %D'", name); return NULL_TREE; } if (TREE_CODE (decl) == NAMESPACE_DECL) { ! error ("namespace `%D' not allowed in using-declaration", decl); return NULL_TREE; } --- 1963,1991 ---- static tree validate_nonmember_using_decl (tree decl, tree scope, tree name) { + /* [namespace.udecl] + A using-declaration for a class member shall be a + member-declaration. */ + if (TYPE_P (scope)) + { + error ("%qT is not a namespace", scope); + return NULL_TREE; + } + else if (scope == error_mark_node) + return NULL_TREE; + if (TREE_CODE (decl) == TEMPLATE_ID_EXPR) { /* 7.3.3/5 A using-declaration shall not name a template-id. */ ! error ("a using-declaration cannot specify a template-id. " ! "Try %", name); return NULL_TREE; } if (TREE_CODE (decl) == NAMESPACE_DECL) { ! error ("namespace %qD not allowed in using-declaration", decl); return NULL_TREE; } *************** validate_nonmember_using_decl (tree decl *** 2123,2145 **** { /* It's a nested name with template parameter dependent scope. This can only be using-declaration for class member. */ ! error ("`%T' is not a namespace", TREE_OPERAND (decl, 0)); return NULL_TREE; } if (is_overloaded_fn (decl)) decl = get_first_fn (decl); ! my_friendly_assert (DECL_P (decl), 20020908); ! ! /* [namespace.udecl] ! A using-declaration for a class member shall be a ! member-declaration. */ ! if (TYPE_P (scope)) ! { ! error ("`%T' is not a namespace", scope); ! return NULL_TREE; ! } /* Make a USING_DECL. */ return push_using_decl (scope, name); --- 1993,2006 ---- { /* It's a nested name with template parameter dependent scope. This can only be using-declaration for class member. */ ! error ("%qT is not a namespace", TREE_OPERAND (decl, 0)); return NULL_TREE; } if (is_overloaded_fn (decl)) decl = get_first_fn (decl); ! gcc_assert (DECL_P (decl)); /* Make a USING_DECL. */ return push_using_decl (scope, name); *************** static void *** 2151,2167 **** do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, tree *newval, tree *newtype) { ! cxx_binding decls; *newval = *newtype = NULL_TREE; - cxx_binding_clear (&decls); if (!qualified_lookup_using_namespace (name, scope, &decls, 0)) /* Lookup error */ return; if (!decls.value && !decls.type) { ! error ("`%D' not declared", name); return; } --- 2012,2027 ---- do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, tree *newval, tree *newtype) { ! struct scope_binding decls = EMPTY_SCOPE_BINDING; *newval = *newtype = NULL_TREE; if (!qualified_lookup_using_namespace (name, scope, &decls, 0)) /* Lookup error */ return; if (!decls.value && !decls.type) { ! error ("%qD not declared", name); return; } *************** do_nonmember_using_decl (tree scope, tre *** 2173,2182 **** if (oldval && !is_overloaded_fn (oldval)) { if (!DECL_IMPLICIT_TYPEDEF_P (oldval)) ! error ("`%D' is already declared in this scope", name); oldval = NULL_TREE; } *newval = oldval; for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) { --- 2033,2051 ---- if (oldval && !is_overloaded_fn (oldval)) { if (!DECL_IMPLICIT_TYPEDEF_P (oldval)) ! error ("%qD is already declared in this scope", name); oldval = NULL_TREE; } + /* It is impossible to overload a built-in function; any + explicit declaration eliminates the built-in declaration. + So, if OLDVAL is a built-in, then we can just pretend it + isn't there. */ + if (oldval + && TREE_CODE (oldval) == FUNCTION_DECL + && DECL_ANTICIPATED (oldval)) + oldval = NULL_TREE; + *newval = oldval; for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) { *************** do_nonmember_using_decl (tree scope, tre *** 2200,2226 **** else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) { /* There was already a non-using declaration in this scope with the same parameter types. If both are the same extern "C" functions, that's ok. */ 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. */ } } --- 2069,2086 ---- else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) { + gcc_assert (!DECL_ANTICIPATED (old_fn)); + /* 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)) ! break; ! else ! { ! error ("%qD is already declared in this scope", name); break; } } } *************** do_nonmember_using_decl (tree scope, tre *** 2252,2265 **** { *newval = decls.value; if (oldval && !decls_match (*newval, oldval)) ! error ("`%D' is already declared in this scope", name); } *newtype = decls.type; if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) { ! error ("using declaration `%D' introduced ambiguous type `%T'", ! name, oldtype); return; } } --- 2112,2125 ---- { *newval = decls.value; if (oldval && !decls_match (*newval, oldval)) ! error ("%qD is already declared in this scope", name); } *newtype = decls.type; if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) { ! error ("using declaration %qD introduced ambiguous type %qT", ! name, oldtype); return; } } *************** void *** 2270,2275 **** --- 2130,2136 ---- do_local_using_decl (tree decl, tree scope, tree name) { tree oldval, oldtype, newval, newtype; + tree orig_decl = decl; decl = validate_nonmember_using_decl (decl, scope, name); if (decl == NULL_TREE) *************** do_local_using_decl (tree decl, tree sco *** 2277,2285 **** if (building_stmt_tree () && at_function_scope_p ()) ! add_decl_stmt (decl); ! oldval = lookup_name_current_level (name); oldtype = lookup_type_current_level (name); do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); --- 2138,2146 ---- if (building_stmt_tree () && at_function_scope_p ()) ! add_decl_expr (decl); ! oldval = lookup_name_innermost_nonclass_level (name); oldtype = lookup_type_current_level (name); do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); *************** do_local_using_decl (tree decl, tree sco *** 2311,2497 **** push_local_binding (name, newtype, PUSH_USING); set_identifier_type_value (name, newtype); } - } - - /* 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 - be used in this way. - - For example, when processing the third line of: - - struct A; - typedef struct A A; - struct A; - - lookup of A will find the typedef. Given A's typedef, this function - will return the type associated with "struct A". For the tag to be - anything other than TYPE, TYPE must be a typedef whose original type - has the same name and context as TYPE itself. - - It is not valid for a typedef of an anonymous type to be used with - an explicit tag: - - typedef struct { ... } B; - struct B; - - Return null for this case. */ - - static tree - follow_tag_typedef (tree type) - { - tree original; - - original = original_type (type); - if (! TYPE_NAME (original)) - return NULL_TREE; - if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type) - && (CP_DECL_CONTEXT (TYPE_NAME (original)) - == CP_DECL_CONTEXT (TYPE_NAME (type))) - && !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original))) - return original; - else - return NULL_TREE; - } - - /* Given NAME, an IDENTIFIER_NODE, - return the structure (or union or enum) definition for that name. - Searches binding levels from its SCOPE up to the global level. - If THISLEVEL_ONLY is nonzero, searches only the specified context - (but skips any sk_cleanup contexts to find one that is - meaningful for tags). - FORM says which kind of type the caller wants; - it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. - If the wrong kind of type is found, and it's not a template, an error is - reported. */ - - tree - lookup_tag (enum tree_code form, tree name, - cxx_scope *binding_level, int thislevel_only) - { - 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) - { - tree tail; - if (type_is_anonymous && level->type_decls != NULL) - { - tree type = binding_table_find_anon_type (level->type_decls, name); - /* There is 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->kind == sk_namespace) - /* Do namespace lookup. */ - for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail)) - { - cxx_binding *binding = - cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (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 - && binding && binding->value - && DECL_CLASS_TEMPLATE_P (binding->value)) - old = binding->value; - else if (binding) - old = select_decl (binding, LOOKUP_PREFER_TYPES); - else - old = NULL_TREE; - - if (old) - { - /* We've found something at this binding level. If it is - a typedef, extract the tag it refers to. Lookup fails - if the typedef doesn't refer to a taggable type. */ - old = TREE_TYPE (old); - old = follow_tag_typedef (old); - if (!old) - 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); - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); - } - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old); - } - if (thislevel_only || tail == global_namespace) - 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->kind != sk_cleanup) - { - if (level->kind == sk_template_parms && allow_template_parms_p) - { - /* We must deal with cases like this: - - template struct S; - template struct S {}; - - When looking up `S', for the second declaration, we - would like to find the first declaration. But, we - are in the pseudo-global level created for the - template parameters, rather than the (surrounding) - namespace level. Thus, we keep going one more level, - even though THISLEVEL_ONLY is nonzero. */ - allow_template_parms_p = 0; - continue; - } - else - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); - } - } - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); - } - - /* Given a type, find the tag that was defined for it and return the tag name. - Otherwise return 0. However, the value can never be 0 - in the cases in which this is used. - - C++: If NAME is nonzero, this is the new name to install. This is - done when replacing anonymous tags with real tag names. */ - - tree - lookup_tag_reverse (tree type, tree name) - { - struct cp_binding_level *level; ! timevar_push (TV_NAME_LOOKUP); ! for (level = current_binding_level; level; level = level->level_chain) ! { ! 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); ! } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); } /* Returns true if ROOT (a namespace, class, or function) encloses --- 2172,2181 ---- push_local_binding (name, newtype, PUSH_USING); set_identifier_type_value (name, newtype); } ! /* Emit debug info. */ ! if (!processing_template_decl) ! cp_emit_debug_info_for_using (orig_decl, current_scope()); } /* Returns true if ROOT (a namespace, class, or function) encloses *************** lookup_tag_reverse (tree type, tree name *** 2500,2511 **** bool is_ancestor (tree root, tree child) { ! 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 ! || CLASS_TYPE_P (child)), ! 20030307); /* The global namespace encloses everything. */ if (root == global_namespace) --- 2184,2194 ---- bool is_ancestor (tree root, tree child) { ! gcc_assert ((TREE_CODE (root) == NAMESPACE_DECL ! || TREE_CODE (root) == FUNCTION_DECL ! || CLASS_TYPE_P (root))); ! gcc_assert ((TREE_CODE (child) == NAMESPACE_DECL ! || CLASS_TYPE_P (child))); /* The global namespace encloses everything. */ if (root == global_namespace) *************** is_ancestor (tree root, tree child) *** 2526,2539 **** } } ! /* Enter the class or namespace scope indicated by T. Returns TRUE iff ! pop_scope should be called later to exit this scope. */ ! bool push_scope (tree t) { - bool pop = true; - if (TREE_CODE (t) == NAMESPACE_DECL) push_decl_namespace (t); else if (CLASS_TYPE_P (t)) --- 2209,2222 ---- } } ! /* Enter the class or namespace scope indicated by T suitable for name ! lookup. T can be arbitrary scope, not necessary nested inside the ! current scope. Returns a non-null scope to pop iff pop_scope ! should be called later to exit this scope. */ ! tree push_scope (tree t) { if (TREE_CODE (t) == NAMESPACE_DECL) push_decl_namespace (t); else if (CLASS_TYPE_P (t)) *************** push_scope (tree t) *** 2546,2555 **** need to re-enter the scope. Since we are not actually pushing a new scope, our caller should not call pop_scope. */ ! pop = false; } ! return pop; } /* Leave scope pushed by push_scope. */ --- 2229,2238 ---- need to re-enter the scope. Since we are not actually pushing a new scope, our caller should not call pop_scope. */ ! t = NULL_TREE; } ! return t; } /* Leave scope pushed by push_scope. */ *************** pop_scope (tree t) *** 2562,2567 **** --- 2245,2354 ---- else if CLASS_TYPE_P (t) pop_nested_class (); } + + /* Subroutine of push_inner_scope. */ + + static void + push_inner_scope_r (tree outer, tree inner) + { + tree prev; + + if (outer == inner + || (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner))) + return; + + prev = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner)); + if (outer != prev) + push_inner_scope_r (outer, prev); + if (TREE_CODE (inner) == NAMESPACE_DECL) + { + struct cp_binding_level *save_template_parm = 0; + /* Temporary take out template parameter scopes. They are saved + in reversed order in save_template_parm. */ + while (current_binding_level->kind == sk_template_parms) + { + struct cp_binding_level *b = current_binding_level; + current_binding_level = b->level_chain; + b->level_chain = save_template_parm; + save_template_parm = b; + } + + resume_scope (NAMESPACE_LEVEL (inner)); + current_namespace = inner; + + /* Restore template parameter scopes. */ + while (save_template_parm) + { + struct cp_binding_level *b = save_template_parm; + save_template_parm = b->level_chain; + b->level_chain = current_binding_level; + current_binding_level = b; + } + } + else + pushclass (inner); + } + + /* Enter the scope INNER from current scope. INNER must be a scope + nested inside current scope. This works with both name lookup and + pushing name into scope. In case a template parameter scope is present, + namespace is pushed under the template parameter scope according to + name lookup rule in 14.6.1/6. + + Return the former current scope suitable for pop_inner_scope. */ + + tree + push_inner_scope (tree inner) + { + tree outer = current_scope (); + if (!outer) + outer = current_namespace; + + push_inner_scope_r (outer, inner); + return outer; + } + + /* Exit the current scope INNER back to scope OUTER. */ + + void + pop_inner_scope (tree outer, tree inner) + { + if (outer == inner + || (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner))) + return; + + while (outer != inner) + { + if (TREE_CODE (inner) == NAMESPACE_DECL) + { + struct cp_binding_level *save_template_parm = 0; + /* Temporary take out template parameter scopes. They are saved + in reversed order in save_template_parm. */ + while (current_binding_level->kind == sk_template_parms) + { + struct cp_binding_level *b = current_binding_level; + current_binding_level = b->level_chain; + b->level_chain = save_template_parm; + save_template_parm = b; + } + + pop_namespace (); + + /* Restore template parameter scopes. */ + while (save_template_parm) + { + struct cp_binding_level *b = save_template_parm; + save_template_parm = b->level_chain; + b->level_chain = current_binding_level; + current_binding_level = b; + } + } + else + popclass (); + + inner = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner)); + } + } /* Do a pushlevel for class declarations. */ *************** void *** 2580,2644 **** poplevel_class (void) { 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 ! of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot ! shouldn't even be used when current_class_type isn't set, and second, ! if we don't touch it here, we're able to use the cache effect if the ! next time we're entering a class scope, it is the same class. */ ! if (current_class_depth != 1) ! { ! struct cp_binding_level* b; ! ! /* Clear out our IDENTIFIER_CLASS_VALUEs. */ ! for (shadowed = level->class_shadowed; ! shadowed; ! shadowed = TREE_CHAIN (shadowed)) ! IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE; ! ! /* Find the next enclosing class, and recreate ! IDENTIFIER_CLASS_VALUEs appropriate for that class. */ ! b = level->level_chain; ! while (b && b->kind != sk_class) ! b = b->level_chain; ! ! if (b) ! for (shadowed = b->class_shadowed; ! shadowed; ! shadowed = TREE_CHAIN (shadowed)) ! { ! cxx_binding *binding; ! ! binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed)); ! while (binding && binding->scope != b) ! binding = binding->previous; ! if (binding) ! IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) ! = binding->value; ! } ! } ! else ! /* Remember to save what IDENTIFIER's were bound in this scope so we ! can recover from cache misses. */ ! { ! previous_class_type = current_class_type; ! previous_class_values = class_binding_level->class_shadowed; ! } for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed)); /* Remove the bindings for all of the class-level declarations. */ ! for (shadowed = level->class_shadowed; ! shadowed; ! shadowed = TREE_CHAIN (shadowed)) ! pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed)); /* Now, pop out of the binding level which we created up in the `pushlevel_class' routine. */ --- 2367,2397 ---- poplevel_class (void) { struct cp_binding_level *level = class_binding_level; + cp_class_binding *cb; + size_t i; tree shadowed; timevar_push (TV_NAME_LOOKUP); ! gcc_assert (level != 0); ! /* If we're leaving a toplevel class, cache its binding level. */ ! if (current_class_depth == 1) ! previous_class_level = level; for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed)); /* Remove the bindings for all of the class-level declarations. */ ! if (level->class_shadowed) ! { ! for (i = 0; ! VEC_iterate (cp_class_binding, level->class_shadowed, i, cb); ! ++i) ! IDENTIFIER_BINDING (cb->identifier) = cb->base.previous; ! ggc_free (level->class_shadowed); ! level->class_shadowed = NULL; ! } /* Now, pop out of the binding level which we created up in the `pushlevel_class' routine. */ *************** poplevel_class (void) *** 2649,2725 **** timevar_pop (TV_NAME_LOOKUP); } ! /* Bind DECL to ID in the class_binding_level. Returns nonzero if the ! binding was successful. */ ! int ! push_class_binding (tree id, tree decl) { - int result = 1; - 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 is an invalid redeclaration of a name already used for some - other purpose. */ - note_name_declared_in_class (id, decl); - - if (binding && binding->scope == class_binding_level) - /* Supplement the existing binding. */ - result = supplement_binding (IDENTIFIER_BINDING (id), decl); - else - /* Create a new binding. */ - push_binding (id, decl, class_binding_level); - - /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the - class-level declaration. Note that we do not use DECL here - because of the possibility of the `struct stat' hack; if DECL is - a class-name or enum-name we might prefer a field-name, or some - such. */ - IDENTIFIER_CLASS_VALUE (id) = IDENTIFIER_BINDING (id)->value; - - /* If this is a binding from a base class, mark it as such. */ - binding = IDENTIFIER_BINDING (id); if (binding->value == decl && TREE_CODE (decl) != TREE_LIST) { if (TREE_CODE (decl) == OVERLOAD) context = CP_DECL_CONTEXT (OVL_CURRENT (decl)); else { ! my_friendly_assert (DECL_P (decl), 0); context = context_for_name_lookup (decl); } ! if (is_properly_derived_from (current_class_type, context)) INHERITED_VALUE_BINDING_P (binding) = 1; else INHERITED_VALUE_BINDING_P (binding) = 0; } else if (binding->value == decl) ! /* We only encounter a TREE_LIST when push_class_decls detects an ! ambiguity. Such an ambiguity can be overridden by a definition ! in this class. */ INHERITED_VALUE_BINDING_P (binding) = 1; ! ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result); ! } ! ! /* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE ! for any names in enclosing classes. */ ! ! void ! clear_identifier_class_values (void) ! { ! tree t; ! ! if (!class_binding_level) ! return; ! ! for (t = class_binding_level->class_shadowed; ! t; ! t = TREE_CHAIN (t)) ! IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE; } /* Make the declaration of X appear in CLASS scope. */ --- 2402,2439 ---- timevar_pop (TV_NAME_LOOKUP); } ! /* Set INHERITED_VALUE_BINDING_P on BINDING to true or false, as ! appropriate. DECL is the value to which a name has just been ! bound. CLASS_TYPE is the class in which the lookup occurred. */ ! static void ! set_inherited_value_binding_p (cxx_binding *binding, tree decl, ! tree class_type) { if (binding->value == decl && TREE_CODE (decl) != TREE_LIST) { + tree context; + if (TREE_CODE (decl) == OVERLOAD) context = CP_DECL_CONTEXT (OVL_CURRENT (decl)); else { ! gcc_assert (DECL_P (decl)); context = context_for_name_lookup (decl); } ! if (is_properly_derived_from (class_type, context)) INHERITED_VALUE_BINDING_P (binding) = 1; else INHERITED_VALUE_BINDING_P (binding) = 0; } else if (binding->value == decl) ! /* We only encounter a TREE_LIST when there is an ambiguity in the ! base classes. Such an ambiguity can be overridden by a ! definition in this class. */ INHERITED_VALUE_BINDING_P (binding) = 1; ! else ! INHERITED_VALUE_BINDING_P (binding) = 0; } /* Make the declaration of X appear in CLASS scope. */ *************** pushdecl_class_level (tree x) *** 2759,2769 **** input_location = save_location; } } ! timevar_pop (TV_NAME_LOOKUP); ! ! return is_valid; } /* Make the declaration(s) of X appear in CLASS scope under the name NAME. Returns true if the binding is valid. */ --- 2473,2542 ---- input_location = save_location; } } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, is_valid); } + /* Return the BINDING (if any) for NAME in SCOPE, which is a class + scope. If the value returned is non-NULL, and the PREVIOUS field + is not set, callers must set the PREVIOUS field explicitly. */ + + static cxx_binding * + get_class_binding (tree name, cxx_scope *scope) + { + tree class_type; + tree type_binding; + tree value_binding; + cxx_binding *binding; + + class_type = scope->this_entity; + + /* Get the type binding. */ + type_binding = lookup_member (class_type, name, + /*protect=*/2, /*want_type=*/true); + /* Get the value binding. */ + value_binding = lookup_member (class_type, name, + /*protect=*/2, /*want_type=*/false); + + if (value_binding + && (TREE_CODE (value_binding) == TYPE_DECL + || DECL_CLASS_TEMPLATE_P (value_binding) + || (TREE_CODE (value_binding) == TREE_LIST + && TREE_TYPE (value_binding) == error_mark_node + && (TREE_CODE (TREE_VALUE (value_binding)) + == TYPE_DECL)))) + /* We found a type binding, even when looking for a non-type + binding. This means that we already processed this binding + above. */ + ; + else if (value_binding) + { + if (TREE_CODE (value_binding) == TREE_LIST + && TREE_TYPE (value_binding) == error_mark_node) + /* NAME is ambiguous. */ + ; + else if (BASELINK_P (value_binding)) + /* NAME is some overloaded functions. */ + value_binding = BASELINK_FUNCTIONS (value_binding); + } + + /* If we found either a type binding or a value binding, create a + new binding object. */ + if (type_binding || value_binding) + { + binding = new_class_binding (name, + value_binding, + type_binding, + scope); + /* This is a class-scope binding, not a block-scope binding. */ + LOCAL_BINDING_P (binding) = 0; + set_inherited_value_binding_p (binding, value_binding, class_type); + } + else + binding = NULL; + + return binding; + } + /* Make the declaration(s) of X appear in CLASS scope under the name NAME. Returns true if the binding is valid. */ *************** bool *** 2771,2776 **** --- 2544,2551 ---- push_class_level_binding (tree name, tree x) { cxx_binding *binding; + tree decl = x; + bool ok; timevar_push (TV_NAME_LOOKUP); /* The class_binding_level will be NULL if x is a template *************** push_class_level_binding (tree name, tre *** 2778,2787 **** if (!class_binding_level) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); ! /* Make sure that this new member does not have the same name ! as a template parameter. */ ! if (TYPE_BEING_DEFINED (current_class_type)) ! check_template_shadow (x); /* [class.mem] --- 2553,2568 ---- if (!class_binding_level) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); ! /* Check for invalid member names. */ ! gcc_assert (TYPE_BEING_DEFINED (current_class_type)); ! /* We could have been passed a tree list if this is an ambiguous ! declaration. If so, pull the declaration out because ! check_template_shadow will not handle a TREE_LIST. */ ! if (TREE_CODE (decl) == TREE_LIST ! && TREE_TYPE (decl) == error_mark_node) ! decl = TREE_VALUE (decl); ! ! check_template_shadow (decl); /* [class.mem] *************** push_class_level_binding (tree name, tre *** 2812,2827 **** tree scope = context_for_name_lookup (x); if (TYPE_P (scope) && same_type_p (scope, current_class_type)) { ! error ("`%D' has the same name as the class in which it is declared", x); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false); } } ! /* If this declaration shadows a declaration from an enclosing ! class, then we will need to restore IDENTIFIER_CLASS_VALUE when ! we leave this class. Record the shadowed declaration here. */ binding = IDENTIFIER_BINDING (name); if (binding && binding->value) { tree bval = binding->value; --- 2593,2621 ---- tree scope = context_for_name_lookup (x); if (TYPE_P (scope) && same_type_p (scope, current_class_type)) { ! error ("%qD has the same name as the class in which it is " ! "declared", x); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false); } } ! /* Get the current binding for NAME in this class, if any. */ binding = IDENTIFIER_BINDING (name); + if (!binding || binding->scope != class_binding_level) + { + binding = get_class_binding (name, class_binding_level); + /* If a new binding was created, put it at the front of the + IDENTIFIER_BINDING list. */ + if (binding) + { + binding->previous = IDENTIFIER_BINDING (name); + IDENTIFIER_BINDING (name) = binding; + } + } + + /* If there is already a binding, then we may need to update the + current value. */ if (binding && binding->value) { tree bval = binding->value; *************** push_class_level_binding (tree name, tre *** 2852,2939 **** old_decl = bval; else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); ! ! if (old_decl) { ! tree shadow; ! ! /* Find the previous binding of name on the class-shadowed ! list, and update it. */ ! for (shadow = class_binding_level->class_shadowed; ! shadow; ! shadow = TREE_CHAIN (shadow)) ! if (TREE_PURPOSE (shadow) == name ! && TREE_TYPE (shadow) == old_decl) ! { ! binding->value = x; ! INHERITED_VALUE_BINDING_P (binding) = 0; ! TREE_TYPE (shadow) = x; ! IDENTIFIER_CLASS_VALUE (name) = x; ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); ! } } } /* If we didn't replace an existing binding, put the binding on the ! stack of bindings for the identifier, and update the shadowed list. */ ! if (push_class_binding (name, x)) { ! class_binding_level->class_shadowed ! = tree_cons (name, NULL, ! class_binding_level->class_shadowed); ! /* 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); } tree ! do_class_using_decl (tree decl) { ! tree name, value, scope, type; ! if (TREE_CODE (decl) != SCOPE_REF ! || !TREE_OPERAND (decl, 0) ! || !TYPE_P (TREE_OPERAND (decl, 0))) { error ("using-declaration for non-member at class scope"); return NULL_TREE; } - scope = TREE_OPERAND (decl, 0); - name = TREE_OPERAND (decl, 1); if (TREE_CODE (name) == BIT_NOT_EXPR) { error ("using-declaration cannot name destructor"); return NULL_TREE; } - if (TREE_CODE (name) == TYPE_DECL) - name = DECL_NAME (name); - else if (TREE_CODE (name) == TEMPLATE_DECL) - name = DECL_NAME (name); - else if (BASELINK_P (name)) - { - tree fns = BASELINK_FUNCTIONS (name); - name = DECL_NAME (get_first_fn (fns)); - } ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716); /* Dependent using decls have a NULL type, non-dependent ones have a void type. */ type = dependent_type_p (scope) ? NULL_TREE : void_type_node; value = build_lang_decl (USING_DECL, name, type); DECL_INITIAL (value) = scope; return value; } - void - set_class_shadows (tree shadows) - { - class_binding_level->class_shadowed = shadows; - } /* Return the binding value for name in scope. */ --- 2646,2722 ---- old_decl = bval; else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); ! ! if (old_decl && binding->scope == class_binding_level) { ! binding->value = x; ! /* It is always safe to clear INHERITED_VALUE_BINDING_P ! here. This function is only used to register bindings ! from with the class definition itself. */ ! INHERITED_VALUE_BINDING_P (binding) = 0; ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); } } + /* Note that we declared this value so that we can issue an error if + this is an invalid redeclaration of a name already used for some + other purpose. */ + note_name_declared_in_class (name, decl); + /* If we didn't replace an existing binding, put the binding on the ! stack of bindings for the identifier, and update the shadowed ! list. */ ! if (binding && binding->scope == class_binding_level) ! /* Supplement the existing binding. */ ! ok = supplement_binding (binding, decl); ! else { ! /* Create a new binding. */ ! push_binding (name, decl, class_binding_level); ! ok = true; } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok); } + /* Process "using SCOPE::NAME" in a class scope. Return the + USING_DECL created. */ + tree ! do_class_using_decl (tree scope, tree name) { ! tree value, type; ! if (!scope || !TYPE_P (scope)) { error ("using-declaration for non-member at class scope"); return NULL_TREE; } if (TREE_CODE (name) == BIT_NOT_EXPR) { error ("using-declaration cannot name destructor"); return NULL_TREE; } ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); /* Dependent using decls have a NULL type, non-dependent ones have a void type. */ type = dependent_type_p (scope) ? NULL_TREE : void_type_node; value = build_lang_decl (USING_DECL, name, type); DECL_INITIAL (value) = scope; + + if (scope && !processing_template_decl) + { + tree r; + + r = lookup_qualified_name (scope, name, false, false); + if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD)) + cp_emit_debug_info_for_using (r, scope); + } return value; } /* Return the binding value for name in scope. */ *************** namespace_binding (tree name, tree scope *** 2944,2950 **** if (scope == NULL) scope = global_namespace; ! scope = ORIGINAL_NAMESPACE (scope); binding = cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); return binding ? binding->value : NULL_TREE; --- 2727,2736 ---- if (scope == NULL) scope = global_namespace; ! else ! /* Unnecessary for the global namespace because it can't be an alias. */ ! scope = ORIGINAL_NAMESPACE (scope); ! binding = cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); return binding ? binding->value : NULL_TREE; *************** set_decl_namespace (tree decl, tree scop *** 2981,3033 **** /* It is ok for friends to be qualified in parallel space. */ 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. */ ! old = namespace_binding (DECL_NAME (decl), scope); ! if (!old) ! /* No old declaration at all. */ ! goto complain; ! /* A template can be explicitly specialized in any namespace. */ ! if (processing_explicit_instantiation) ! return; ! if (!is_overloaded_fn (decl)) ! /* Don't compare non-function decls with decls_match here, ! since it can't check for the correct constness at this ! point. pushdecl will find those errors later. */ ! return; ! /* Since decl is a function, old should contain a function decl. */ ! if (!is_overloaded_fn (old)) ! goto complain; ! if (processing_template_decl || processing_specialization) ! /* We have not yet called push_template_decl to turn a ! FUNCTION_DECL into a TEMPLATE_DECL, so the declarations ! won't match. But, we'll check later, when we construct the ! template. */ ! return; ! if (is_overloaded_fn (old)) ! { ! for (; old; old = OVL_NEXT (old)) ! if (decls_match (decl, OVL_CURRENT (old))) ! return; ! } ! else ! if (decls_match (decl, old)) ! return; } ! else return; complain: ! error ("`%D' should have been declared inside `%D'", ! decl, scope); } /* Return the namespace where the current declaration is declared. */ ! tree current_decl_namespace (void) { tree result; --- 2767,2822 ---- /* It is ok for friends to be qualified in parallel space. */ if (!friendp && !is_ancestor (current_namespace, scope)) ! error ("declaration of %qD not in a namespace surrounding %qD", ! decl, scope); DECL_CONTEXT (decl) = FROB_CONTEXT (scope); ! ! /* Writing "int N::i" to declare a variable within "N" is invalid. */ ! if (scope == current_namespace) { ! if (at_namespace_scope_p ()) ! error ("explicit qualification in declaration of `%D'", ! decl); ! return; } ! ! /* See whether this has been declared in the namespace. */ ! old = namespace_binding (DECL_NAME (decl), scope); ! if (!old) ! /* No old declaration at all. */ ! goto complain; ! /* A template can be explicitly specialized in any namespace. */ ! if (processing_explicit_instantiation) return; + if (!is_overloaded_fn (decl)) + /* Don't compare non-function decls with decls_match here, since + it can't check for the correct constness at this + point. pushdecl will find those errors later. */ + return; + /* Since decl is a function, old should contain a function decl. */ + if (!is_overloaded_fn (old)) + goto complain; + if (processing_template_decl || processing_specialization) + /* We have not yet called push_template_decl to turn a + FUNCTION_DECL into a TEMPLATE_DECL, so the declarations won't + match. But, we'll check later, when we construct the + template. */ + return; + if (is_overloaded_fn (old)) + { + for (; old; old = OVL_NEXT (old)) + if (decls_match (decl, OVL_CURRENT (old))) + return; + } + else if (decls_match (decl, old)) + return; complain: ! error ("%qD should have been declared inside %qD", decl, scope); } /* Return the namespace where the current declaration is declared. */ ! static tree current_decl_namespace (void) { tree result; *************** push_namespace (tree name) *** 3060,3067 **** /* We should not get here if the global_namespace is not yet constructed nor if NAME designates the global namespace: The global scope is constructed elsewhere. */ ! my_friendly_assert (global_namespace != NULL && name != global_scope_name, ! 20030531); if (anon) { --- 2849,2855 ---- /* We should not get here if the global_namespace is not yet constructed nor if NAME designates the global namespace: The global scope is constructed elsewhere. */ ! gcc_assert (global_namespace != NULL && name != global_scope_name); if (anon) { *************** push_namespace (tree name) *** 3085,3092 **** need_new = 0; if (DECL_NAMESPACE_ALIAS (d)) { ! error ("namespace alias `%D' not allowed here, assuming `%D'", ! d, DECL_NAMESPACE_ALIAS (d)); d = DECL_NAMESPACE_ALIAS (d); } } --- 2873,2880 ---- need_new = 0; if (DECL_NAMESPACE_ALIAS (d)) { ! error ("namespace alias %qD not allowed here, assuming %qD", ! d, DECL_NAMESPACE_ALIAS (d)); d = DECL_NAMESPACE_ALIAS (d); } } *************** push_namespace (tree name) *** 3097,3103 **** /* Make a new namespace, binding the name to it. */ d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace); ! d = pushdecl (d); if (anon) { /* Clear DECL_NAME for the benefit of debugging back ends. */ --- 2885,2891 ---- /* Make a new namespace, binding the name to it. */ d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace); ! pushdecl (d); if (anon) { /* Clear DECL_NAME for the benefit of debugging back ends. */ *************** push_namespace (tree name) *** 3122,3128 **** void pop_namespace (void) { ! my_friendly_assert (current_namespace != global_namespace, 20010801); current_namespace = CP_DECL_CONTEXT (current_namespace); /* The binding level is not popped, as it might be re-opened later. */ leave_scope (); --- 2910,2916 ---- void pop_namespace (void) { ! gcc_assert (current_namespace != global_namespace); current_namespace = CP_DECL_CONTEXT (current_namespace); /* The binding level is not popped, as it might be re-opened later. */ leave_scope (); *************** do_namespace_alias (tree alias, tree nam *** 3200,3206 **** if (TREE_CODE (namespace) != NAMESPACE_DECL) { /* The parser did not find it, so it's not there. */ ! error ("unknown namespace `%D'", namespace); return; } --- 2988,2994 ---- if (TREE_CODE (namespace) != NAMESPACE_DECL) { /* The parser did not find it, so it's not there. */ ! error ("unknown namespace %qD", namespace); return; } *************** do_namespace_alias (tree alias, tree nam *** 3210,3219 **** alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); DECL_NAMESPACE_ALIAS (alias) = namespace; DECL_EXTERNAL (alias) = 1; ! DECL_CONTEXT (alias) = current_scope (); ! if (!DECL_CONTEXT (alias)) ! DECL_CONTEXT (alias) = FROB_CONTEXT (current_namespace); pushdecl (alias); } /* Like pushdecl, only it places X in the current namespace, --- 2998,3008 ---- alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); DECL_NAMESPACE_ALIAS (alias) = namespace; DECL_EXTERNAL (alias) = 1; ! DECL_CONTEXT (alias) = FROB_CONTEXT (current_scope ()); pushdecl (alias); + + /* Emit debug info for namespace alias. */ + (*debug_hooks->global_decl) (alias); } /* Like pushdecl, only it places X in the current namespace, *************** pushdecl_namespace_level (tree x) *** 3230,3238 **** /* Now, the type_shadowed stack may screw us. Munge it so it does what we want. */ ! if (TREE_CODE (x) == TYPE_DECL) { ! tree name = DECL_NAME (x); tree newval; tree *ptr = (tree *)0; for (; !global_scope_p (b); b = b->level_chain) --- 3019,3027 ---- /* Now, the type_shadowed stack may screw us. Munge it so it does what we want. */ ! if (TREE_CODE (t) == TYPE_DECL) { ! tree name = DECL_NAME (t); tree newval; tree *ptr = (tree *)0; for (; !global_scope_p (b); b = b->level_chain) *************** pushdecl_namespace_level (tree x) *** 3247,3258 **** PT names. It's gross, but I haven't time to fix it. */ } } ! newval = TREE_TYPE (x); if (ptr == (tree *)0) { /* @@ This shouldn't be needed. My test case "zstring.cc" trips up here if this is changed to an assertion. --KR */ ! SET_IDENTIFIER_TYPE_VALUE (name, x); } else { --- 3036,3047 ---- PT names. It's gross, but I haven't time to fix it. */ } } ! newval = TREE_TYPE (t); if (ptr == (tree *)0) { /* @@ This shouldn't be needed. My test case "zstring.cc" trips up here if this is changed to an assertion. --KR */ ! SET_IDENTIFIER_TYPE_VALUE (name, t); } else { *************** add_using_namespace (tree user, tree use *** 3276,3283 **** timevar_pop (TV_NAME_LOOKUP); return; } ! my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380); ! my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380); /* Check if we already have this. */ t = purpose_member (used, DECL_NAMESPACE_USING (user)); if (t != NULL_TREE) --- 3065,3072 ---- timevar_pop (TV_NAME_LOOKUP); return; } ! gcc_assert (TREE_CODE (user) == NAMESPACE_DECL); ! gcc_assert (TREE_CODE (used) == NAMESPACE_DECL); /* Check if we already have this. */ t = purpose_member (used, DECL_NAMESPACE_USING (user)); if (t != NULL_TREE) *************** void *** 3317,3322 **** --- 3106,3112 ---- do_toplevel_using_decl (tree decl, tree scope, tree name) { tree oldval, oldtype, newval, newtype; + tree orig_decl = decl; cxx_binding *binding; decl = validate_nonmember_using_decl (decl, scope, name); *************** do_toplevel_using_decl (tree decl, tree *** 3330,3335 **** --- 3120,3129 ---- do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + /* Emit debug info. */ + if (!processing_template_decl) + cp_emit_debug_info_for_using (orig_decl, current_namespace); + /* Copy declarations found. */ if (newval) binding->value = newval; *************** do_toplevel_using_decl (tree decl, tree *** 3343,3348 **** --- 3137,3144 ---- void do_using_directive (tree namespace) { + tree context = NULL_TREE; + if (building_stmt_tree ()) add_stmt (build_stmt (USING_STMT, namespace)); *************** do_using_directive (tree namespace) *** 3353,3373 **** { /* Lookup in lexer did not find a namespace. */ if (!processing_template_decl) ! error ("namespace `%T' undeclared", namespace); return; } if (TREE_CODE (namespace) != NAMESPACE_DECL) { if (!processing_template_decl) ! error ("`%T' is not a namespace", namespace); return; } namespace = ORIGINAL_NAMESPACE (namespace); if (!toplevel_bindings_p ()) ! push_using_directive (namespace); else ! /* direct usage */ ! add_using_namespace (current_namespace, namespace, 0); } /* Deal with a using-directive seen by the parser. Currently we only --- 3149,3180 ---- { /* Lookup in lexer did not find a namespace. */ if (!processing_template_decl) ! error ("namespace %qT undeclared", namespace); return; } if (TREE_CODE (namespace) != NAMESPACE_DECL) { if (!processing_template_decl) ! error ("%qT is not a namespace", namespace); return; } namespace = ORIGINAL_NAMESPACE (namespace); if (!toplevel_bindings_p ()) ! { ! push_using_directive (namespace); ! context = current_scope (); ! } else ! { ! /* direct usage */ ! add_using_namespace (current_namespace, namespace, 0); ! if (current_namespace != global_namespace) ! context = current_namespace; ! } ! ! /* Emit debugging info. */ ! if (!processing_template_decl) ! (*debug_hooks->imported_module_or_decl) (namespace, context); } /* Deal with a using-directive seen by the parser. Currently we only *************** parse_using_directive (tree namespace, t *** 3393,3399 **** DECL_NAMESPACE_ASSOCIATIONS (namespace)); } else ! warning ("`%D' attribute directive ignored", name); } } --- 3200,3206 ---- DECL_NAMESPACE_ASSOCIATIONS (namespace)); } else ! warning ("%qD attribute directive ignored", name); } } *************** merge_functions (tree s1, tree s2) *** 3475,3485 **** XXX In what way should I treat extern declarations? XXX I don't want to repeat the entire duplicate_decls here */ ! static cxx_binding * ! ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags) { tree val, type; ! my_friendly_assert (old != NULL, 393); /* Copy the value. */ val = new->value; if (val) --- 3282,3293 ---- XXX In what way should I treat extern declarations? XXX I don't want to repeat the entire duplicate_decls here */ ! static void ! ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new, ! int flags) { tree val, type; ! gcc_assert (old != NULL); /* Copy the value. */ val = new->value; if (val) *************** ambiguous_decl (tree name, cxx_binding * *** 3526,3536 **** repeat ourselves. */ if (old->value != error_mark_node) { ! error ("use of `%D' is ambiguous", name); ! cp_error_at (" first declared as `%#D' here", ! old->value); } ! cp_error_at (" also declared as `%#D' here", val); } old->value = error_mark_node; } --- 3334,3343 ---- repeat ourselves. */ if (old->value != error_mark_node) { ! error ("use of %qD is ambiguous", name); ! cp_error_at (" first declared as %q#D here", old->value); } ! cp_error_at (" also declared as %q#D here", val); } old->value = error_mark_node; } *************** ambiguous_decl (tree name, cxx_binding * *** 3545,3556 **** { if (flags & LOOKUP_COMPLAIN) { ! error ("`%D' denotes an ambiguous type",name); error ("%J first type here", TYPE_MAIN_DECL (old->type)); error ("%J other type here", TYPE_MAIN_DECL (type)); } } - return old; } /* Return the declarations that are members of the namespace NS. */ --- 3352,3362 ---- { if (flags & LOOKUP_COMPLAIN) { ! error ("%qD denotes an ambiguous type",name); error ("%J first type here", TYPE_MAIN_DECL (old->type)); error ("%J other type here", TYPE_MAIN_DECL (type)); } } } /* Return the declarations that are members of the namespace NS. */ *************** lookup_namespace_name (tree namespace, t *** 3600,3609 **** { 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 when B is a namespace. */ --- 3406,3415 ---- { tree val; tree template_id = NULL_TREE; ! struct scope_binding binding = EMPTY_SCOPE_BINDING; timevar_push (TV_NAME_LOOKUP); ! gcc_assert (TREE_CODE (namespace) == NAMESPACE_DECL); if (TREE_CODE (name) == NAMESPACE_DECL) /* This happens for A::B when B is a namespace. */ *************** lookup_namespace_name (tree namespace, t *** 3612,3618 **** { /* This happens for A::B where B is a template, and there are no template arguments. */ ! error ("invalid use of `%D'", name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } --- 3418,3424 ---- { /* This happens for A::B where B is a template, and there are no template arguments. */ ! error ("invalid use of %qD", name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } *************** lookup_namespace_name (tree namespace, t *** 3628,3636 **** name = DECL_NAME (name); } ! my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373); - cxx_binding_clear (&binding); if (!qualified_lookup_using_namespace (name, namespace, &binding, 0)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); --- 3434,3441 ---- name = DECL_NAME (name); } ! gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); if (!qualified_lookup_using_namespace (name, namespace, &binding, 0)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); *************** lookup_namespace_name (tree namespace, t *** 3653,3660 **** TREE_OPERAND (template_id, 1)); else { ! error ("`%D::%D' is not a template", ! namespace, name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } } --- 3458,3464 ---- TREE_OPERAND (template_id, 1)); else { ! error ("%<%D::%D%> is not a template", namespace, name); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } } *************** lookup_namespace_name (tree namespace, t *** 3670,3683 **** POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); } ! error ("`%D' undeclared in namespace `%D'", name, namespace); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } /* Select the right _DECL from multiple choices. */ static tree ! select_decl (cxx_binding *binding, int flags) { tree val; val = binding->value; --- 3474,3487 ---- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); } ! error ("%qD undeclared in namespace %qD", name, namespace); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); } /* Select the right _DECL from multiple choices. */ static tree ! select_decl (const struct scope_binding *binding, int flags) { tree val; val = binding->value; *************** select_decl (cxx_binding *binding, int f *** 3696,3704 **** if (binding->type && (!val || (flags & LOOKUP_PREFER_TYPES))) val = binding->type; /* 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; POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); --- 3500,3507 ---- if (binding->type && (!val || (flags & LOOKUP_PREFER_TYPES))) val = binding->type; /* Don't return non-types if we really prefer types. */ ! else if (val && LOOKUP_TYPES_ONLY (flags) ! && ! DECL_DECLARES_TYPE_P (val)) val = NULL_TREE; POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); *************** unqualified_namespace_lookup (tree name, *** 3715,3724 **** tree siter; struct cp_binding_level *level; tree val = NULL_TREE; ! cxx_binding binding; timevar_push (TV_NAME_LOOKUP); - cxx_binding_clear (&binding); for (; !val; scope = CP_DECL_CONTEXT (scope)) { --- 3518,3526 ---- tree siter; struct cp_binding_level *level; tree val = NULL_TREE; ! struct scope_binding binding = EMPTY_SCOPE_BINDING; timevar_push (TV_NAME_LOOKUP); for (; !val; scope = CP_DECL_CONTEXT (scope)) { *************** unqualified_namespace_lookup (tree name, *** 3773,3779 **** Returns a DECL (or OVERLOAD, or BASELINK) representing the declaration found. If no suitable declaration can be found, ! ERROR_MARK_NODE is returned. Iif COMPLAIN is true and SCOPE is neither a class-type nor a namespace a diagnostic is issued. */ tree --- 3575,3581 ---- Returns a DECL (or OVERLOAD, or BASELINK) representing the declaration found. If no suitable declaration can be found, ! ERROR_MARK_NODE is returned. If COMPLAIN is true and SCOPE is neither a class-type nor a namespace a diagnostic is issued. */ tree *************** lookup_qualified_name (tree scope, tree *** 3783,3791 **** if (TREE_CODE (scope) == NAMESPACE_DECL) { ! cxx_binding binding; - cxx_binding_clear (&binding); flags |= LOOKUP_COMPLAIN; if (is_type_p) flags |= LOOKUP_PREFER_TYPES; --- 3585,3592 ---- if (TREE_CODE (scope) == NAMESPACE_DECL) { ! struct scope_binding binding = EMPTY_SCOPE_BINDING; flags |= LOOKUP_COMPLAIN; if (is_type_p) flags |= LOOKUP_PREFER_TYPES; *************** lookup_qualified_name (tree scope, tree *** 3795,3801 **** else if (is_aggr_type (scope, complain)) { tree t; ! t = lookup_member (scope, name, 0, is_type_p); if (t) return t; } --- 3596,3602 ---- else if (is_aggr_type (scope, complain)) { tree t; ! t = lookup_member (scope, name, 2, is_type_p); if (t) return t; } *************** lookup_qualified_name (tree scope, tree *** 3811,3818 **** Returns false on errors. */ static bool ! lookup_using_namespace (tree name, cxx_binding *val, tree usings, tree scope, ! int flags) { tree iter; timevar_push (TV_NAME_LOOKUP); --- 3612,3619 ---- Returns false on errors. */ static bool ! lookup_using_namespace (tree name, struct scope_binding *val, ! tree usings, tree scope, int flags) { tree iter; timevar_push (TV_NAME_LOOKUP); *************** lookup_using_namespace (tree name, cxx_b *** 3826,3832 **** cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name); /* Resolve ambiguities. */ if (val1) ! val = ambiguous_decl (name, val, val1, flags); } POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node); } --- 3627,3633 ---- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name); /* Resolve ambiguities. */ if (val1) ! ambiguous_decl (name, val, val1, flags); } POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node); } *************** lookup_using_namespace (tree name, cxx_b *** 3837,3844 **** or false on error. */ static bool ! qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result, ! int flags) { /* Maintain a list of namespaces visited... */ tree seen = NULL_TREE; --- 3638,3645 ---- or false on error. */ static bool ! qualified_lookup_using_namespace (tree name, tree scope, ! struct scope_binding *result, int flags) { /* Maintain a list of namespaces visited... */ tree seen = NULL_TREE; *************** qualified_lookup_using_namespace (tree n *** 3855,3861 **** cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); seen = tree_cons (scope, NULL_TREE, seen); if (binding) ! result = ambiguous_decl (name, result, binding, flags); /* Consider strong using directives always, and non-strong ones if we haven't found a binding yet. ??? Shouldn't we consider --- 3656,3662 ---- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); seen = tree_cons (scope, NULL_TREE, seen); if (binding) ! ambiguous_decl (name, result, binding, flags); /* Consider strong using directives always, and non-strong ones if we haven't found a binding yet. ??? Shouldn't we consider *************** qualified_lookup_using_namespace (tree n *** 3900,3905 **** --- 3701,3773 ---- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node); } + /* Return the innermost non-namespace binding for NAME from a scope + containing BINDING, or, if BINDING is NULL, the current scope. If + CLASS_P is false, then class bindings are ignored. */ + + cxx_binding * + outer_binding (tree name, + cxx_binding *binding, + bool class_p) + { + cxx_binding *outer; + cxx_scope *scope; + cxx_scope *outer_scope; + + if (binding) + { + scope = binding->scope->level_chain; + outer = binding->previous; + } + else + { + scope = current_binding_level; + outer = IDENTIFIER_BINDING (name); + } + outer_scope = outer ? outer->scope : NULL; + + /* Because we create class bindings lazily, we might be missing a + class binding for NAME. If there are any class binding levels + between the LAST_BINDING_LEVEL and the scope in which OUTER was + declared, we must lookup NAME in those class scopes. */ + if (class_p) + while (scope && scope != outer_scope && scope->kind != sk_namespace) + { + if (scope->kind == sk_class) + { + cxx_binding *class_binding; + + class_binding = get_class_binding (name, scope); + if (class_binding) + { + /* Thread this new class-scope binding onto the + IDENTIFIER_BINDING list so that future lookups + find it quickly. */ + class_binding->previous = outer; + if (binding) + binding->previous = class_binding; + else + IDENTIFIER_BINDING (name) = class_binding; + return class_binding; + } + } + scope = scope->level_chain; + } + + return outer; + } + + /* Return the innermost block-scope or class-scope value binding for + NAME, or NULL_TREE if there is no such binding. */ + + tree + innermost_non_namespace_value (tree name) + { + cxx_binding *binding; + binding = outer_binding (name, /*binding=*/NULL, /*class_p=*/true); + return binding ? binding->value : NULL_TREE; + } + /* 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 *************** qualified_lookup_using_namespace (tree n *** 3910,3920 **** If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces). Otherwise we prefer non-TYPE_DECLs. ! If NONCLASS is nonzero, we don't look for the NAME in class scope, ! using IDENTIFIER_CLASS_VALUE. */ tree ! lookup_name_real (tree name, int prefer_type, int nonclass, int namespaces_only, int flags) { cxx_binding *iter; --- 3778,3788 ---- If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces). Otherwise we prefer non-TYPE_DECLs. ! If NONCLASS is nonzero, bindings in class scopes are ignored. If ! BLOCK_P is false, bindings in block scopes are ignored. */ tree ! lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p, int namespaces_only, int flags) { cxx_binding *iter; *************** lookup_name_real (tree name, int prefer_ *** 3957,3993 **** if (current_class_type == NULL_TREE) nonclass = 1; ! for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous) ! { ! tree binding; ! ! 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 (iter->value, flags)) ! binding = iter->value; ! else if ((flags & LOOKUP_PREFER_TYPES) ! && qualify_lookup (iter->type, flags)) ! binding = iter->type; ! else ! binding = NULL_TREE; ! ! if (binding) ! { ! val = binding; ! break; ! } ! } /* Now lookup in namespace scopes. */ if (!val) ! { ! tree t = unqualified_namespace_lookup (name, flags); ! if (t) ! val = t; ! } if (val) { --- 3825,3860 ---- if (current_class_type == NULL_TREE) nonclass = 1; ! if (block_p || !nonclass) ! for (iter = outer_binding (name, NULL, !nonclass); ! iter; ! iter = outer_binding (name, iter, !nonclass)) ! { ! tree binding; ! ! /* Skip entities we don't want. */ ! if (LOCAL_BINDING_P (iter) ? !block_p : nonclass) ! continue; ! ! /* If this is the kind of thing we're looking for, we're done. */ ! if (qualify_lookup (iter->value, flags)) ! binding = iter->value; ! else if ((flags & LOOKUP_PREFER_TYPES) ! && qualify_lookup (iter->type, flags)) ! binding = iter->type; ! else ! binding = NULL_TREE; ! ! if (binding) ! { ! val = binding; ! break; ! } ! } /* Now lookup in namespace scopes. */ if (!val) ! val = unqualified_namespace_lookup (name, flags); if (val) { *************** lookup_name_real (tree name, int prefer_ *** 4002,4027 **** tree lookup_name_nonclass (tree name) { ! return lookup_name_real (name, 0, 1, 0, LOOKUP_COMPLAIN); } tree ! lookup_function_nonclass (tree name, tree args) { ! return lookup_arg_dependent (name, lookup_name_nonclass (name), args); } tree lookup_name (tree name, int prefer_type) { ! return lookup_name_real (name, prefer_type, 0, 0, LOOKUP_COMPLAIN); } /* Similar to `lookup_name' but look only in the innermost non-class binding level. */ static tree ! lookup_name_current_level (tree name) { struct cp_binding_level *b; tree t = NULL_TREE; --- 3869,3992 ---- tree lookup_name_nonclass (tree name) { ! return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); } tree ! lookup_function_nonclass (tree name, tree args, bool block_p) { ! return ! lookup_arg_dependent (name, ! lookup_name_real (name, 0, 1, block_p, 0, ! LOOKUP_COMPLAIN), ! args); } tree lookup_name (tree name, int prefer_type) { ! return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, ! 0, LOOKUP_COMPLAIN); ! } ! ! /* Look up NAME for type used in elaborated name specifier in ! the scopes given by SCOPE. SCOPE can be either TS_CURRENT or ! TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the ! name, more scopes are checked if cleanup or template parameter ! scope is encountered. ! ! Unlike lookup_name_real, we make sure that NAME is actually ! declared in the desired scope, not from inheritance, nor using ! directive. For using declaration, there is DR138 still waiting ! to be resolved. ! ! A TYPE_DECL best matching the NAME is returned. Catching error ! and issuing diagnostics are caller's responsibility. */ ! ! tree ! lookup_type_scope (tree name, tag_scope scope) ! { ! cxx_binding *iter = NULL; ! tree val = NULL_TREE; ! ! timevar_push (TV_NAME_LOOKUP); ! ! /* Look in non-namespace scope first. */ ! if (current_binding_level->kind != sk_namespace) ! iter = outer_binding (name, NULL, /*class_p=*/ true); ! for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true)) ! { ! /* Check if this is the kind of thing we're looking for. ! If SCOPE is TS_CURRENT, also make sure it doesn't come from ! base class. For ITER->VALUE, we can simply use ! INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to use ! our own check. ! ! We check ITER->TYPE before ITER->VALUE in order to handle ! typedef struct C {} C; ! correctly. */ ! ! if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES) ! && (scope != ts_current ! || LOCAL_BINDING_P (iter) ! || DECL_CONTEXT (iter->type) == iter->scope->this_entity)) ! val = iter->type; ! else if ((scope != ts_current ! || !INHERITED_VALUE_BINDING_P (iter)) ! && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES)) ! val = iter->value; ! ! if (val) ! break; ! } ! ! /* Look in namespace scope. */ ! if (!val) ! { ! iter = cxx_scope_find_binding_for_name ! (NAMESPACE_LEVEL (current_decl_namespace ()), name); ! ! if (iter) ! { ! /* If this is the kind of thing we're looking for, we're done. ! Ignore names found via using declaration. See DR138 for ! current status. */ ! if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)) ! val = iter->type; ! else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES)) ! val = iter->value; ! } ! ! } ! ! /* Type found, check if it is in the allowed scopes, ignoring cleanup ! and template parameter scopes. */ ! if (val) ! { ! struct cp_binding_level *b = current_binding_level; ! while (b) ! { ! if (iter->scope == b) ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); ! ! if (b->kind == sk_cleanup || b->kind == sk_template_parms) ! b = b->level_chain; ! else if (b->kind == sk_class ! && scope == ts_within_enclosing_non_class) ! b = b->level_chain; ! else ! break; ! } ! } ! ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); } /* Similar to `lookup_name' but look only in the innermost non-class binding level. */ static tree ! lookup_name_innermost_nonclass_level (tree name) { struct cp_binding_level *b; tree t = NULL_TREE; *************** lookup_name_current_level (tree name) *** 4040,4049 **** else if (IDENTIFIER_BINDING (name) && LOCAL_BINDING_P (IDENTIFIER_BINDING (name))) { while (1) { ! if (IDENTIFIER_BINDING (name)->scope == b) ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name)); if (b->kind == sk_cleanup) b = b->level_chain; --- 4005,4018 ---- else if (IDENTIFIER_BINDING (name) && LOCAL_BINDING_P (IDENTIFIER_BINDING (name))) { + cxx_binding *binding; + binding = IDENTIFIER_BINDING (name); while (1) { ! if (binding->scope == b ! && !(TREE_CODE (binding->value) == VAR_DECL ! && DECL_DEAD_FOR_LOCAL (binding->value))) ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, binding->value); if (b->kind == sk_cleanup) b = b->level_chain; *************** lookup_name_current_level (tree name) *** 4055,4061 **** POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); } ! /* Like lookup_name_current_level, but for types. */ static tree lookup_type_current_level (tree name) --- 4024,4030 ---- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); } ! /* Like lookup_name_innermost_nonclass_level, but for types. */ static tree lookup_type_current_level (tree name) *************** lookup_type_current_level (tree name) *** 4063,4070 **** tree t = NULL_TREE; timevar_push (TV_NAME_LOOKUP); ! my_friendly_assert (current_binding_level->kind != sk_namespace, ! 980716); if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node) --- 4032,4038 ---- tree t = NULL_TREE; timevar_push (TV_NAME_LOOKUP); ! gcc_assert (current_binding_level->kind != sk_namespace); if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node) *************** add_function (struct arg_lookup *k, tree *** 4132,4140 **** { fn = f1; f1 = f2; f2 = fn; } ! cp_error_at ("`%D' is not a function,", f1); ! cp_error_at (" conflict with `%D'", f2); ! error (" in call to `%D'", k->name); return true; } --- 4100,4108 ---- { fn = f1; f1 = f2; f2 = fn; } ! cp_error_at ("%qD is not a function,", f1); ! cp_error_at (" conflict with %qD", f2); ! error (" in call to %qD", k->name); return true; } *************** arg_assoc_class (struct arg_lookup *k, t *** 4260,4270 **** context = decl_namespace_context (type); if (arg_assoc_namespace (k, context)) return true; ! ! /* Process baseclasses. */ ! for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++) ! if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i))) ! return true; /* Process friends. */ for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; --- 4228,4244 ---- context = decl_namespace_context (type); if (arg_assoc_namespace (k, context)) return true; ! ! if (TYPE_BINFO (type)) ! { ! /* Process baseclasses. */ ! tree binfo, base_binfo; ! ! for (binfo = TYPE_BINFO (type), i = 0; ! BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) ! if (arg_assoc_class (k, BINFO_TYPE (base_binfo))) ! return true; ! } /* Process friends. */ for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; *************** arg_assoc_class (struct arg_lookup *k, t *** 4289,4295 **** } /* Process template arguments. */ ! if (CLASSTYPE_TEMPLATE_INFO (type)) { list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); for (i = 0; i < TREE_VEC_LENGTH (list); ++i) --- 4263,4270 ---- } /* Process template arguments. */ ! if (CLASSTYPE_TEMPLATE_INFO (type) ! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) { list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); for (i = 0; i < TREE_VEC_LENGTH (list); ++i) *************** arg_assoc_type (struct arg_lookup *k, tr *** 4355,4365 **** case TYPENAME_TYPE: return false; case LANG_TYPE: ! if (type == unknown_type_node) ! return false; ! /* else fall through */ default: ! abort (); } return false; } --- 4330,4339 ---- case TYPENAME_TYPE: return false; case LANG_TYPE: ! gcc_assert (type == unknown_type_node); ! return false; default: ! gcc_unreachable (); } return false; } *************** maybe_process_template_type_declaration *** 4541,4551 **** ; else { ! maybe_check_template_type (type); ! ! my_friendly_assert (IS_AGGR_TYPE (type) ! || TREE_CODE (type) == ENUMERAL_TYPE, 0); ! if (processing_template_decl) { --- 4515,4521 ---- ; else { ! gcc_assert (IS_AGGR_TYPE (type) || TREE_CODE (type) == ENUMERAL_TYPE); if (processing_template_decl) { *************** maybe_process_template_type_declaration *** 4566,4584 **** && b->level_chain->kind == sk_class) { finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type)); ! /* Put this UDT in the table of UDTs for the class, since ! that won't happen below because B is not the class ! binding level, but is instead the pseudo-global level. */ ! 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)) { maybe_add_class_template_decl_list (current_class_type, type, /*friend_p=*/0); ! CLASSTYPE_NESTED_UTDS (current_class_type) = ! b->level_chain->type_decls; } } } --- 4536,4553 ---- && b->level_chain->kind == sk_class) { finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type)); ! if (!COMPLETE_TYPE_P (current_class_type)) { maybe_add_class_template_decl_list (current_class_type, type, /*friend_p=*/0); ! /* Put this UDT in the table of UDTs for the class. */ ! if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL) ! CLASSTYPE_NESTED_UTDS (current_class_type) = ! binding_table_new (SCOPE_DEFAULT_HT_SIZE); ! ! binding_table_insert ! (CLASSTYPE_NESTED_UTDS (current_class_type), name, type); } } } *************** maybe_process_template_type_declaration *** 4590,4598 **** /* Push a tag name NAME for struct/class/union/enum type TYPE. Normally put it into the inner-most non-sk_cleanup scope, but if GLOBALIZE is true, put it in the inner-most non-class scope. ! The latter is needed for implicit declarations. */ ! void pushtag (tree name, tree type, int globalize) { struct cp_binding_level *b; --- 4559,4568 ---- /* Push a tag name NAME for struct/class/union/enum type TYPE. Normally put it into the inner-most non-sk_cleanup scope, but if GLOBALIZE is true, put it in the inner-most non-class scope. ! The latter is needed for implicit declarations. ! Returns TYPE upon success and ERROR_MARK_NODE otherwise. */ ! tree pushtag (tree name, tree type, int globalize) { struct cp_binding_level *b; *************** pushtag (tree name, tree type, int globa *** 4618,4627 **** || COMPLETE_TYPE_P (b->this_entity)))) b = b->level_chain; - 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) { /* Do C++ gratuitous typedefing. */ --- 4588,4593 ---- *************** pushtag (tree name, tree type, int globa *** 4661,4666 **** --- 4627,4634 ---- d = maybe_process_template_type_declaration (type, globalize, b); + if (d == error_mark_node) + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); if (b->kind == sk_class) { *************** pushtag (tree name, tree type, int globa *** 4697,4703 **** { maybe_add_class_template_decl_list (current_class_type, type, /*friend_p=*/0); ! CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls; } } --- 4665,4677 ---- { maybe_add_class_template_decl_list (current_class_type, type, /*friend_p=*/0); ! ! if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL) ! CLASSTYPE_NESTED_UTDS (current_class_type) ! = binding_table_new (SCOPE_DEFAULT_HT_SIZE); ! ! binding_table_insert ! (CLASSTYPE_NESTED_UTDS (current_class_type), name, type); } } *************** pushtag (tree name, tree type, int globa *** 4717,4741 **** tree d = build_decl (TYPE_DECL, NULL_TREE, type); TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b); } ! 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 --- 4691,4699 ---- tree d = build_decl (TYPE_DECL, NULL_TREE, type); TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b); } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type); } /* 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 *************** struct cxx_saved_binding GTY(()) *** 4743,4791 **** scope isn't enough, because more binding levels may be pushed. */ struct saved_scope *scope_chain; ! static cxx_saved_binding * ! store_bindings (tree names, cxx_saved_binding *old_bindings) { tree t; - cxx_saved_binding *search_bindings = old_bindings; timevar_push (TV_NAME_LOOKUP); for (t = names; t; t = TREE_CHAIN (t)) { tree id; - cxx_saved_binding *saved; - cxx_saved_binding *t1; if (TREE_CODE (t) == TREE_LIST) id = TREE_PURPOSE (t); else id = DECL_NAME (t); ! if (!id ! /* Note that we may have an IDENTIFIER_CLASS_VALUE even when ! we have no IDENTIFIER_BINDING if we have left the class ! scope, but cached the class-level declarations. */ ! || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id))) ! continue; ! for (t1 = search_bindings; t1; t1 = t1->previous) ! if (t1->identifier == id) ! goto skip_it; ! my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135); ! 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; ! old_bindings = saved; ! skip_it: ! ; ! } ! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings); } void --- 4701,4763 ---- scope isn't enough, because more binding levels may be pushed. */ struct saved_scope *scope_chain; ! /* If ID has not already been marked, add an appropriate binding to ! *OLD_BINDINGS. */ ! ! static void ! store_binding (tree id, VEC(cxx_saved_binding) **old_bindings) ! { ! cxx_saved_binding *saved; ! ! if (!id || !IDENTIFIER_BINDING (id)) ! return; ! ! if (IDENTIFIER_MARKED (id)) ! return; ! ! IDENTIFIER_MARKED (id) = 1; ! ! saved = VEC_safe_push (cxx_saved_binding, *old_bindings, NULL); ! saved->identifier = id; ! saved->binding = IDENTIFIER_BINDING (id); ! saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id); ! IDENTIFIER_BINDING (id) = NULL; ! } ! ! static void ! store_bindings (tree names, VEC(cxx_saved_binding) **old_bindings) { tree t; timevar_push (TV_NAME_LOOKUP); for (t = names; t; t = TREE_CHAIN (t)) { tree id; if (TREE_CODE (t) == TREE_LIST) id = TREE_PURPOSE (t); else id = DECL_NAME (t); ! store_binding (id, old_bindings); ! } ! timevar_pop (TV_NAME_LOOKUP); ! } ! /* Like store_bindings, but NAMES is a vector of cp_class_binding ! objects, rather than a TREE_LIST. */ ! static void ! store_class_bindings (VEC(cp_class_binding) *names, ! VEC(cxx_saved_binding) **old_bindings) ! { ! size_t i; ! cp_class_binding *cb; ! ! timevar_push (TV_NAME_LOOKUP); ! for (i = 0; VEC_iterate(cp_class_binding, names, i, cb); ++i) ! store_binding (cb->identifier, old_bindings); ! timevar_pop (TV_NAME_LOOKUP); } void *************** push_to_top_level (void) *** 4793,4803 **** { struct saved_scope *s; struct cp_binding_level *b; ! cxx_saved_binding *old_bindings; int need_pop; timevar_push (TV_NAME_LOOKUP); ! s = ggc_alloc_cleared (sizeof (struct saved_scope)); b = scope_chain ? current_binding_level : 0; --- 4765,4776 ---- { struct saved_scope *s; struct cp_binding_level *b; ! cxx_saved_binding *sb; ! size_t i; int need_pop; timevar_push (TV_NAME_LOOKUP); ! s = GGC_CNEW (struct saved_scope); b = scope_chain ? current_binding_level : 0; *************** push_to_top_level (void) *** 4810,4818 **** else need_pop = 0; ! old_bindings = NULL; ! if (scope_chain && previous_class_type) ! old_bindings = store_bindings (previous_class_values, old_bindings); /* Have to include the global scope, because class-scope decls aren't listed anywhere useful. */ --- 4783,4791 ---- else need_pop = 0; ! if (scope_chain && previous_class_level) ! store_class_bindings (previous_class_level->class_shadowed, ! &s->old_bindings); /* Have to include the global scope, because class-scope decls aren't listed anywhere useful. */ *************** push_to_top_level (void) *** 4827,4844 **** if (global_scope_p (b)) break; ! old_bindings = store_bindings (b->names, old_bindings); /* We also need to check class_shadowed to save class-level type bindings, since pushclass doesn't fill in b->names. */ if (b->kind == sk_class) ! old_bindings = store_bindings (b->class_shadowed, old_bindings); /* Unwind type-value slots back to top level. */ for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); } s->prev = scope_chain; - s->old_bindings = old_bindings; s->bindings = b; s->need_pop_function_context = need_pop; s->function_decl = current_function_decl; --- 4800,4820 ---- if (global_scope_p (b)) break; ! store_bindings (b->names, &s->old_bindings); /* We also need to check class_shadowed to save class-level type bindings, since pushclass doesn't fill in b->names. */ if (b->kind == sk_class) ! store_class_bindings (b->class_shadowed, &s->old_bindings); /* Unwind type-value slots back to top level. */ for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); } + + for (i = 0; VEC_iterate (cxx_saved_binding, s->old_bindings, i, sb); ++i) + IDENTIFIER_MARKED (sb->identifier) = 0; + s->prev = scope_chain; s->bindings = b; s->need_pop_function_context = need_pop; s->function_decl = current_function_decl; *************** pop_from_top_level (void) *** 4856,4876 **** { struct saved_scope *s = scope_chain; cxx_saved_binding *saved; timevar_push (TV_NAME_LOOKUP); /* Clear out class-level bindings cache. */ ! if (previous_class_type) invalidate_class_lookup_cache (); current_lang_base = 0; scope_chain = s->prev; ! for (saved = s->old_bindings; saved; saved = saved->previous) { tree id = saved->identifier; IDENTIFIER_BINDING (id) = saved->binding; - IDENTIFIER_CLASS_VALUE (id) = saved->class_value; SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value); } --- 4832,4852 ---- { struct saved_scope *s = scope_chain; cxx_saved_binding *saved; + size_t i; timevar_push (TV_NAME_LOOKUP); /* Clear out class-level bindings cache. */ ! if (previous_class_level) invalidate_class_lookup_cache (); current_lang_base = 0; scope_chain = s->prev; ! for (i = 0; VEC_iterate (cxx_saved_binding, s->old_bindings, i, saved); ++i) { tree id = saved->identifier; IDENTIFIER_BINDING (id) = saved->binding; SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value); } *************** pop_everything (void) *** 4902,4905 **** --- 4878,4909 ---- verbatim ("XXX leaving pop_everything ()\n"); } + /* Emit debugging information for using declarations and directives. + If input tree is overloaded fn then emit debug info for all + candidates. */ + + static void + cp_emit_debug_info_for_using (tree t, tree context) + { + /* Ignore this FUNCTION_DECL if it refers to a builtin declaration + of a builtin function. */ + if (TREE_CODE (t) == FUNCTION_DECL + && DECL_EXTERNAL (t) + && DECL_BUILT_IN (t)) + return; + + /* Do not supply context to imported_module_or_decl, if + it is a global namespace. */ + if (context == global_namespace) + context = NULL_TREE; + + if (BASELINK_P (t)) + t = BASELINK_FUNCTIONS (t); + + /* FIXME: Handle TEMPLATE_DECLs. */ + for (t = OVL_CURRENT (t); t; t = OVL_NEXT (t)) + if (TREE_CODE (t) != TEMPLATE_DECL) + (*debug_hooks->imported_module_or_decl) (t, context); + } + #include "gt-cp-name-lookup.h" diff -Nrcpad gcc-3.4.3/gcc/cp/name-lookup.h gcc-4.0.0/gcc/cp/name-lookup.h *** gcc-3.4.3/gcc/cp/name-lookup.h Mon Mar 1 06:21:39 2004 --- gcc-4.0.0/gcc/cp/name-lookup.h Tue Jan 25 08:55:00 2005 *************** *** 1,5 **** /* Declarations for C++ name lookup routines. ! Copyright (C) 2003, 2004 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. --- 1,5 ---- /* Declarations for C++ name lookup routines. ! Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. *************** struct binding_entry_s GTY(()) *** 46,60 **** #define NAMESPACE_STD_HT_SIZE (1 << 8) #define GLOBAL_SCOPE_HT_SIZE (1 << 8) - extern void binding_table_remove_anonymous_types (binding_table); 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); - /* 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; - /* Datatype that represents binding established by a declaration between a name and a C++ entity. */ typedef struct cxx_binding cxx_binding; --- 46,54 ---- *************** struct cxx_binding GTY(()) *** 84,94 **** unsigned is_local : 1; }; extern tree identifier_type_value (tree); extern void set_identifier_type_value (tree, tree); extern void pop_binding (tree, tree); - extern void clear_identifier_class_values (void); - extern tree constructor_name_full (tree); extern tree constructor_name (tree); extern bool constructor_name_p (tree, tree); --- 78,99 ---- unsigned is_local : 1; }; + /* Datatype used to temporarily save C++ bindings (for implicit + instantiations purposes and like). Implemented in decl.c. */ + typedef struct cxx_saved_binding GTY(()) + { + /* The name of the current binding. */ + tree identifier; + /* The binding we're saving. */ + cxx_binding *binding; + tree real_type_value; + } cxx_saved_binding; + + DEF_VEC_GC_O(cxx_saved_binding); + extern tree identifier_type_value (tree); extern void set_identifier_type_value (tree, tree); extern void pop_binding (tree, tree); extern tree constructor_name (tree); extern bool constructor_name_p (tree, tree); *************** typedef enum scope_kind { *** 117,122 **** --- 122,152 ---- "template <>", this scope is always empty. */ } scope_kind; + /* The scope where the class/struct/union/enum tag applies. */ + typedef enum tag_scope { + ts_current = 0, /* Current scope only. This is for the + class-key identifier; + case mentioned in [basic.lookup.elab]/2, + or the class/enum definition + class-key identifier { ... }; */ + ts_global = 1, /* All scopes. This is the 3.4.1 + [basic.lookup.unqual] lookup mentioned + in [basic.lookup.elab]/2. */ + ts_within_enclosing_non_class = 2 /* Search within enclosing non-class + only, for friend class lookup + according to [namespace.memdef]/3 + and [class.friend]/9. */ + } tag_scope; + + typedef struct cp_class_binding GTY(()) + { + cxx_binding base; + /* The bound name. */ + tree identifier; + } cp_class_binding; + + DEF_VEC_GC_O(cp_class_binding); + /* For each binding contour we allocate a binding_level structure which records the names defined in that contour. Contours include: *************** struct cp_binding_level GTY(()) *** 161,169 **** /* A chain of VTABLE_DECL nodes. */ tree vtables; - /* A dictionary for looking up user-defined-types. */ - binding_table type_decls; - /* A list of USING_DECL nodes. */ tree usings; --- 191,196 ---- *************** struct cp_binding_level GTY(()) *** 171,185 **** 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 ! class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node ! is the name of an entity bound in the class. The TREE_TYPE is ! the DECL bound by this name in the class. */ ! tree class_shadowed; /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and ! is used for all binding levels. In addition the TREE_VALUE is the ! IDENTIFIER_TYPE_VALUE before we entered the class. */ tree type_shadowed; /* A TREE_LIST. Each TREE_VALUE is the LABEL_DECL for a local --- 198,212 ---- VALUE the common ancestor with this binding_level's namespace. */ tree using_directives; ! /* For the binding level corresponding to a class, the entities ! declared in the class or its base classes. */ ! VEC(cp_class_binding) *class_shadowed; /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and ! is used for all binding levels. The TREE_PURPOSE is the name of ! the entity, the TREE_TYPE is the associated type. In addition ! the TREE_VALUE is the IDENTIFIER_TYPE_VALUE before we entered ! the class. */ tree type_shadowed; /* A TREE_LIST. Each TREE_VALUE is the LABEL_DECL for a local *************** struct cp_binding_level GTY(()) *** 205,216 **** TREE_LIST; the TREE_VALUE is the actual declaration. */ tree dead_vars_from_for; /* Binding depth at which this level began. */ int binding_depth; /* The kind of scope that this object represents. However, a SK_TEMPLATE_SPEC scope is represented with KIND set to ! SK_TEMPALTE_PARMS and EXPLICIT_SPEC_P set to true. */ ENUM_BITFIELD (scope_kind) kind : 4; /* True if this scope is an SK_TEMPLATE_SPEC scope. This field is --- 232,247 ---- TREE_LIST; the TREE_VALUE is the actual declaration. */ tree dead_vars_from_for; + /* STATEMENT_LIST for statements in this binding contour. + Only used at present for SK_CLEANUP temporary bindings. */ + tree statement_list; + /* Binding depth at which this level began. */ int binding_depth; /* The kind of scope that this object represents. However, a SK_TEMPLATE_SPEC scope is represented with KIND set to ! SK_TEMPLATE_PARMS and EXPLICIT_SPEC_P set to true. */ ENUM_BITFIELD (scope_kind) kind : 4; /* True if this scope is an SK_TEMPLATE_SPEC scope. This field is *************** extern bool template_parm_scope_p (void) *** 261,274 **** extern scope_kind innermost_scope_kind (void); extern cxx_scope *begin_scope (scope_kind, tree); extern void print_binding_stack (void); - extern void print_binding_level (cxx_scope *); extern void push_to_top_level (void); extern void pop_from_top_level (void); extern void pop_everything (void); extern void keep_next_level (bool); extern bool is_ancestor (tree, tree); ! extern bool push_scope (tree); extern void pop_scope (tree); extern void push_namespace (tree); extern void pop_namespace (void); --- 292,307 ---- extern scope_kind innermost_scope_kind (void); extern cxx_scope *begin_scope (scope_kind, tree); extern void print_binding_stack (void); extern void push_to_top_level (void); extern void pop_from_top_level (void); extern void pop_everything (void); extern void keep_next_level (bool); extern bool is_ancestor (tree, tree); ! extern tree push_scope (tree); extern void pop_scope (tree); + extern tree push_inner_scope (tree); + extern void pop_inner_scope (tree, tree); + extern void push_binding_level (struct cp_binding_level *); extern void push_namespace (tree); extern void pop_namespace (void); *************** extern void pop_nested_namespace (tree); *** 277,313 **** extern void pushlevel_class (void); extern void poplevel_class (void); extern tree pushdecl_with_scope (tree, cxx_scope *); - extern tree lookup_tag (enum tree_code, tree, cxx_scope *, int); - extern tree lookup_tag_reverse (tree, tree); extern tree lookup_name (tree, int); ! extern tree lookup_name_real (tree, int, int, int, int); extern tree namespace_binding (tree, tree); extern void set_namespace_binding (tree, tree, tree); extern tree lookup_namespace_name (tree, tree); extern tree lookup_qualified_name (tree, tree, bool, bool); extern tree lookup_name_nonclass (tree); ! extern tree lookup_function_nonclass (tree, tree); ! extern int push_class_binding (tree, tree); extern bool pushdecl_class_level (tree); extern tree pushdecl_namespace_level (tree); extern bool push_class_level_binding (tree, tree); - extern void storetags (tree); extern tree getdecls (void); extern tree cp_namespace_decls (tree); - extern void set_class_shadows (tree); extern void set_decl_namespace (tree, tree, bool); - extern tree current_decl_namespace (void); extern void push_decl_namespace (tree); extern void pop_decl_namespace (void); extern void do_namespace_alias (tree, tree); extern void do_toplevel_using_decl (tree, tree, tree); extern void do_local_using_decl (tree, tree, tree); ! extern tree do_class_using_decl (tree); extern void do_using_directive (tree); extern tree lookup_arg_dependent (tree, tree, tree); extern bool is_associated_namespace (tree, tree); extern void parse_using_directive (tree, tree); ! /* Set *DECL to the (non-hidden) declaration for ID at global scope, if present and return true; otherwise return false. */ --- 310,343 ---- extern void pushlevel_class (void); extern void poplevel_class (void); extern tree pushdecl_with_scope (tree, cxx_scope *); extern tree lookup_name (tree, int); ! extern tree lookup_name_real (tree, int, int, bool, int, int); ! extern tree lookup_type_scope (tree, tag_scope); extern tree namespace_binding (tree, tree); extern void set_namespace_binding (tree, tree, tree); extern tree lookup_namespace_name (tree, tree); extern tree lookup_qualified_name (tree, tree, bool, bool); extern tree lookup_name_nonclass (tree); ! extern tree lookup_function_nonclass (tree, tree, bool); ! extern void push_local_binding (tree, tree, int); extern bool pushdecl_class_level (tree); extern tree pushdecl_namespace_level (tree); extern bool push_class_level_binding (tree, tree); extern tree getdecls (void); extern tree cp_namespace_decls (tree); extern void set_decl_namespace (tree, tree, bool); extern void push_decl_namespace (tree); extern void pop_decl_namespace (void); extern void do_namespace_alias (tree, tree); extern void do_toplevel_using_decl (tree, tree, tree); extern void do_local_using_decl (tree, tree, tree); ! extern tree do_class_using_decl (tree, tree); extern void do_using_directive (tree); extern tree lookup_arg_dependent (tree, tree, tree); extern bool is_associated_namespace (tree, tree); extern void parse_using_directive (tree, tree); ! extern tree innermost_non_namespace_value (tree); ! extern cxx_binding *outer_binding (tree, cxx_binding *, bool); /* Set *DECL to the (non-hidden) declaration for ID at global scope, if present and return true; otherwise return false. */ *************** static inline bool *** 316,322 **** get_global_value_if_present (tree id, tree *decl) { tree global_value = namespace_binding (id, global_namespace); - if (global_value) *decl = global_value; return global_value != NULL; --- 346,351 ---- diff -Nrcpad gcc-3.4.3/gcc/cp/optimize.c gcc-4.0.0/gcc/cp/optimize.c *** gcc-3.4.3/gcc/cp/optimize.c Sun Feb 8 01:52:50 2004 --- gcc-4.0.0/gcc/cp/optimize.c Wed Aug 4 15:33:50 2004 *************** Software Foundation, 59 Temple Place - S *** 34,94 **** #include "varray.h" #include "params.h" #include "hashtab.h" #include "debug.h" #include "tree-inline.h" /* Prototypes. */ - static tree calls_setjmp_r (tree *, int *, void *); static void update_cloned_parm (tree, tree); - static void dump_function (enum tree_dump_index, tree); - - /* Optimize the body of FN. */ - - void - optimize_function (tree fn) - { - dump_function (TDI_original, fn); - - if (flag_inline_trees - /* 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) TARGET_ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */ - && !DECL_THUNK_P (fn)) - { - optimize_inline_calls (fn); - dump_function (TDI_inlined, fn); - } - - dump_function (TDI_optimized, fn); - } - - /* Called from calls_setjmp_p via walk_tree. */ - - static tree - calls_setjmp_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) - { - /* We're only interested in FUNCTION_DECLS. */ - if (TREE_CODE (*tp) != FUNCTION_DECL) - return NULL_TREE; - - return setjmp_call_p (*tp) ? *tp : NULL_TREE; - } - - /* 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 nonzero value even when FN does not actually - call `setjmp'. */ - - bool - calls_setjmp_p (tree fn) - { - return walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), - calls_setjmp_r, - NULL) != NULL_TREE; - } /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor or destructor. Update it to ensure that the source-position for --- 34,51 ---- #include "varray.h" #include "params.h" #include "hashtab.h" + #include "target.h" #include "debug.h" #include "tree-inline.h" + #include "flags.h" + #include "langhooks.h" + #include "diagnostic.h" + #include "tree-dump.h" + #include "tree-gimple.h" /* Prototypes. */ static void update_cloned_parm (tree, tree); /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor or destructor. Update it to ensure that the source-position for *************** maybe_clone_body (tree fn) *** 132,140 **** /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ ! for (clone = TREE_CHAIN (fn); ! clone && DECL_CLONED_FUNCTION_P (clone); ! clone = TREE_CHAIN (clone)) { tree parm; tree clone_parm; --- 89,96 ---- /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ ! push_to_top_level (); ! FOR_EACH_CLONE (clone, fn) { tree parm; tree clone_parm; *************** maybe_clone_body (tree fn) *** 155,160 **** --- 111,117 ---- DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); TREE_PUBLIC (clone) = TREE_PUBLIC (fn); DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); + DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); /* Adjust the parameter names and locations. */ parm = DECL_ARGUMENTS (fn); *************** maybe_clone_body (tree fn) *** 175,182 **** update_cloned_parm (parm, clone_parm); /* Start processing the function. */ ! push_to_top_level (); ! start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED); /* Remap the parameters. */ decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); --- 132,138 ---- update_cloned_parm (parm, clone_parm); /* Start processing the function. */ ! start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); /* Remap the parameters. */ decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); *************** maybe_clone_body (tree fn) *** 229,234 **** --- 185,197 ---- } } + if (targetm.cxx.cdtor_returns_this ()) + { + parm = DECL_RESULT (fn); + clone_parm = DECL_RESULT (clone); + splay_tree_insert (decl_map, (splay_tree_key) parm, + (splay_tree_value) clone_parm); + } /* Clone the body. */ clone_body (clone, fn, decl_map); *************** maybe_clone_body (tree fn) *** 242,273 **** finish_function (0); BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); expand_or_defer_fn (clone); - pop_from_top_level (); } /* We don't need to process the original function any further. */ return 1; } - - /* Dump FUNCTION_DECL FN as tree dump PHASE. */ - - static void - dump_function (enum tree_dump_index phase, tree fn) - { - FILE *stream; - int flags; - - stream = dump_begin (phase, &flags); - if (stream) - { - fprintf (stream, "\n;; Function %s", - decl_as_string (fn, TFF_DECL_SPECIFIERS)); - fprintf (stream, " (%s)\n", - decl_as_string (DECL_ASSEMBLER_NAME (fn), 0)); - fprintf (stream, ";; enabled by -fdump-%s\n", dump_flag_name (phase)); - fprintf (stream, "\n"); - - dump_node (fn, TDF_SLIM | flags, stream); - dump_end (phase, stream); - } - } --- 205,213 ---- finish_function (0); BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); expand_or_defer_fn (clone); } + pop_from_top_level (); /* We don't need to process the original function any further. */ return 1; } diff -Nrcpad gcc-3.4.3/gcc/cp/parser.c gcc-4.0.0/gcc/cp/parser.c *** gcc-3.4.3/gcc/cp/parser.c Thu Oct 28 05:28:20 2004 --- gcc-4.0.0/gcc/cp/parser.c Fri Apr 8 21:23:18 2005 *************** *** 1,5 **** /* C++ Parser. ! Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by Mark Mitchell . This file is part of GCC. --- 1,6 ---- /* C++ Parser. ! Copyright (C) 2000, 2001, 2002, 2003, 2004, ! 2005 Free Software Foundation, Inc. Written by Mark Mitchell . This file is part of GCC. *************** *** 34,67 **** #include "diagnostic.h" #include "toplev.h" #include "output.h" /* The lexer. */ ! /* Overview ! -------- ! ! A cp_lexer represents a stream of cp_tokens. It allows arbitrary ! look-ahead. ! ! Methodology ! ----------- ! ! We use a circular buffer to store incoming tokens. ! ! Some artifacts of the C++ language (such as the ! expression/declaration ambiguity) require arbitrary look-ahead. ! The strategy we adopt for dealing with these problems is to attempt ! to parse one construct (e.g., the declaration) and fall back to the ! other (e.g., the expression) if that attempt does not succeed. ! Therefore, we must sometimes store an arbitrary number of tokens. ! ! The parser routinely peeks at the next token, and then consumes it ! later. That also requires a buffer in which to store the tokens. ! ! In order to easily permit adding tokens to the end of the buffer, ! while removing them from the beginning of the buffer, we use a ! circular buffer. */ /* A C++ token. */ --- 35,47 ---- #include "diagnostic.h" #include "toplev.h" #include "output.h" + #include "target.h" /* The lexer. */ ! /* The cp_lexer_* routines mediate between the lexer proper (in libcpp ! and c-lex.c) and the C++ parser. */ /* A C++ token. */ *************** typedef struct cp_token GTY (()) *** 74,208 **** ENUM_BITFIELD (rid) keyword : 8; /* Token flags. */ unsigned char flags; /* The value associated with this token, if any. */ tree value; /* The location at which this token was found. */ location_t location; } cp_token; ! /* The number of tokens in a single token block. ! Computed so that cp_token_block fits in a 512B allocation unit. */ ! ! #define CP_TOKEN_BLOCK_NUM_TOKENS ((512 - 3*sizeof (char*))/sizeof (cp_token)) ! ! /* A group of tokens. These groups are chained together to store ! large numbers of tokens. (For example, a token block is created ! when the body of an inline member function is first encountered; ! the tokens are processed later after the class definition is ! complete.) ! ! This somewhat ungainly data structure (as opposed to, say, a ! variable-length array), is used due to constraints imposed by the ! current garbage-collection methodology. If it is made more ! flexible, we could perhaps simplify the data structures involved. */ ! ! typedef struct cp_token_block GTY (()) ! { ! /* The tokens. */ ! cp_token tokens[CP_TOKEN_BLOCK_NUM_TOKENS]; ! /* The number of tokens in this block. */ ! size_t num_tokens; ! /* The next token block in the chain. */ ! struct cp_token_block *next; ! /* The previous block in the chain. */ ! struct cp_token_block *prev; ! } cp_token_block; ! ! typedef struct cp_token_cache GTY (()) ! { ! /* The first block in the cache. NULL if there are no tokens in the ! cache. */ ! cp_token_block *first; ! /* The last block in the cache. NULL If there are no tokens in the ! cache. */ ! cp_token_block *last; ! } cp_token_cache; ! ! /* Prototypes. */ ! ! static cp_token_cache *cp_token_cache_new ! (void); ! static void cp_token_cache_push_token ! (cp_token_cache *, cp_token *); ! ! /* Create a new cp_token_cache. */ ! ! static cp_token_cache * ! cp_token_cache_new (void) ! { ! return ggc_alloc_cleared (sizeof (cp_token_cache)); ! } ! ! /* Add *TOKEN to *CACHE. */ ! static void ! cp_token_cache_push_token (cp_token_cache *cache, ! cp_token *token) { ! cp_token_block *b = cache->last; ! ! /* See if we need to allocate a new token block. */ ! if (!b || b->num_tokens == CP_TOKEN_BLOCK_NUM_TOKENS) ! { ! b = ggc_alloc_cleared (sizeof (cp_token_block)); ! b->prev = cache->last; ! if (cache->last) ! { ! cache->last->next = b; ! cache->last = b; ! } ! else ! cache->first = cache->last = b; ! } ! /* Add this token to the current token block. */ ! b->tokens[b->num_tokens++] = *token; ! } /* The cp_lexer structure represents the C++ lexer. It is responsible for managing the token stream from the preprocessor and supplying ! it to the parser. */ typedef struct cp_lexer GTY (()) { ! /* The memory allocated for the buffer. Never NULL. */ ! cp_token * GTY ((length ("(%h.buffer_end - %h.buffer)"))) buffer; ! /* A pointer just past the end of the memory allocated for the buffer. */ ! cp_token * GTY ((skip (""))) buffer_end; ! /* The first valid token in the buffer, or NULL if none. */ ! cp_token * GTY ((skip (""))) first_token; ! /* The next available token. If NEXT_TOKEN is NULL, then there are no more available tokens. */ ! cp_token * GTY ((skip (""))) next_token; ! /* A pointer just past the last available token. If FIRST_TOKEN is ! NULL, however, there are no available tokens, and then this ! location is simply the place in which the next token read will be ! placed. If LAST_TOKEN == FIRST_TOKEN, then the buffer is full. ! When the LAST_TOKEN == BUFFER, then the last token is at the ! highest memory address in the BUFFER. */ ! cp_token * GTY ((skip (""))) last_token; /* A stack indicating positions at which cp_lexer_save_tokens was called. The top entry is the most recent position at which we ! began saving tokens. The entries are differences in token ! position between FIRST_TOKEN and the first saved token. ! ! If the stack is non-empty, we are saving tokens. When a token is ! consumed, the NEXT_TOKEN pointer will move, but the FIRST_TOKEN ! pointer will not. The token stream will be preserved so that it ! can be reexamined later. ! ! If the stack is empty, then we are not saving tokens. Whenever a ! token is consumed, the FIRST_TOKEN pointer will be moved, and the ! consumed token will be gone forever. */ ! varray_type saved_tokens; ! ! /* The STRING_CST tokens encountered while processing the current ! string literal. */ ! varray_type string_tokens; ! ! /* True if we should obtain more tokens from the preprocessor; false ! if we are processing a saved token cache. */ ! bool main_lexer_p; /* True if we should output debugging information. */ bool debugging_p; --- 54,110 ---- ENUM_BITFIELD (rid) keyword : 8; /* Token flags. */ unsigned char flags; + /* True if this token is from a system header. */ + BOOL_BITFIELD in_system_header : 1; + /* True if this token is from a context where it is implicitly extern "C" */ + BOOL_BITFIELD implicit_extern_c : 1; /* The value associated with this token, if any. */ tree value; /* The location at which this token was found. */ location_t location; } cp_token; ! /* We use a stack of token pointer for saving token sets. */ ! typedef struct cp_token *cp_token_position; ! DEF_VEC_MALLOC_P (cp_token_position); ! static const cp_token eof_token = { ! CPP_EOF, RID_MAX, 0, 0, 0, NULL_TREE, ! #if USE_MAPPED_LOCATION ! 0 ! #else ! {0, 0} ! #endif ! }; /* The cp_lexer structure represents the C++ lexer. It is responsible for managing the token stream from the preprocessor and supplying ! it to the parser. Tokens are never added to the cp_lexer after ! it is created. */ typedef struct cp_lexer GTY (()) { ! /* The memory allocated for the buffer. NULL if this lexer does not ! own the token buffer. */ ! cp_token * GTY ((length ("%h.buffer_length"))) buffer; ! /* If the lexer owns the buffer, this is the number of tokens in the ! buffer. */ ! size_t buffer_length; ! ! /* A pointer just past the last available token. The tokens ! in this lexer are [buffer, last_token). */ ! cp_token_position GTY ((skip)) last_token; ! ! /* The next available token. If NEXT_TOKEN is &eof_token, then there are no more available tokens. */ ! cp_token_position GTY ((skip)) next_token; /* A stack indicating positions at which cp_lexer_save_tokens was called. The top entry is the most recent position at which we ! began saving tokens. If the stack is non-empty, we are saving ! tokens. */ ! VEC (cp_token_position) *GTY ((skip)) saved_tokens; /* True if we should output debugging information. */ bool debugging_p; *************** typedef struct cp_lexer GTY (()) *** 211,237 **** struct cp_lexer *next; } cp_lexer; /* Prototypes. */ static cp_lexer *cp_lexer_new_main (void); static cp_lexer *cp_lexer_new_from_tokens ! (struct cp_token_cache *); static int cp_lexer_saving_tokens (const cp_lexer *); ! static cp_token *cp_lexer_next_token ! (cp_lexer *, cp_token *); ! static cp_token *cp_lexer_prev_token ! (cp_lexer *, cp_token *); ! static ptrdiff_t cp_lexer_token_difference ! (cp_lexer *, cp_token *, cp_token *); ! static cp_token *cp_lexer_read_token ! (cp_lexer *); ! static void cp_lexer_maybe_grow_buffer ! (cp_lexer *); static void cp_lexer_get_preprocessor_token (cp_lexer *, cp_token *); ! static cp_token *cp_lexer_peek_token (cp_lexer *); static cp_token *cp_lexer_peek_nth_token (cp_lexer *, size_t); --- 113,150 ---- struct cp_lexer *next; } cp_lexer; + /* cp_token_cache is a range of tokens. There is no need to represent + allocate heap memory for it, since tokens are never removed from the + lexer's array. There is also no need for the GC to walk through + a cp_token_cache, since everything in here is referenced through + a lexer. */ + + typedef struct cp_token_cache GTY(()) + { + /* The beginning of the token range. */ + cp_token * GTY((skip)) first; + + /* Points immediately after the last token in the range. */ + cp_token * GTY ((skip)) last; + } cp_token_cache; + /* Prototypes. */ static cp_lexer *cp_lexer_new_main (void); static cp_lexer *cp_lexer_new_from_tokens ! (cp_token_cache *tokens); ! static void cp_lexer_destroy ! (cp_lexer *); static int cp_lexer_saving_tokens (const cp_lexer *); ! static cp_token_position cp_lexer_token_position ! (cp_lexer *, bool); ! static cp_token *cp_lexer_token_at ! (cp_lexer *, cp_token_position); static void cp_lexer_get_preprocessor_token (cp_lexer *, cp_token *); ! static inline cp_token *cp_lexer_peek_token (cp_lexer *); static cp_token *cp_lexer_peek_nth_token (cp_lexer *, size_t); *************** static bool cp_lexer_next_token_is_not *** 241,273 **** (cp_lexer *, enum cpp_ttype); static bool cp_lexer_next_token_is_keyword (cp_lexer *, enum rid); ! static cp_token *cp_lexer_consume_token (cp_lexer *); static void cp_lexer_purge_token (cp_lexer *); static void cp_lexer_purge_tokens_after ! (cp_lexer *, cp_token *); static void cp_lexer_save_tokens (cp_lexer *); static void cp_lexer_commit_tokens (cp_lexer *); static void cp_lexer_rollback_tokens (cp_lexer *); ! static inline void cp_lexer_set_source_position_from_token ! (cp_lexer *, const cp_token *); static void cp_lexer_print_token (FILE *, cp_token *); ! static inline bool cp_lexer_debugging_p (cp_lexer *); static void cp_lexer_start_debugging (cp_lexer *) ATTRIBUTE_UNUSED; static void cp_lexer_stop_debugging (cp_lexer *) ATTRIBUTE_UNUSED; ! /* Manifest constants. */ ! #define CP_TOKEN_BUFFER_SIZE 5 ! #define CP_SAVED_TOKENS_SIZE 5 /* A token type for keywords, as opposed to ordinary identifiers. */ #define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1)) --- 154,198 ---- (cp_lexer *, enum cpp_ttype); static bool cp_lexer_next_token_is_keyword (cp_lexer *, enum rid); ! static cp_token *cp_lexer_consume_token (cp_lexer *); static void cp_lexer_purge_token (cp_lexer *); static void cp_lexer_purge_tokens_after ! (cp_lexer *, cp_token_position); ! static void cp_lexer_handle_pragma ! (cp_lexer *); static void cp_lexer_save_tokens (cp_lexer *); static void cp_lexer_commit_tokens (cp_lexer *); static void cp_lexer_rollback_tokens (cp_lexer *); ! #ifdef ENABLE_CHECKING static void cp_lexer_print_token (FILE *, cp_token *); ! static inline bool cp_lexer_debugging_p (cp_lexer *); static void cp_lexer_start_debugging (cp_lexer *) ATTRIBUTE_UNUSED; static void cp_lexer_stop_debugging (cp_lexer *) ATTRIBUTE_UNUSED; + #else + /* If we define cp_lexer_debug_stream to NULL it will provoke warnings + about passing NULL to functions that require non-NULL arguments + (fputs, fprintf). It will never be used, so all we need is a value + of the right type that's guaranteed not to be NULL. */ + #define cp_lexer_debug_stream stdout + #define cp_lexer_print_token(str, tok) (void) 0 + #define cp_lexer_debugging_p(lexer) 0 + #endif /* ENABLE_CHECKING */ ! static cp_token_cache *cp_token_cache_new ! (cp_token *, cp_token *); ! /* Manifest constants. */ ! #define CP_LEXER_BUFFER_SIZE 10000 ! #define CP_SAVED_TOKEN_STACK 5 /* A token type for keywords, as opposed to ordinary identifiers. */ #define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1)) *************** static void cp_lexer_stop_debugging *** 286,298 **** #define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1)) /* A token type for tokens that are not tokens at all; these are used ! to mark the end of a token block. */ ! #define CPP_NONE (CPP_NESTED_NAME_SPECIFIER + 1) /* Variables. */ /* The stream to which debugging output should be written. */ static FILE *cp_lexer_debug_stream; /* Create a new main C++ lexer, the lexer that gets tokens from the preprocessor. */ --- 211,229 ---- #define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1)) /* A token type for tokens that are not tokens at all; these are used ! to represent slots in the array where there used to be a token ! that has now been deleted. */ ! #define CPP_PURGED ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1)) ! ! /* The number of token types, including C++-specific ones. */ ! #define N_CP_TTYPES ((int) (CPP_PURGED + 1)) /* Variables. */ + #ifdef ENABLE_CHECKING /* The stream to which debugging output should be written. */ static FILE *cp_lexer_debug_stream; + #endif /* ENABLE_CHECKING */ /* Create a new main C++ lexer, the lexer that gets tokens from the preprocessor. */ *************** static FILE *cp_lexer_debug_stream; *** 300,625 **** static cp_lexer * cp_lexer_new_main (void) { - cp_lexer *lexer; cp_token first_token; /* It's possible that lexing the first token will load a PCH file, which is a GC collection point. So we have to grab the first ! token before allocating any memory. */ cp_lexer_get_preprocessor_token (NULL, &first_token); - c_common_no_more_pch (); ! /* Allocate the memory. */ ! lexer = ggc_alloc_cleared (sizeof (cp_lexer)); ! /* Create the circular buffer. */ ! lexer->buffer = ggc_calloc (CP_TOKEN_BUFFER_SIZE, sizeof (cp_token)); ! lexer->buffer_end = lexer->buffer + CP_TOKEN_BUFFER_SIZE; ! /* There is one token in the buffer. */ ! lexer->last_token = lexer->buffer + 1; ! lexer->first_token = lexer->buffer; ! lexer->next_token = lexer->buffer; ! memcpy (lexer->buffer, &first_token, sizeof (cp_token)); ! /* This lexer obtains more tokens by calling c_lex. */ ! lexer->main_lexer_p = true; ! /* Create the SAVED_TOKENS stack. */ ! VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens"); ! /* Create the STRINGS array. */ ! VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings"); ! /* Assume we are not debugging. */ ! lexer->debugging_p = false; return lexer; } ! /* Create a new lexer whose token stream is primed with the TOKENS. ! When these tokens are exhausted, no new tokens will be read. */ static cp_lexer * ! cp_lexer_new_from_tokens (cp_token_cache *tokens) { ! cp_lexer *lexer; ! cp_token *token; ! cp_token_block *block; ! ptrdiff_t num_tokens; ! ! /* Allocate the memory. */ ! lexer = ggc_alloc_cleared (sizeof (cp_lexer)); ! ! /* Create a new buffer, appropriately sized. */ ! num_tokens = 0; ! for (block = tokens->first; block != NULL; block = block->next) ! num_tokens += block->num_tokens; ! lexer->buffer = ggc_alloc (num_tokens * sizeof (cp_token)); ! lexer->buffer_end = lexer->buffer + num_tokens; ! ! /* Install the tokens. */ ! token = lexer->buffer; ! for (block = tokens->first; block != NULL; block = block->next) ! { ! memcpy (token, block->tokens, block->num_tokens * sizeof (cp_token)); ! token += block->num_tokens; ! } ! ! /* The FIRST_TOKEN is the beginning of the buffer. */ ! lexer->first_token = lexer->buffer; ! /* The next available token is also at the beginning of the buffer. */ ! lexer->next_token = lexer->buffer; ! /* The buffer is full. */ ! lexer->last_token = lexer->first_token; ! ! /* This lexer doesn't obtain more tokens. */ ! lexer->main_lexer_p = false; ! /* Create the SAVED_TOKENS stack. */ ! VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens"); ! /* Create the STRINGS array. */ ! VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings"); ! /* Assume we are not debugging. */ lexer->debugging_p = false; return lexer; } ! /* Returns nonzero if debugging information should be output. */ ! static inline bool ! cp_lexer_debugging_p (cp_lexer *lexer) { ! return lexer->debugging_p; } ! /* Set the current source position from the information stored in ! TOKEN. */ ! static inline void ! cp_lexer_set_source_position_from_token (cp_lexer *lexer ATTRIBUTE_UNUSED , ! const cp_token *token) ! { ! /* Ideally, the source position information would not be a global ! variable, but it is. */ ! /* Update the line number. */ ! if (token->type != CPP_EOF) ! input_location = token->location; } ! /* TOKEN points into the circular token buffer. Return a pointer to ! the next token in the buffer. */ ! static inline cp_token * ! cp_lexer_next_token (cp_lexer* lexer, cp_token* token) { ! token++; ! if (token == lexer->buffer_end) ! token = lexer->buffer; ! return token; } - /* TOKEN points into the circular token buffer. Return a pointer to - the previous token in the buffer. */ - static inline cp_token * ! cp_lexer_prev_token (cp_lexer* lexer, cp_token* token) { ! if (token == lexer->buffer) ! token = lexer->buffer_end; ! return token - 1; } /* nonzero if we are presently saving tokens. */ ! static int cp_lexer_saving_tokens (const cp_lexer* lexer) { ! return VARRAY_ACTIVE_SIZE (lexer->saved_tokens) != 0; ! } ! ! /* Return a pointer to the token that is N tokens beyond TOKEN in the ! buffer. */ ! ! static cp_token * ! cp_lexer_advance_token (cp_lexer *lexer, cp_token *token, ptrdiff_t n) ! { ! token += n; ! if (token >= lexer->buffer_end) ! token = lexer->buffer + (token - lexer->buffer_end); ! return token; ! } ! ! /* Returns the number of times that START would have to be incremented ! to reach FINISH. If START and FINISH are the same, returns zero. */ ! ! static ptrdiff_t ! cp_lexer_token_difference (cp_lexer* lexer, cp_token* start, cp_token* finish) ! { ! if (finish >= start) ! return finish - start; ! else ! return ((lexer->buffer_end - lexer->buffer) ! - (start - finish)); ! } ! ! /* Obtain another token from the C preprocessor and add it to the ! token buffer. Returns the newly read token. */ ! ! static cp_token * ! cp_lexer_read_token (cp_lexer* lexer) ! { ! cp_token *token; ! ! /* Make sure there is room in the buffer. */ ! cp_lexer_maybe_grow_buffer (lexer); ! ! /* If there weren't any tokens, then this one will be the first. */ ! if (!lexer->first_token) ! lexer->first_token = lexer->last_token; ! /* Similarly, if there were no available tokens, there is one now. */ ! if (!lexer->next_token) ! lexer->next_token = lexer->last_token; ! ! /* Figure out where we're going to store the new token. */ ! token = lexer->last_token; ! ! /* Get a new token from the preprocessor. */ ! cp_lexer_get_preprocessor_token (lexer, token); ! ! /* Increment LAST_TOKEN. */ ! lexer->last_token = cp_lexer_next_token (lexer, token); ! ! /* Strings should have type `const char []'. Right now, we will ! have an ARRAY_TYPE that is constant rather than an array of ! constant elements. ! FIXME: Make fix_string_type get this right in the first place. */ ! if ((token->type == CPP_STRING || token->type == CPP_WSTRING) ! && flag_const_strings) ! { ! tree type; ! ! /* Get the current type. It will be an ARRAY_TYPE. */ ! type = TREE_TYPE (token->value); ! /* Use build_cplus_array_type to rebuild the array, thereby ! getting the right type. */ ! type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type)); ! /* Reset the type of the token. */ ! TREE_TYPE (token->value) = type; ! } ! ! return token; } ! /* If the circular buffer is full, make it bigger. */ static void - cp_lexer_maybe_grow_buffer (cp_lexer* lexer) - { - /* If the buffer is full, enlarge it. */ - if (lexer->last_token == lexer->first_token) - { - cp_token *new_buffer; - cp_token *old_buffer; - cp_token *new_first_token; - ptrdiff_t buffer_length; - size_t num_tokens_to_copy; - - /* Remember the current buffer pointer. It will become invalid, - but we will need to do pointer arithmetic involving this - value. */ - old_buffer = lexer->buffer; - /* Compute the current buffer size. */ - buffer_length = lexer->buffer_end - lexer->buffer; - /* Allocate a buffer twice as big. */ - new_buffer = ggc_realloc (lexer->buffer, - 2 * buffer_length * sizeof (cp_token)); - - /* Because the buffer is circular, logically consecutive tokens - are not necessarily placed consecutively in memory. - Therefore, we must keep move the tokens that were before - FIRST_TOKEN to the second half of the newly allocated - buffer. */ - num_tokens_to_copy = (lexer->first_token - old_buffer); - memcpy (new_buffer + buffer_length, - new_buffer, - num_tokens_to_copy * sizeof (cp_token)); - /* Clear the rest of the buffer. We never look at this storage, - but the garbage collector may. */ - memset (new_buffer + buffer_length + num_tokens_to_copy, 0, - (buffer_length - num_tokens_to_copy) * sizeof (cp_token)); - - /* Now recompute all of the buffer pointers. */ - new_first_token - = new_buffer + (lexer->first_token - old_buffer); - if (lexer->next_token != NULL) - { - ptrdiff_t next_token_delta; - - if (lexer->next_token > lexer->first_token) - next_token_delta = lexer->next_token - lexer->first_token; - else - next_token_delta = - buffer_length - (lexer->first_token - lexer->next_token); - lexer->next_token = new_first_token + next_token_delta; - } - lexer->last_token = new_first_token + buffer_length; - lexer->buffer = new_buffer; - lexer->buffer_end = new_buffer + buffer_length * 2; - lexer->first_token = new_first_token; - } - } - - /* Store the next token from the preprocessor in *TOKEN. */ - - static void cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , cp_token *token) { ! bool done; ! ! /* If this not the main lexer, return a terminating CPP_EOF token. */ ! if (lexer != NULL && !lexer->main_lexer_p) ! { ! token->type = CPP_EOF; ! token->location.line = 0; ! token->location.file = NULL; ! token->value = NULL_TREE; ! token->keyword = RID_MAX; ! ! return; ! } ! ! done = false; ! /* Keep going until we get a token we like. */ ! while (!done) ! { ! /* Get a new token from the preprocessor. */ ! token->type = c_lex_with_flags (&token->value, &token->flags); ! /* Issue messages about tokens we cannot process. */ ! switch (token->type) ! { ! case CPP_ATSIGN: ! case CPP_HASH: ! case CPP_PASTE: ! error ("invalid token"); ! break; ! default: ! /* This is a good token, so we exit the loop. */ ! done = true; ! break; ! } ! } ! /* Now we've got our token. */ token->location = input_location; /* Check to see if this token is a keyword. */ ! if (token->type == CPP_NAME && C_IS_RESERVED_WORD (token->value)) { /* Mark this token as a keyword. */ --- 231,398 ---- static cp_lexer * cp_lexer_new_main (void) { cp_token first_token; + cp_lexer *lexer; + cp_token *pos; + size_t alloc; + size_t space; + cp_token *buffer; /* It's possible that lexing the first token will load a PCH file, which is a GC collection point. So we have to grab the first ! token before allocating any memory. Pragmas must not be deferred ! as -fpch-preprocess can generate a pragma to load the PCH file in ! the preprocessed output used by -save-temps. */ cp_lexer_get_preprocessor_token (NULL, &first_token); ! /* Tell cpplib we want CPP_PRAGMA tokens. */ ! cpp_get_options (parse_in)->defer_pragmas = true; ! /* Tell c_lex not to merge string constants. */ ! c_lex_return_raw_strings = true; ! c_common_no_more_pch (); ! /* Allocate the memory. */ ! lexer = GGC_CNEW (cp_lexer); ! #ifdef ENABLE_CHECKING ! /* Initially we are not debugging. */ ! lexer->debugging_p = false; ! #endif /* ENABLE_CHECKING */ ! lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK); ! ! /* Create the buffer. */ ! alloc = CP_LEXER_BUFFER_SIZE; ! buffer = ggc_alloc (alloc * sizeof (cp_token)); ! ! /* Put the first token in the buffer. */ ! space = alloc; ! pos = buffer; ! *pos = first_token; ! /* Get the remaining tokens from the preprocessor. */ ! while (pos->type != CPP_EOF) ! { ! pos++; ! if (!--space) ! { ! space = alloc; ! alloc *= 2; ! buffer = ggc_realloc (buffer, alloc * sizeof (cp_token)); ! pos = buffer + space; ! } ! cp_lexer_get_preprocessor_token (lexer, pos); ! } ! lexer->buffer = buffer; ! lexer->buffer_length = alloc - space; ! lexer->last_token = pos; ! lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token; ! /* Pragma processing (via cpp_handle_deferred_pragma) may result in ! direct calls to c_lex. Those callers all expect c_lex to do ! string constant concatenation. */ ! c_lex_return_raw_strings = false; + gcc_assert (lexer->next_token->type != CPP_PURGED); return lexer; } ! /* Create a new lexer whose token stream is primed with the tokens in ! CACHE. When these tokens are exhausted, no new tokens will be read. */ static cp_lexer * ! cp_lexer_new_from_tokens (cp_token_cache *cache) { ! cp_token *first = cache->first; ! cp_token *last = cache->last; ! cp_lexer *lexer = GGC_CNEW (cp_lexer); ! /* We do not own the buffer. */ ! lexer->buffer = NULL; ! lexer->buffer_length = 0; ! lexer->next_token = first == last ? (cp_token *)&eof_token : first; ! lexer->last_token = last; ! lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK); ! #ifdef ENABLE_CHECKING ! /* Initially we are not debugging. */ lexer->debugging_p = false; + #endif + gcc_assert (lexer->next_token->type != CPP_PURGED); return lexer; } ! /* Frees all resources associated with LEXER. */ ! static void ! cp_lexer_destroy (cp_lexer *lexer) { ! if (lexer->buffer) ! ggc_free (lexer->buffer); ! VEC_free (cp_token_position, lexer->saved_tokens); ! ggc_free (lexer); } ! /* Returns nonzero if debugging information should be output. */ ! #ifdef ENABLE_CHECKING ! static inline bool ! cp_lexer_debugging_p (cp_lexer *lexer) ! { ! return lexer->debugging_p; } ! #endif /* ENABLE_CHECKING */ ! static inline cp_token_position ! cp_lexer_token_position (cp_lexer *lexer, bool previous_p) { ! gcc_assert (!previous_p || lexer->next_token != &eof_token); ! ! return lexer->next_token - previous_p; } static inline cp_token * ! cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos) { ! return pos; } /* nonzero if we are presently saving tokens. */ ! static inline int cp_lexer_saving_tokens (const cp_lexer* lexer) { ! return VEC_length (cp_token_position, lexer->saved_tokens) != 0; } ! /* Store the next token from the preprocessor in *TOKEN. Return true ! if we reach EOF. */ static void cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , cp_token *token) { ! static int is_extern_c = 0; ! /* Get a new token from the preprocessor. */ ! token->type = c_lex_with_flags (&token->value, &token->flags); token->location = input_location; + token->in_system_header = in_system_header; + + /* On some systems, some header files are surrounded by an + implicit extern "C" block. Set a flag in the token if it + comes from such a header. */ + is_extern_c += pending_lang_change; + pending_lang_change = 0; + token->implicit_extern_c = is_extern_c > 0; /* Check to see if this token is a keyword. */ ! if (token->type == CPP_NAME && C_IS_RESERVED_WORD (token->value)) { /* Mark this token as a keyword. */ *************** cp_lexer_get_preprocessor_token (cp_lexe *** 636,682 **** token->keyword = RID_MAX; } /* Return a pointer to the next token in the token stream, but do not consume it. */ ! static cp_token * ! cp_lexer_peek_token (cp_lexer* lexer) { - cp_token *token; - - /* If there are no tokens, read one now. */ - if (!lexer->next_token) - cp_lexer_read_token (lexer); - - /* Provide debugging output. */ if (cp_lexer_debugging_p (lexer)) { ! fprintf (cp_lexer_debug_stream, "cp_lexer: peeking at token: "); cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token); ! fprintf (cp_lexer_debug_stream, "\n"); } ! ! token = lexer->next_token; ! cp_lexer_set_source_position_from_token (lexer, token); ! return token; } /* Return true if the next token has the indicated TYPE. */ ! static bool cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type) { ! cp_token *token; ! ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (lexer); ! /* Check to see if it has the indicated TYPE. */ ! return token->type == type; } /* Return true if the next token does not have the indicated TYPE. */ ! static bool cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type) { return !cp_lexer_next_token_is (lexer, type); --- 409,451 ---- token->keyword = RID_MAX; } + /* Update the globals input_location and in_system_header from TOKEN. */ + static inline void + cp_lexer_set_source_position_from_token (cp_token *token) + { + if (token->type != CPP_EOF) + { + input_location = token->location; + in_system_header = token->in_system_header; + } + } + /* Return a pointer to the next token in the token stream, but do not consume it. */ ! static inline cp_token * ! cp_lexer_peek_token (cp_lexer *lexer) { if (cp_lexer_debugging_p (lexer)) { ! fputs ("cp_lexer: peeking at token: ", cp_lexer_debug_stream); cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token); ! putc ('\n', cp_lexer_debug_stream); } ! return lexer->next_token; } /* Return true if the next token has the indicated TYPE. */ ! static inline bool cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type) { ! return cp_lexer_peek_token (lexer)->type == type; } /* Return true if the next token does not have the indicated TYPE. */ ! static inline bool cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type) { return !cp_lexer_next_token_is (lexer, type); *************** cp_lexer_next_token_is_not (cp_lexer* le *** 684,690 **** /* Return true if the next token is the indicated KEYWORD. */ ! static bool cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) { cp_token *token; --- 453,459 ---- /* Return true if the next token is the indicated KEYWORD. */ ! static inline bool cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) { cp_token *token; *************** cp_lexer_next_token_is_keyword (cp_lexer *** 696,702 **** } /* Return a pointer to the Nth token in the token stream. If N is 1, ! then this is precisely equivalent to cp_lexer_peek_token. */ static cp_token * cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) --- 465,474 ---- } /* Return a pointer to the Nth token in the token stream. If N is 1, ! then this is precisely equivalent to cp_lexer_peek_token (except ! that it is not inline). One would like to disallow that case, but ! there is one case (cp_parser_nth_token_starts_template_id) where ! the caller passes a variable for N and it might be 1. */ static cp_token * cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) *************** cp_lexer_peek_nth_token (cp_lexer* lexer *** 704,842 **** cp_token *token; /* N is 1-based, not zero-based. */ ! my_friendly_assert (n > 0, 20000224); ! /* Skip ahead from NEXT_TOKEN, reading more tokens as necessary. */ token = lexer->next_token; ! /* If there are no tokens in the buffer, get one now. */ ! if (!token) { ! cp_lexer_read_token (lexer); ! token = lexer->next_token; } ! /* Now, read tokens until we have enough. */ ! while (--n > 0) { ! /* Advance to the next token. */ ! token = cp_lexer_next_token (lexer, token); ! /* If that's all the tokens we have, read a new one. */ ! if (token == lexer->last_token) ! token = cp_lexer_read_token (lexer); } return token; } ! /* Consume the next token. The pointer returned is valid only until ! another token is read. Callers should preserve copy the token ! explicitly if they will need its value for a longer period of ! time. */ static cp_token * cp_lexer_consume_token (cp_lexer* lexer) { ! cp_token *token; ! ! /* If there are no tokens, read one now. */ ! if (!lexer->next_token) ! cp_lexer_read_token (lexer); ! ! /* Remember the token we'll be returning. */ ! token = lexer->next_token; ! ! /* Increment NEXT_TOKEN. */ ! lexer->next_token = cp_lexer_next_token (lexer, ! lexer->next_token); ! /* Check to see if we're all out of tokens. */ ! if (lexer->next_token == lexer->last_token) ! lexer->next_token = NULL; ! /* If we're not saving tokens, then move FIRST_TOKEN too. */ ! if (!cp_lexer_saving_tokens (lexer)) { ! /* If there are no tokens available, set FIRST_TOKEN to NULL. */ ! if (!lexer->next_token) ! lexer->first_token = NULL; ! else ! lexer->first_token = lexer->next_token; } ! /* Provide debugging output. */ if (cp_lexer_debugging_p (lexer)) { ! fprintf (cp_lexer_debug_stream, "cp_lexer: consuming token: "); cp_lexer_print_token (cp_lexer_debug_stream, token); ! fprintf (cp_lexer_debug_stream, "\n"); } ! return token; } ! /* Permanently remove the next token from the token stream. There ! must be a valid next token already; this token never reads ! additional tokens from the preprocessor. */ static void cp_lexer_purge_token (cp_lexer *lexer) { ! cp_token *token; ! cp_token *next_token; ! token = lexer->next_token; ! while (true) { ! next_token = cp_lexer_next_token (lexer, token); ! if (next_token == lexer->last_token) ! break; ! *token = *next_token; ! token = next_token; } ! ! lexer->last_token = token; ! /* The token purged may have been the only token remaining; if so, ! clear NEXT_TOKEN. */ ! if (lexer->next_token == token) ! lexer->next_token = NULL; } ! /* Permanently remove all tokens after TOKEN, up to, but not including, the token that will be returned next by cp_lexer_peek_token. */ static void ! cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *token) { ! cp_token *peek; ! cp_token *t1; ! cp_token *t2; ! if (lexer->next_token) ! { ! /* Copy the tokens that have not yet been read to the location ! immediately following TOKEN. */ ! t1 = cp_lexer_next_token (lexer, token); ! t2 = peek = cp_lexer_peek_token (lexer); ! /* Move tokens into the vacant area between TOKEN and PEEK. */ ! while (t2 != lexer->last_token) ! { ! *t1 = *t2; ! t1 = cp_lexer_next_token (lexer, t1); ! t2 = cp_lexer_next_token (lexer, t2); ! } ! /* Now, the next available token is right after TOKEN. */ ! lexer->next_token = cp_lexer_next_token (lexer, token); ! /* And the last token is wherever we ended up. */ ! lexer->last_token = t1; ! } ! else { ! /* There are no tokens in the buffer, so there is nothing to ! copy. The last token in the buffer is TOKEN itself. */ ! lexer->last_token = cp_lexer_next_token (lexer, token); } } /* Begin saving tokens. All tokens consumed after this point will be preserved. */ --- 476,616 ---- cp_token *token; /* N is 1-based, not zero-based. */ ! gcc_assert (n > 0 && lexer->next_token != &eof_token); ! if (cp_lexer_debugging_p (lexer)) ! fprintf (cp_lexer_debug_stream, ! "cp_lexer: peeking ahead %ld at token: ", (long)n); ! ! --n; token = lexer->next_token; ! while (n != 0) { ! ++token; ! if (token == lexer->last_token) ! { ! token = (cp_token *)&eof_token; ! break; ! } ! ! if (token->type != CPP_PURGED) ! --n; } ! if (cp_lexer_debugging_p (lexer)) { ! cp_lexer_print_token (cp_lexer_debug_stream, token); ! putc ('\n', cp_lexer_debug_stream); } return token; } ! /* Return the next token, and advance the lexer's next_token pointer ! to point to the next non-purged token. */ static cp_token * cp_lexer_consume_token (cp_lexer* lexer) { ! cp_token *token = lexer->next_token; ! gcc_assert (token != &eof_token); ! ! do { ! lexer->next_token++; ! if (lexer->next_token == lexer->last_token) ! { ! lexer->next_token = (cp_token *)&eof_token; ! break; ! } ! } ! while (lexer->next_token->type == CPP_PURGED); ! ! cp_lexer_set_source_position_from_token (token); ! /* Provide debugging output. */ if (cp_lexer_debugging_p (lexer)) { ! fputs ("cp_lexer: consuming token: ", cp_lexer_debug_stream); cp_lexer_print_token (cp_lexer_debug_stream, token); ! putc ('\n', cp_lexer_debug_stream); } ! return token; } ! /* Permanently remove the next token from the token stream, and ! advance the next_token pointer to refer to the next non-purged ! token. */ static void cp_lexer_purge_token (cp_lexer *lexer) { ! cp_token *tok = lexer->next_token; ! ! gcc_assert (tok != &eof_token); ! tok->type = CPP_PURGED; ! tok->location = UNKNOWN_LOCATION; ! tok->value = NULL_TREE; ! tok->keyword = RID_MAX; ! do { ! tok++; ! if (tok == lexer->last_token) ! { ! tok = (cp_token *)&eof_token; ! break; ! } } ! while (tok->type == CPP_PURGED); ! lexer->next_token = tok; } ! /* Permanently remove all tokens after TOK, up to, but not including, the token that will be returned next by cp_lexer_peek_token. */ static void ! cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok) { ! cp_token *peek = lexer->next_token; ! if (peek == &eof_token) ! peek = lexer->last_token; ! ! gcc_assert (tok < peek); ! ! for ( tok += 1; tok != peek; tok += 1) { ! tok->type = CPP_PURGED; ! tok->location = UNKNOWN_LOCATION; ! tok->value = NULL_TREE; ! tok->keyword = RID_MAX; } } + /* Consume and handle a pragma token. */ + static void + cp_lexer_handle_pragma (cp_lexer *lexer) + { + cpp_string s; + cp_token *token = cp_lexer_consume_token (lexer); + gcc_assert (token->type == CPP_PRAGMA); + gcc_assert (token->value); + + s.len = TREE_STRING_LENGTH (token->value); + s.text = (const unsigned char *) TREE_STRING_POINTER (token->value); + + cpp_handle_deferred_pragma (parse_in, &s); + + /* Clearing token->value here means that we will get an ICE if we + try to process this #pragma again (which should be impossible). */ + token->value = NULL; + } + /* Begin saving tokens. All tokens consumed after this point will be preserved. */ *************** cp_lexer_save_tokens (cp_lexer* lexer) *** 847,861 **** if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: saving tokens\n"); ! /* Make sure that LEXER->NEXT_TOKEN is non-NULL so that we can ! restore the tokens if required. */ ! if (!lexer->next_token) ! cp_lexer_read_token (lexer); ! ! VARRAY_PUSH_INT (lexer->saved_tokens, ! cp_lexer_token_difference (lexer, ! lexer->first_token, ! lexer->next_token)); } /* Commit to the portion of the token stream most recently saved. */ --- 621,627 ---- if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: saving tokens\n"); ! VEC_safe_push (cp_token_position, lexer->saved_tokens, lexer->next_token); } /* Commit to the portion of the token stream most recently saved. */ *************** cp_lexer_commit_tokens (cp_lexer* lexer) *** 867,873 **** if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: committing tokens\n"); ! VARRAY_POP (lexer->saved_tokens); } /* Return all tokens saved since the last call to cp_lexer_save_tokens --- 633,639 ---- if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: committing tokens\n"); ! VEC_pop (cp_token_position, lexer->saved_tokens); } /* Return all tokens saved since the last call to cp_lexer_save_tokens *************** cp_lexer_commit_tokens (cp_lexer* lexer) *** 876,971 **** static void cp_lexer_rollback_tokens (cp_lexer* lexer) { - size_t delta; - /* Provide debugging output. */ if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: restoring tokens\n"); ! /* Find the token that was the NEXT_TOKEN when we started saving ! tokens. */ ! delta = VARRAY_TOP_INT(lexer->saved_tokens); ! /* Make it the next token again now. */ ! lexer->next_token = cp_lexer_advance_token (lexer, ! lexer->first_token, ! delta); ! /* It might be the case that there were no tokens when we started ! saving tokens, but that there are some tokens now. */ ! if (!lexer->next_token && lexer->first_token) ! lexer->next_token = lexer->first_token; ! ! /* Stop saving tokens. */ ! VARRAY_POP (lexer->saved_tokens); } /* Print a representation of the TOKEN on the STREAM. */ static void ! cp_lexer_print_token (FILE * stream, cp_token* token) { ! const char *token_type = NULL; ! /* Figure out what kind of token this is. */ switch (token->type) { ! case CPP_EQ: ! token_type = "EQ"; ! break; ! ! case CPP_COMMA: ! token_type = "COMMA"; ! break; ! ! case CPP_OPEN_PAREN: ! token_type = "OPEN_PAREN"; ! break; ! ! case CPP_CLOSE_PAREN: ! token_type = "CLOSE_PAREN"; ! break; ! ! case CPP_OPEN_BRACE: ! token_type = "OPEN_BRACE"; ! break; ! ! case CPP_CLOSE_BRACE: ! token_type = "CLOSE_BRACE"; ! break; ! ! case CPP_SEMICOLON: ! token_type = "SEMICOLON"; ! break; ! case CPP_NAME: ! token_type = "NAME"; ! break; ! ! case CPP_EOF: ! token_type = "EOF"; break; ! case CPP_KEYWORD: ! token_type = "keyword"; break; - /* This is not a token that we know how to handle yet. */ default: break; } - - /* If we have a name for the token, print it out. Otherwise, we - simply give the numeric code. */ - if (token_type) - fprintf (stream, "%s", token_type); - else - fprintf (stream, "%d", token->type); - /* And, for an identifier, print the identifier name. */ - if (token->type == CPP_NAME - /* Some keywords have a value that is not an IDENTIFIER_NODE. - For example, `struct' is mapped to an INTEGER_CST. */ - || (token->type == CPP_KEYWORD - && TREE_CODE (token->value) == IDENTIFIER_NODE)) - fprintf (stream, " %s", IDENTIFIER_POINTER (token->value)); } /* Start emitting debugging information. */ --- 642,704 ---- static void cp_lexer_rollback_tokens (cp_lexer* lexer) { /* Provide debugging output. */ if (cp_lexer_debugging_p (lexer)) fprintf (cp_lexer_debug_stream, "cp_lexer: restoring tokens\n"); ! lexer->next_token = VEC_pop (cp_token_position, lexer->saved_tokens); } /* Print a representation of the TOKEN on the STREAM. */ + #ifdef ENABLE_CHECKING + static void ! cp_lexer_print_token (FILE * stream, cp_token *token) { ! /* We don't use cpp_type2name here because the parser defines ! a few tokens of its own. */ ! static const char *const token_names[] = { ! /* cpplib-defined token types */ ! #define OP(e, s) #e, ! #define TK(e, s) #e, ! TTYPE_TABLE ! #undef OP ! #undef TK ! /* C++ parser token types - see "Manifest constants", above. */ ! "KEYWORD", ! "TEMPLATE_ID", ! "NESTED_NAME_SPECIFIER", ! "PURGED" ! }; ! ! /* If we have a name for the token, print it out. Otherwise, we ! simply give the numeric code. */ ! gcc_assert (token->type < ARRAY_SIZE(token_names)); ! fputs (token_names[token->type], stream); ! /* For some tokens, print the associated data. */ switch (token->type) { ! case CPP_KEYWORD: ! /* Some keywords have a value that is not an IDENTIFIER_NODE. ! For example, `struct' is mapped to an INTEGER_CST. */ ! if (TREE_CODE (token->value) != IDENTIFIER_NODE) ! break; ! /* else fall through */ case CPP_NAME: ! fputs (IDENTIFIER_POINTER (token->value), stream); break; ! case CPP_STRING: ! case CPP_WSTRING: ! case CPP_PRAGMA: ! fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value)); break; default: break; } } /* Start emitting debugging information. */ *************** cp_lexer_print_token (FILE * stream, cp_ *** 973,990 **** static void cp_lexer_start_debugging (cp_lexer* lexer) { ! ++lexer->debugging_p; } ! /* Stop emitting debugging information. */ static void cp_lexer_stop_debugging (cp_lexer* lexer) { ! --lexer->debugging_p; } /* The parser. */ /* Overview --- 706,941 ---- static void cp_lexer_start_debugging (cp_lexer* lexer) { ! lexer->debugging_p = true; } ! /* Stop emitting debugging information. */ static void cp_lexer_stop_debugging (cp_lexer* lexer) { ! lexer->debugging_p = false; ! } ! ! #endif /* ENABLE_CHECKING */ ! ! /* Create a new cp_token_cache, representing a range of tokens. */ ! ! static cp_token_cache * ! cp_token_cache_new (cp_token *first, cp_token *last) ! { ! cp_token_cache *cache = GGC_NEW (cp_token_cache); ! cache->first = first; ! cache->last = last; ! return cache; } + /* Decl-specifiers. */ + + static void clear_decl_specs + (cp_decl_specifier_seq *); + + /* Set *DECL_SPECS to represent an empty decl-specifier-seq. */ + + static void + clear_decl_specs (cp_decl_specifier_seq *decl_specs) + { + memset (decl_specs, 0, sizeof (cp_decl_specifier_seq)); + } + + /* Declarators. */ + + /* Nothing other than the parser should be creating declarators; + declarators are a semi-syntactic representation of C++ entities. + Other parts of the front end that need to create entities (like + VAR_DECLs or FUNCTION_DECLs) should do that directly. */ + + static cp_declarator *make_call_declarator + (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree); + static cp_declarator *make_array_declarator + (cp_declarator *, tree); + static cp_declarator *make_pointer_declarator + (cp_cv_quals, cp_declarator *); + static cp_declarator *make_reference_declarator + (cp_cv_quals, cp_declarator *); + static cp_parameter_declarator *make_parameter_declarator + (cp_decl_specifier_seq *, cp_declarator *, tree); + static cp_declarator *make_ptrmem_declarator + (cp_cv_quals, tree, cp_declarator *); + + cp_declarator *cp_error_declarator; + + /* The obstack on which declarators and related data structures are + allocated. */ + static struct obstack declarator_obstack; + + /* Alloc BYTES from the declarator memory pool. */ + + static inline void * + alloc_declarator (size_t bytes) + { + return obstack_alloc (&declarator_obstack, bytes); + } + + /* Allocate a declarator of the indicated KIND. Clear fields that are + common to all declarators. */ + + static cp_declarator * + make_declarator (cp_declarator_kind kind) + { + cp_declarator *declarator; + + declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator)); + declarator->kind = kind; + declarator->attributes = NULL_TREE; + declarator->declarator = NULL; + + return declarator; + } + + /* Make a declarator for a generalized identifier. If non-NULL, the + identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is + just UNQUALIFIED_NAME. */ + + static cp_declarator * + make_id_declarator (tree qualifying_scope, tree unqualified_name) + { + cp_declarator *declarator; + + /* It is valid to write: + + class C { void f(); }; + typedef C D; + void D::f(); + + The standard is not clear about whether `typedef const C D' is + legal; as of 2002-09-15 the committee is considering that + question. EDG 3.0 allows that syntax. Therefore, we do as + well. */ + if (qualifying_scope && TYPE_P (qualifying_scope)) + qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope); + + declarator = make_declarator (cdk_id); + declarator->u.id.qualifying_scope = qualifying_scope; + declarator->u.id.unqualified_name = unqualified_name; + declarator->u.id.sfk = sfk_none; + + return declarator; + } + + /* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list + of modifiers such as const or volatile to apply to the pointer + type, represented as identifiers. */ + + cp_declarator * + make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) + { + cp_declarator *declarator; + + declarator = make_declarator (cdk_pointer); + declarator->declarator = target; + declarator->u.pointer.qualifiers = cv_qualifiers; + declarator->u.pointer.class_type = NULL_TREE; + + return declarator; + } + + /* Like make_pointer_declarator -- but for references. */ + + cp_declarator * + make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) + { + cp_declarator *declarator; + + declarator = make_declarator (cdk_reference); + declarator->declarator = target; + declarator->u.pointer.qualifiers = cv_qualifiers; + declarator->u.pointer.class_type = NULL_TREE; + + return declarator; + } + + /* Like make_pointer_declarator -- but for a pointer to a non-static + member of CLASS_TYPE. */ + + cp_declarator * + make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, + cp_declarator *pointee) + { + cp_declarator *declarator; + + declarator = make_declarator (cdk_ptrmem); + declarator->declarator = pointee; + declarator->u.pointer.qualifiers = cv_qualifiers; + declarator->u.pointer.class_type = class_type; + + return declarator; + } + + /* Make a declarator for the function given by TARGET, with the + indicated PARMS. The CV_QUALIFIERS aply to the function, as in + "const"-qualified member function. The EXCEPTION_SPECIFICATION + indicates what exceptions can be thrown. */ + + cp_declarator * + make_call_declarator (cp_declarator *target, + cp_parameter_declarator *parms, + cp_cv_quals cv_qualifiers, + tree exception_specification) + { + cp_declarator *declarator; + + declarator = make_declarator (cdk_function); + declarator->declarator = target; + declarator->u.function.parameters = parms; + declarator->u.function.qualifiers = cv_qualifiers; + declarator->u.function.exception_specification = exception_specification; + + return declarator; + } + + /* Make a declarator for an array of BOUNDS elements, each of which is + defined by ELEMENT. */ + + cp_declarator * + make_array_declarator (cp_declarator *element, tree bounds) + { + cp_declarator *declarator; + + declarator = make_declarator (cdk_array); + declarator->declarator = element; + declarator->u.array.bounds = bounds; + + return declarator; + } + + cp_parameter_declarator *no_parameters; + + /* Create a parameter declarator with the indicated DECL_SPECIFIERS, + DECLARATOR and DEFAULT_ARGUMENT. */ + + cp_parameter_declarator * + make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, + cp_declarator *declarator, + tree default_argument) + { + cp_parameter_declarator *parameter; + + parameter = ((cp_parameter_declarator *) + alloc_declarator (sizeof (cp_parameter_declarator))); + parameter->next = NULL; + if (decl_specifiers) + parameter->decl_specifiers = *decl_specifiers; + else + clear_decl_specs (¶meter->decl_specifiers); + parameter->declarator = declarator; + parameter->default_argument = default_argument; + parameter->ellipsis_p = false; + + return parameter; + } + /* The parser. */ /* Overview *************** cp_lexer_stop_debugging (cp_lexer* lexer *** 1000,1006 **** The parser invokes routines elsewhere in the compiler to perform semantic analysis and to build up the abstract syntax tree for the ! code processed. The parser (and the template instantiation code, which is, in a way, a close relative of parsing) are the only parts of the --- 951,957 ---- The parser invokes routines elsewhere in the compiler to perform semantic analysis and to build up the abstract syntax tree for the ! code processed. The parser (and the template instantiation code, which is, in a way, a close relative of parsing) are the only parts of the *************** cp_lexer_stop_debugging (cp_lexer* lexer *** 1013,1019 **** Methodology ----------- ! The parser is of the standard recursive-descent variety. Upcoming tokens in the token stream are examined in order to determine which production to use when parsing a non-terminal. Some C++ constructs --- 964,970 ---- Methodology ----------- ! The parser is of the standard recursive-descent variety. Upcoming tokens in the token stream are examined in order to determine which production to use when parsing a non-terminal. Some C++ constructs *************** cp_lexer_stop_debugging (cp_lexer* lexer *** 1033,1051 **** Future Improvements ------------------- - - The performance of the parser could probably be improved - substantially. Some possible improvements include: - - - The expression parser recurses through the various levels of - precedence as specified in the grammar, rather than using an - operator-precedence technique. Therefore, parsing a simple - identifier requires multiple recursive calls. ! - We could often eliminate the need to parse tentatively by ! looking ahead a little bit. In some places, this approach ! might not entirely eliminate the need to parse tentatively, but ! it might still speed up the average case. */ /* Flags that are passed to some parsing functions. These values can be bitwise-ored together. */ --- 984,995 ---- Future Improvements ------------------- ! The performance of the parser could probably be improved substantially. ! We could often eliminate the need to parse tentatively by looking ahead ! a little bit. In some places, this approach might not entirely eliminate ! the need to parse tentatively, but it might still speed up the average ! case. */ /* Flags that are passed to some parsing functions. These values can be bitwise-ored together. */ *************** typedef enum cp_parser_flags *** 1065,1071 **** typedef enum cp_parser_declarator_kind { ! /* We want an abstract declartor. */ CP_PARSER_DECLARATOR_ABSTRACT, /* We want a named declarator. */ CP_PARSER_DECLARATOR_NAMED, --- 1009,1015 ---- typedef enum cp_parser_declarator_kind { ! /* We want an abstract declarator. */ CP_PARSER_DECLARATOR_ABSTRACT, /* We want a named declarator. */ CP_PARSER_DECLARATOR_NAMED, *************** typedef enum cp_parser_declarator_kind *** 1073,1092 **** CP_PARSER_DECLARATOR_EITHER } cp_parser_declarator_kind; ! /* A mapping from a token type to a corresponding tree node type. */ ! typedef struct cp_parser_token_tree_map_node { ! /* The token type. */ ! ENUM_BITFIELD (cpp_ttype) token_type : 8; ! /* The corresponding tree code. */ ! ENUM_BITFIELD (tree_code) tree_type : 8; ! } cp_parser_token_tree_map_node; ! /* A complete map consists of several ordinary entries, followed by a ! terminator. The terminating entry has a token_type of CPP_EOF. */ ! typedef cp_parser_token_tree_map_node cp_parser_token_tree_map[]; /* The status of a tentative parse. */ --- 1017,1055 ---- CP_PARSER_DECLARATOR_EITHER } cp_parser_declarator_kind; ! /* The precedence values used to parse binary expressions. The minimum value ! of PREC must be 1, because zero is reserved to quickly discriminate ! binary operators from other tokens. */ ! enum cp_parser_prec { ! PREC_NOT_OPERATOR, ! PREC_LOGICAL_OR_EXPRESSION, ! PREC_LOGICAL_AND_EXPRESSION, ! PREC_INCLUSIVE_OR_EXPRESSION, ! PREC_EXCLUSIVE_OR_EXPRESSION, ! PREC_AND_EXPRESSION, ! PREC_EQUALITY_EXPRESSION, ! PREC_RELATIONAL_EXPRESSION, ! PREC_SHIFT_EXPRESSION, ! PREC_ADDITIVE_EXPRESSION, ! PREC_MULTIPLICATIVE_EXPRESSION, ! PREC_PM_EXPRESSION, ! NUM_PREC_VALUES = PREC_PM_EXPRESSION ! }; ! /* A mapping from a token type to a corresponding tree node type, with a ! precedence value. */ ! typedef struct cp_parser_binary_operations_map_node ! { ! /* The token type. */ ! enum cpp_ttype token_type; ! /* The corresponding tree code. */ ! enum tree_code tree_type; ! /* The precedence of this operator. */ ! enum cp_parser_prec prec; ! } cp_parser_binary_operations_map_node; /* The status of a tentative parse. */ *************** typedef enum cp_parser_status_kind *** 1101,1108 **** CP_PARSER_STATUS_KIND_COMMITTED } cp_parser_status_kind; ! /* Context that is saved and restored when parsing tentatively. */ typedef struct cp_parser_context GTY (()) { /* If this is a tentative parsing context, the status of the --- 1064,1083 ---- CP_PARSER_STATUS_KIND_COMMITTED } cp_parser_status_kind; ! typedef struct cp_parser_expression_stack_entry ! { ! tree lhs; ! enum tree_code tree_type; ! int prec; ! } cp_parser_expression_stack_entry; ! ! /* The stack for storing partial expressions. We only need NUM_PREC_VALUES ! entries because precedence levels on the stack are monotonically ! increasing. */ ! typedef struct cp_parser_expression_stack_entry ! cp_parser_expression_stack[NUM_PREC_VALUES]; + /* Context that is saved and restored when parsing tentatively. */ typedef struct cp_parser_context GTY (()) { /* If this is a tentative parsing context, the status of the *************** typedef struct cp_parser_context GTY (() *** 1113,1118 **** --- 1088,1094 ---- scope given by OBJECT_TYPE (the type of `x' or `*x') and also in the context of the containing expression. */ tree object_type; + /* The next parsing context in the stack. */ struct cp_parser_context *next; } cp_parser_context; *************** static cp_parser_context *cp_parser_cont *** 1126,1132 **** /* Class variables. */ ! static GTY((deletable (""))) cp_parser_context* cp_parser_context_free_list; /* Constructors and destructors. */ --- 1102,1152 ---- /* Class variables. */ ! static GTY((deletable)) cp_parser_context* cp_parser_context_free_list; ! ! /* The operator-precedence table used by cp_parser_binary_expression. ! Transformed into an associative array (binops_by_token) by ! cp_parser_new. */ ! ! static const cp_parser_binary_operations_map_node binops[] = { ! { CPP_DEREF_STAR, MEMBER_REF, PREC_PM_EXPRESSION }, ! { CPP_DOT_STAR, DOTSTAR_EXPR, PREC_PM_EXPRESSION }, ! ! { CPP_MULT, MULT_EXPR, PREC_MULTIPLICATIVE_EXPRESSION }, ! { CPP_DIV, TRUNC_DIV_EXPR, PREC_MULTIPLICATIVE_EXPRESSION }, ! { CPP_MOD, TRUNC_MOD_EXPR, PREC_MULTIPLICATIVE_EXPRESSION }, ! ! { CPP_PLUS, PLUS_EXPR, PREC_ADDITIVE_EXPRESSION }, ! { CPP_MINUS, MINUS_EXPR, PREC_ADDITIVE_EXPRESSION }, ! ! { CPP_LSHIFT, LSHIFT_EXPR, PREC_SHIFT_EXPRESSION }, ! { CPP_RSHIFT, RSHIFT_EXPR, PREC_SHIFT_EXPRESSION }, ! ! { CPP_LESS, LT_EXPR, PREC_RELATIONAL_EXPRESSION }, ! { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION }, ! { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION }, ! { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION }, ! { CPP_MIN, MIN_EXPR, PREC_RELATIONAL_EXPRESSION }, ! { CPP_MAX, MAX_EXPR, PREC_RELATIONAL_EXPRESSION }, ! ! { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION }, ! { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION }, ! ! { CPP_AND, BIT_AND_EXPR, PREC_AND_EXPRESSION }, ! ! { CPP_XOR, BIT_XOR_EXPR, PREC_EXCLUSIVE_OR_EXPRESSION }, ! ! { CPP_OR, BIT_IOR_EXPR, PREC_INCLUSIVE_OR_EXPRESSION }, ! ! { CPP_AND_AND, TRUTH_ANDIF_EXPR, PREC_LOGICAL_AND_EXPRESSION }, ! ! { CPP_OR_OR, TRUTH_ORIF_EXPR, PREC_LOGICAL_OR_EXPRESSION } ! }; ! ! /* The same as binops, but initialized by cp_parser_new so that ! binops_by_token[N].token_type == N. Used in cp_parser_binary_expression ! for speed. */ ! static cp_parser_binary_operations_map_node binops_by_token[N_CP_TTYPES]; /* Constructors and destructors. */ *************** cp_parser_context_new (cp_parser_context *** 1147,1153 **** memset (context, 0, sizeof (*context)); } else ! context = ggc_alloc_cleared (sizeof (cp_parser_context)); /* No errors have occurred yet in this context. */ context->status = CP_PARSER_STATUS_KIND_NO_ERROR; /* If this is not the bottomost context, copy information that we --- 1167,1174 ---- memset (context, 0, sizeof (*context)); } else ! context = GGC_CNEW (cp_parser_context); ! /* No errors have occurred yet in this context. */ context->status = CP_PARSER_STATUS_KIND_NO_ERROR; /* If this is not the bottomost context, copy information that we *************** typedef struct cp_parser GTY(()) *** 1174,1180 **** /* The scope in which names should be looked up. If NULL_TREE, then we look up names in the scope that is currently open in the source program. If non-NULL, this is either a TYPE or ! NAMESPACE_DECL for the scope in which we should look. This value is not cleared automatically after a name is looked up, so we must be careful to clear it before starting a new look --- 1195,1201 ---- /* The scope in which names should be looked up. If NULL_TREE, then we look up names in the scope that is currently open in the source program. If non-NULL, this is either a TYPE or ! NAMESPACE_DECL for the scope in which we should look. This value is not cleared automatically after a name is looked up, so we must be careful to clear it before starting a new look *************** typedef struct cp_parser GTY(()) *** 1188,1194 **** /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the last lookup took place. OBJECT_SCOPE is used if an expression like "x->y" or "x.y" was used; it gives the type of "*x" or "x", ! respectively. QUALIFYING_SCOPE is used for an expression of the form "X::Y"; it refers to X. */ tree object_scope; tree qualifying_scope; --- 1209,1215 ---- /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the last lookup took place. OBJECT_SCOPE is used if an expression like "x->y" or "x.y" was used; it gives the type of "*x" or "x", ! respectively. QUALIFYING_SCOPE is used for an expression of the form "X::Y"; it refers to X. */ tree object_scope; tree qualifying_scope; *************** typedef struct cp_parser GTY(()) *** 1217,1223 **** that starts at this point. FALSE if only a gnu extension makes them permissible. */ bool default_arg_ok_p; ! /* TRUE if we are parsing an integral constant-expression. See [expr.const] for a precise definition. */ bool integral_constant_expression_p; --- 1238,1244 ---- that starts at this point. FALSE if only a gnu extension makes them permissible. */ bool default_arg_ok_p; ! /* TRUE if we are parsing an integral constant-expression. See [expr.const] for a precise definition. */ bool integral_constant_expression_p; *************** typedef struct cp_parser GTY(()) *** 1232,1240 **** been seen that makes the expression non-constant. */ bool non_integral_constant_expression_p; - /* TRUE if we are parsing the argument to "__offsetof__". */ - bool in_offsetof_p; - /* TRUE if local variable names and `this' are forbidden in the current context. */ bool local_variables_forbidden_p; --- 1253,1258 ---- *************** typedef struct cp_parser GTY(()) *** 1264,1269 **** --- 1282,1295 ---- alternatives. */ bool in_type_id_in_expr_p; + /* TRUE if we are currently in a header file where declarations are + implicitly extern "C". */ + bool implicit_extern_c; + + /* TRUE if strings in expressions should be translated to the execution + character set. */ + bool translate_strings_p; + /* If non-NULL, then we are parsing a construct where new type definitions are not permitted. The string stored here will be issued as an error message if a type is defined. */ *************** typedef tree (*cp_parser_expression_fn) *** 1304,1310 **** static cp_parser *cp_parser_new (void); ! /* Routines to parse various constructs. Those that return `tree' will return the error_mark_node (rather than NULL_TREE) if a parse error occurs, unless otherwise noted. --- 1330,1336 ---- static cp_parser *cp_parser_new (void); ! /* Routines to parse various constructs. Those that return `tree' will return the error_mark_node (rather than NULL_TREE) if a parse error occurs, unless otherwise noted. *************** static cp_parser *cp_parser_new *** 1320,1325 **** --- 1346,1353 ---- static tree cp_parser_identifier (cp_parser *); + static tree cp_parser_string_literal + (cp_parser *, bool, bool); /* Basic concepts [gram.basic] */ *************** static bool cp_parser_translation_unit *** 1329,1335 **** /* Expressions [gram.expr] */ static tree cp_parser_primary_expression ! (cp_parser *, cp_id_kind *, tree *); static tree cp_parser_id_expression (cp_parser *, bool, bool, bool *, bool); static tree cp_parser_unqualified_id --- 1357,1363 ---- /* Expressions [gram.expr] */ static tree cp_parser_primary_expression ! (cp_parser *, bool, cp_id_kind *, tree *); static tree cp_parser_id_expression (cp_parser *, bool, bool, bool *, bool); static tree cp_parser_unqualified_id *************** static tree cp_parser_nested_name_specif *** 1341,1353 **** static tree cp_parser_class_or_namespace_name (cp_parser *, bool, bool, bool, bool, bool); static tree cp_parser_postfix_expression ! (cp_parser *, bool); static tree cp_parser_parenthesized_expression_list ! (cp_parser *, bool, bool *); static void cp_parser_pseudo_destructor_name (cp_parser *, tree *, tree *); static tree cp_parser_unary_expression ! (cp_parser *, bool); static enum tree_code cp_parser_unary_operator (cp_token *); static tree cp_parser_new_expression --- 1369,1385 ---- static tree cp_parser_class_or_namespace_name (cp_parser *, bool, bool, bool, bool, bool); static tree cp_parser_postfix_expression ! (cp_parser *, bool, bool); ! static tree cp_parser_postfix_open_square_expression ! (cp_parser *, tree, bool); ! static tree cp_parser_postfix_dot_deref_expression ! (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *); static tree cp_parser_parenthesized_expression_list ! (cp_parser *, bool, bool, bool *); static void cp_parser_pseudo_destructor_name (cp_parser *, tree *, tree *); static tree cp_parser_unary_expression ! (cp_parser *, bool, bool); static enum tree_code cp_parser_unary_operator (cp_token *); static tree cp_parser_new_expression *************** static tree cp_parser_new_expression *** 1355,1416 **** static tree cp_parser_new_placement (cp_parser *); static tree cp_parser_new_type_id (cp_parser *); ! static tree cp_parser_new_declarator_opt ! (cp_parser *); ! static tree cp_parser_direct_new_declarator (cp_parser *); static tree cp_parser_new_initializer (cp_parser *); static tree cp_parser_delete_expression (cp_parser *); ! static tree cp_parser_cast_expression (cp_parser *, bool); - static tree cp_parser_pm_expression - (cp_parser *); - static tree cp_parser_multiplicative_expression - (cp_parser *); - static tree cp_parser_additive_expression - (cp_parser *); - static tree cp_parser_shift_expression - (cp_parser *); - static tree cp_parser_relational_expression - (cp_parser *); - static tree cp_parser_equality_expression - (cp_parser *); - static tree cp_parser_and_expression - (cp_parser *); - static tree cp_parser_exclusive_or_expression - (cp_parser *); - static tree cp_parser_inclusive_or_expression - (cp_parser *); - static tree cp_parser_logical_and_expression - (cp_parser *); - static tree cp_parser_logical_or_expression - (cp_parser *); static tree cp_parser_question_colon_clause (cp_parser *, tree); static tree cp_parser_assignment_expression ! (cp_parser *); static enum tree_code cp_parser_assignment_operator_opt (cp_parser *); static tree cp_parser_expression ! (cp_parser *); static tree cp_parser_constant_expression (cp_parser *, bool, bool *); /* Statements [gram.stmt.stmt] */ static void cp_parser_statement ! (cp_parser *, bool); static tree cp_parser_labeled_statement ! (cp_parser *, bool); static tree cp_parser_expression_statement ! (cp_parser *, bool); static tree cp_parser_compound_statement ! (cp_parser *, bool); static void cp_parser_statement_seq_opt ! (cp_parser *, bool); static tree cp_parser_selection_statement (cp_parser *); static tree cp_parser_condition --- 1387,1430 ---- static tree cp_parser_new_placement (cp_parser *); static tree cp_parser_new_type_id + (cp_parser *, tree *); + static cp_declarator *cp_parser_new_declarator_opt (cp_parser *); ! static cp_declarator *cp_parser_direct_new_declarator (cp_parser *); static tree cp_parser_new_initializer (cp_parser *); static tree cp_parser_delete_expression (cp_parser *); ! static tree cp_parser_cast_expression ! (cp_parser *, bool, bool); ! static tree cp_parser_binary_expression (cp_parser *, bool); static tree cp_parser_question_colon_clause (cp_parser *, tree); static tree cp_parser_assignment_expression ! (cp_parser *, bool); static enum tree_code cp_parser_assignment_operator_opt (cp_parser *); static tree cp_parser_expression ! (cp_parser *, bool); static tree cp_parser_constant_expression (cp_parser *, bool, bool *); + static tree cp_parser_builtin_offsetof + (cp_parser *); /* Statements [gram.stmt.stmt] */ static void cp_parser_statement ! (cp_parser *, tree); static tree cp_parser_labeled_statement ! (cp_parser *, tree); static tree cp_parser_expression_statement ! (cp_parser *, tree); static tree cp_parser_compound_statement ! (cp_parser *, tree, bool); static void cp_parser_statement_seq_opt ! (cp_parser *, tree); static tree cp_parser_selection_statement (cp_parser *); static tree cp_parser_condition *************** static void cp_parser_block_declaration *** 1439,1454 **** (cp_parser *, bool); static void cp_parser_simple_declaration (cp_parser *, bool); ! static tree cp_parser_decl_specifier_seq ! (cp_parser *, cp_parser_flags, tree *, int *); static tree cp_parser_storage_class_specifier_opt (cp_parser *); static tree cp_parser_function_specifier_opt ! (cp_parser *); static tree cp_parser_type_specifier ! (cp_parser *, cp_parser_flags, bool, bool, int *, bool *); static tree cp_parser_simple_type_specifier ! (cp_parser *, cp_parser_flags, bool); static tree cp_parser_type_name (cp_parser *); static tree cp_parser_elaborated_type_specifier --- 1453,1469 ---- (cp_parser *, bool); static void cp_parser_simple_declaration (cp_parser *, bool); ! static void cp_parser_decl_specifier_seq ! (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *); static tree cp_parser_storage_class_specifier_opt (cp_parser *); static tree cp_parser_function_specifier_opt ! (cp_parser *, cp_decl_specifier_seq *); static tree cp_parser_type_specifier ! (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool, ! int *, bool *); static tree cp_parser_simple_type_specifier ! (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags); static tree cp_parser_type_name (cp_parser *); static tree cp_parser_elaborated_type_specifier *************** static tree cp_parser_enum_specifier *** 1457,1463 **** (cp_parser *); static void cp_parser_enumerator_list (cp_parser *, tree); ! static void cp_parser_enumerator_definition (cp_parser *, tree); static tree cp_parser_namespace_name (cp_parser *); --- 1472,1478 ---- (cp_parser *); static void cp_parser_enumerator_list (cp_parser *, tree); ! static void cp_parser_enumerator_definition (cp_parser *, tree); static tree cp_parser_namespace_name (cp_parser *); *************** static void cp_parser_linkage_specificat *** 1481,1508 **** /* Declarators [gram.dcl.decl] */ static tree cp_parser_init_declarator ! (cp_parser *, tree, tree, bool, bool, int, bool *); ! static tree cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); ! static tree cp_parser_direct_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool); static enum tree_code cp_parser_ptr_operator ! (cp_parser *, tree *, tree *); ! static tree cp_parser_cv_qualifier_seq_opt ! (cp_parser *); ! static tree cp_parser_cv_qualifier_opt (cp_parser *); static tree cp_parser_declarator_id (cp_parser *); static tree cp_parser_type_id (cp_parser *); ! static tree cp_parser_type_specifier_seq ! (cp_parser *); ! static tree cp_parser_parameter_declaration_clause ! (cp_parser *); ! static tree cp_parser_parameter_declaration_list (cp_parser *); ! static tree cp_parser_parameter_declaration (cp_parser *, bool, bool *); static void cp_parser_function_body (cp_parser *); --- 1496,1521 ---- /* Declarators [gram.dcl.decl] */ static tree cp_parser_init_declarator ! (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *); ! static cp_declarator *cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); ! static cp_declarator *cp_parser_direct_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool); static enum tree_code cp_parser_ptr_operator ! (cp_parser *, tree *, cp_cv_quals *); ! static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); static tree cp_parser_declarator_id (cp_parser *); static tree cp_parser_type_id (cp_parser *); ! static void cp_parser_type_specifier_seq ! (cp_parser *, bool, cp_decl_specifier_seq *); ! static cp_parameter_declarator *cp_parser_parameter_declaration_clause (cp_parser *); ! static cp_parameter_declarator *cp_parser_parameter_declaration_list ! (cp_parser *, bool *); ! static cp_parameter_declarator *cp_parser_parameter_declaration (cp_parser *, bool, bool *); static void cp_parser_function_body (cp_parser *); *************** static bool cp_parser_ctor_initializer_o *** 1519,1525 **** /* Classes [gram.class] */ static tree cp_parser_class_name ! (cp_parser *, bool, bool, bool, bool, bool, bool); static tree cp_parser_class_specifier (cp_parser *); static tree cp_parser_class_head --- 1532,1538 ---- /* Classes [gram.class] */ static tree cp_parser_class_name ! (cp_parser *, bool, bool, enum tag_types, bool, bool, bool); static tree cp_parser_class_specifier (cp_parser *); static tree cp_parser_class_head *************** static tree cp_parser_conversion_functio *** 1548,1554 **** (cp_parser *); static tree cp_parser_conversion_type_id (cp_parser *); ! static tree cp_parser_conversion_declarator_opt (cp_parser *); static bool cp_parser_ctor_initializer_opt (cp_parser *); --- 1561,1567 ---- (cp_parser *); static tree cp_parser_conversion_type_id (cp_parser *); ! static cp_declarator *cp_parser_conversion_declarator_opt (cp_parser *); static bool cp_parser_ctor_initializer_opt (cp_parser *); *************** static void cp_parser_template_declarati *** 1573,1579 **** static tree cp_parser_template_parameter_list (cp_parser *); static tree cp_parser_template_parameter ! (cp_parser *); static tree cp_parser_type_parameter (cp_parser *); static tree cp_parser_template_id --- 1586,1592 ---- static tree cp_parser_template_parameter_list (cp_parser *); static tree cp_parser_template_parameter ! (cp_parser *, bool *); static tree cp_parser_type_parameter (cp_parser *); static tree cp_parser_template_id *************** static void cp_parser_explicit_specializ *** 1591,1597 **** /* Exception handling [gram.exception] */ ! static tree cp_parser_try_block (cp_parser *); static bool cp_parser_function_try_block (cp_parser *); --- 1604,1610 ---- /* Exception handling [gram.exception] */ ! static tree cp_parser_try_block (cp_parser *); static bool cp_parser_function_try_block (cp_parser *); *************** static void cp_parser_label_declaration *** 1628,1652 **** /* Utility Routines */ static tree cp_parser_lookup_name ! (cp_parser *, tree, bool, bool, bool, bool); static tree cp_parser_lookup_name_simple (cp_parser *, tree); static tree cp_parser_maybe_treat_template_as_class (tree, bool); static bool cp_parser_check_declarator_template_parameters ! (cp_parser *, tree); static bool cp_parser_check_template_parameters (cp_parser *, unsigned); static tree cp_parser_simple_cast_expression (cp_parser *); - static tree cp_parser_binary_expression - (cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn); static tree cp_parser_global_scope_opt (cp_parser *, bool); static bool cp_parser_constructor_declarator_p (cp_parser *, bool); static tree cp_parser_function_definition_from_specifiers_and_declarator ! (cp_parser *, tree, tree, tree); static tree cp_parser_function_definition_after_declarator (cp_parser *, bool); static void cp_parser_template_declaration_after_export --- 1641,1663 ---- /* Utility Routines */ static tree cp_parser_lookup_name ! (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *); static tree cp_parser_lookup_name_simple (cp_parser *, tree); static tree cp_parser_maybe_treat_template_as_class (tree, bool); static bool cp_parser_check_declarator_template_parameters ! (cp_parser *, cp_declarator *); static bool cp_parser_check_template_parameters (cp_parser *, unsigned); static tree cp_parser_simple_cast_expression (cp_parser *); static tree cp_parser_global_scope_opt (cp_parser *, bool); static bool cp_parser_constructor_declarator_p (cp_parser *, bool); static tree cp_parser_function_definition_from_specifiers_and_declarator ! (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *); static tree cp_parser_function_definition_after_declarator (cp_parser *, bool); static void cp_parser_template_declaration_after_export *************** static tree cp_parser_single_declaration *** 1656,1662 **** static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body ! (cp_parser *, tree, tree, tree); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args --- 1667,1673 ---- static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body ! (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args *************** static tree cp_parser_sizeof_operand *** 1669,1681 **** (cp_parser *, enum rid); static bool cp_parser_declares_only_class_p (cp_parser *); static bool cp_parser_friend_p ! (tree); static cp_token *cp_parser_require (cp_parser *, enum cpp_ttype, const char *); static cp_token *cp_parser_require_keyword (cp_parser *, enum rid, const char *); ! static bool cp_parser_token_starts_function_definition_p (cp_token *); static bool cp_parser_next_token_starts_class_definition_p (cp_parser *); --- 1680,1696 ---- (cp_parser *, enum rid); static bool cp_parser_declares_only_class_p (cp_parser *); + static void cp_parser_set_storage_class + (cp_decl_specifier_seq *, cp_storage_class); + static void cp_parser_set_decl_spec_type + (cp_decl_specifier_seq *, tree, bool); static bool cp_parser_friend_p ! (const cp_decl_specifier_seq *); static cp_token *cp_parser_require (cp_parser *, enum cpp_ttype, const char *); static cp_token *cp_parser_require_keyword (cp_parser *, enum rid, const char *); ! static bool cp_parser_token_starts_function_definition_p (cp_token *); static bool cp_parser_next_token_starts_class_definition_p (cp_parser *); *************** static void cp_parser_check_access_in_re *** 1691,1701 **** (tree type); static bool cp_parser_optional_template_keyword (cp_parser *); ! static void cp_parser_pre_parsed_nested_name_specifier (cp_parser *); static void cp_parser_cache_group ! (cp_parser *, cp_token_cache *, enum cpp_ttype, unsigned); ! static void cp_parser_parse_tentatively (cp_parser *); static void cp_parser_commit_to_tentative_parse (cp_parser *); --- 1706,1716 ---- (tree type); static bool cp_parser_optional_template_keyword (cp_parser *); ! static void cp_parser_pre_parsed_nested_name_specifier (cp_parser *); static void cp_parser_cache_group ! (cp_parser *, enum cpp_ttype, unsigned); ! static void cp_parser_parse_tentatively (cp_parser *); static void cp_parser_commit_to_tentative_parse (cp_parser *); *************** static bool cp_parser_parse_definitely *** 1705,1711 **** (cp_parser *); static inline bool cp_parser_parsing_tentatively (cp_parser *); ! static bool cp_parser_committed_to_tentative_parse (cp_parser *); static void cp_parser_error (cp_parser *, const char *); --- 1720,1726 ---- (cp_parser *); static inline bool cp_parser_parsing_tentatively (cp_parser *); ! static bool cp_parser_uncommitted_to_tentative_parse_p (cp_parser *); static void cp_parser_error (cp_parser *, const char *); *************** static bool cp_parser_simulate_error *** 1716,1727 **** static void cp_parser_check_type_definition (cp_parser *); static void cp_parser_check_for_definition_in_return_type ! (tree, int); static void cp_parser_check_for_invalid_template_id (cp_parser *, tree); static bool cp_parser_non_integral_constant_expression (cp_parser *, const char *); ! static bool cp_parser_diagnose_invalid_type_name (cp_parser *); static int cp_parser_skip_to_closing_parenthesis (cp_parser *, bool, bool, bool); --- 1731,1744 ---- static void cp_parser_check_type_definition (cp_parser *); static void cp_parser_check_for_definition_in_return_type ! (cp_declarator *, tree); static void cp_parser_check_for_invalid_template_id (cp_parser *, tree); static bool cp_parser_non_integral_constant_expression (cp_parser *, const char *); ! static void cp_parser_diagnose_invalid_type_name ! (cp_parser *, tree, tree); ! static bool cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *); static int cp_parser_skip_to_closing_parenthesis (cp_parser *, bool, bool, bool); *************** static bool cp_parser_allow_gnu_extensio *** 1741,1748 **** (cp_parser *); static bool cp_parser_is_string_literal (cp_token *); ! static bool cp_parser_is_keyword (cp_token *, enum rid); /* Returns nonzero if we are parsing tentatively. */ --- 1758,1767 ---- (cp_parser *); static bool cp_parser_is_string_literal (cp_token *); ! static bool cp_parser_is_keyword (cp_token *, enum rid); + static tree cp_parser_make_typename_type + (cp_parser *, tree, tree); /* Returns nonzero if we are parsing tentatively. */ *************** cp_parser_is_keyword (cp_token* token, e *** 1768,1788 **** return token->keyword == keyword; } ! /* Issue the indicated error MESSAGE. */ static void cp_parser_error (cp_parser* parser, const char* message) { - /* Output the MESSAGE -- unless we're parsing tentatively. */ if (!cp_parser_simulate_error (parser)) { ! cp_token *token; ! token = cp_lexer_peek_token (parser->lexer); ! c_parse_error (message, /* Because c_parser_error does not understand CPP_KEYWORD, keywords are treated like identifiers. */ ! (token->type == CPP_KEYWORD ? CPP_NAME : token->type), token->value); } } --- 1787,1828 ---- return token->keyword == keyword; } ! /* A minimum or maximum operator has been seen. As these are ! deprecated, issue a warning. */ ! ! static inline void ! cp_parser_warn_min_max (void) ! { ! if (warn_deprecated && !in_system_header) ! warning ("minimum/maximum operators are deprecated"); ! } ! ! /* If not parsing tentatively, issue a diagnostic of the form ! FILE:LINE: MESSAGE before TOKEN ! where TOKEN is the next token in the input stream. MESSAGE ! (specified by the caller) is usually of the form "expected ! OTHER-TOKEN". */ static void cp_parser_error (cp_parser* parser, const char* message) { if (!cp_parser_simulate_error (parser)) { ! cp_token *token = cp_lexer_peek_token (parser->lexer); ! /* This diagnostic makes more sense if it is tagged to the line ! of the token we just peeked at. */ ! cp_lexer_set_source_position_from_token (token); ! if (token->type == CPP_PRAGMA) ! { ! error ("%<#pragma%> is not allowed here"); ! cp_lexer_purge_token (parser->lexer); ! return; ! } ! c_parse_error (message, /* Because c_parser_error does not understand CPP_KEYWORD, keywords are treated like identifiers. */ ! (token->type == CPP_KEYWORD ? CPP_NAME : token->type), token->value); } } *************** cp_parser_name_lookup_error (cp_parser* *** 1803,1832 **** if (decl == error_mark_node) { if (parser->scope && parser->scope != global_namespace) ! error ("`%D::%D' has not been declared", parser->scope, name); else if (parser->scope == global_namespace) ! error ("`::%D' has not been declared", name); else ! error ("`%D' has not been declared", name); } else if (parser->scope && parser->scope != global_namespace) ! error ("`%D::%D' %s", parser->scope, name, desired); else if (parser->scope == global_namespace) ! error ("`::%D' %s", name, desired); else ! error ("`%D' %s", name, desired); } /* If we are parsing tentatively, remember that an error has occurred during this tentative parse. Returns true if the error was ! simulated; false if a messgae should be issued by the caller. */ static bool cp_parser_simulate_error (cp_parser* parser) { ! if (cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) { parser->context->status = CP_PARSER_STATUS_KIND_ERROR; return true; --- 1843,1878 ---- if (decl == error_mark_node) { if (parser->scope && parser->scope != global_namespace) ! error ("%<%D::%D%> has not been declared", parser->scope, name); else if (parser->scope == global_namespace) ! error ("%<::%D%> has not been declared", name); ! else if (parser->object_scope ! && !CLASS_TYPE_P (parser->object_scope)) ! error ("request for member %qD in non-class type %qT", ! name, parser->object_scope); ! else if (parser->object_scope) ! error ("%<%T::%D%> has not been declared", ! parser->object_scope, name); else ! error ("%qD has not been declared", name); } else if (parser->scope && parser->scope != global_namespace) ! error ("%<%D::%D%> %s", parser->scope, name, desired); else if (parser->scope == global_namespace) ! error ("%<::%D%> %s", name, desired); else ! error ("%qD %s", name, desired); } /* If we are parsing tentatively, remember that an error has occurred during this tentative parse. Returns true if the error was ! simulated; false if a message should be issued by the caller. */ static bool cp_parser_simulate_error (cp_parser* parser) { ! if (cp_parser_uncommitted_to_tentative_parse_p (parser)) { parser->context->status = CP_PARSER_STATUS_KIND_ERROR; return true; *************** cp_parser_check_type_definition (cp_pars *** 1848,1873 **** error ("%s", parser->type_definition_forbidden_message); } ! /* This function is called when a declaration is parsed. If ! DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM ! indicates that a type was defined in the decl-specifiers for DECL, ! then an error is issued. */ static void ! cp_parser_check_for_definition_in_return_type (tree declarator, ! int declares_class_or_enum) { /* [dcl.fct] forbids type definitions in return types. Unfortunately, it's not easy to know whether or not we are processing a return type until after the fact. */ while (declarator ! && (TREE_CODE (declarator) == INDIRECT_REF ! || TREE_CODE (declarator) == ADDR_EXPR)) ! declarator = TREE_OPERAND (declarator, 0); if (declarator ! && TREE_CODE (declarator) == CALL_EXPR ! && declares_class_or_enum & 2) ! error ("new types may not be defined in a return type"); } /* A type-specifier (TYPE) has been parsed which cannot be followed by --- 1894,1923 ---- error ("%s", parser->type_definition_forbidden_message); } ! /* This function is called when the DECLARATOR is processed. The TYPE ! was a type defined in the decl-specifiers. If it is invalid to ! define a type in the decl-specifiers for DECLARATOR, an error is ! issued. */ static void ! cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, ! tree type) { /* [dcl.fct] forbids type definitions in return types. Unfortunately, it's not easy to know whether or not we are processing a return type until after the fact. */ while (declarator ! && (declarator->kind == cdk_pointer ! || declarator->kind == cdk_reference ! || declarator->kind == cdk_ptrmem)) ! declarator = declarator->declarator; if (declarator ! && declarator->kind == cdk_function) ! { ! error ("new types may not be defined in a return type"); ! inform ("(perhaps a semicolon is missing after the definition of %qT)", ! type); ! } } /* A type-specifier (TYPE) has been parsed which cannot be followed by *************** cp_parser_check_for_definition_in_return *** 1876,1931 **** invalid attempt to form a template-id. */ static void ! cp_parser_check_for_invalid_template_id (cp_parser* parser, tree type) { ! ptrdiff_t start; ! cp_token *token; if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { if (TYPE_P (type)) ! error ("`%T' is not a template", type); else if (TREE_CODE (type) == IDENTIFIER_NODE) ! error ("`%s' is not a template", IDENTIFIER_POINTER (type)); else error ("invalid template-id"); /* Remember the location of the invalid "<". */ ! if (cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) ! { ! token = cp_lexer_peek_token (parser->lexer); ! token = cp_lexer_prev_token (parser->lexer, token); ! start = cp_lexer_token_difference (parser->lexer, ! parser->lexer->first_token, ! token); ! } ! else ! start = -1; /* Consume the "<". */ cp_lexer_consume_token (parser->lexer); /* Parse the template arguments. */ cp_parser_enclosed_template_argument_list (parser); /* Permanently remove the invalid template arguments so that this error message is not issued again. */ ! if (start >= 0) ! { ! token = cp_lexer_advance_token (parser->lexer, ! parser->lexer->first_token, ! start); ! cp_lexer_purge_tokens_after (parser->lexer, token); ! } } } /* If parsing an integral constant-expression, issue an error message about the fact that THING appeared and return true. Otherwise, ! return false, marking the current expression as non-constant. */ static bool cp_parser_non_integral_constant_expression (cp_parser *parser, const char *thing) { if (parser->integral_constant_expression_p) { if (!parser->allow_non_integral_constant_expression_p) --- 1926,1968 ---- invalid attempt to form a template-id. */ static void ! cp_parser_check_for_invalid_template_id (cp_parser* parser, tree type) { ! cp_token_position start = 0; if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { if (TYPE_P (type)) ! error ("%qT is not a template", type); else if (TREE_CODE (type) == IDENTIFIER_NODE) ! error ("%qE is not a template", type); else error ("invalid template-id"); /* Remember the location of the invalid "<". */ ! if (cp_parser_uncommitted_to_tentative_parse_p (parser)) ! start = cp_lexer_token_position (parser->lexer, true); /* Consume the "<". */ cp_lexer_consume_token (parser->lexer); /* Parse the template arguments. */ cp_parser_enclosed_template_argument_list (parser); /* Permanently remove the invalid template arguments so that this error message is not issued again. */ ! if (start) ! cp_lexer_purge_tokens_after (parser->lexer, start); } } /* If parsing an integral constant-expression, issue an error message about the fact that THING appeared and return true. Otherwise, ! return false. In either case, set ! PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P. */ static bool cp_parser_non_integral_constant_expression (cp_parser *parser, const char *thing) { + parser->non_integral_constant_expression_p = true; if (parser->integral_constant_expression_p) { if (!parser->allow_non_integral_constant_expression_p) *************** cp_parser_non_integral_constant_expressi *** 1933,1967 **** error ("%s cannot appear in a constant-expression", thing); return true; } - parser->non_integral_constant_expression_p = true; } return false; } ! /* Check for a common situation where a type-name should be present, ! but is not, and issue a sensible error message. Returns true if an ! invalid type-name was detected. */ ! static bool ! cp_parser_diagnose_invalid_type_name (cp_parser *parser) { ! /* If the next two tokens are both identifiers, the code is ! erroneous. The usual cause of this situation is code like: ! ! T t; ! ! where "T" should name a type -- but does not. */ ! if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME) { - tree name; - - /* If parsing tentatively, we should commit; we really are - looking at a declaration. */ - /* Consume the first identifier. */ - name = cp_lexer_consume_token (parser->lexer)->value; /* Issue an error message. */ ! error ("`%s' does not name a type", IDENTIFIER_POINTER (name)); /* If we're in a template class, it's possible that the user was referring to a type from a base class. For example: --- 1970,2003 ---- error ("%s cannot appear in a constant-expression", thing); return true; } } return false; } ! /* Emit a diagnostic for an invalid type name. SCOPE is the ! qualifying scope (or NULL, if none) for ID. This function commits ! to the current active tentative parse, if any. (Otherwise, the ! problematic construct might be encountered again later, resulting ! in duplicate error messages.) */ ! static void ! cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) { ! tree decl, old_scope; ! /* Try to lookup the identifier. */ ! old_scope = parser->scope; ! parser->scope = scope; ! decl = cp_parser_lookup_name_simple (parser, id); ! parser->scope = old_scope; ! /* If the lookup found a template-name, it means that the user forgot ! to specify an argument list. Emit an useful error message. */ ! if (TREE_CODE (decl) == TEMPLATE_DECL) ! error ("invalid use of template-name %qE without an argument list", ! decl); ! else if (!parser->scope) { /* Issue an error message. */ ! error ("%qE does not name a type", id); /* If we're in a template class, it's possible that the user was referring to a type from a base class. For example: *************** cp_parser_diagnose_invalid_type_name (cp *** 1969,1975 **** template struct B : public A { X x; }; The user should have said "typename A::X". */ ! if (processing_template_decl && current_class_type) { tree b; --- 2005,2012 ---- template struct B : public A { X x; }; The user should have said "typename A::X". */ ! if (processing_template_decl && current_class_type ! && TYPE_BINFO (current_class_type)) { tree b; *************** cp_parser_diagnose_invalid_type_name (cp *** 1978,1984 **** b = TREE_CHAIN (b)) { tree base_type = BINFO_TYPE (b); ! if (CLASS_TYPE_P (base_type) && dependent_type_p (base_type)) { tree field; --- 2015,2021 ---- b = TREE_CHAIN (b)) { tree base_type = BINFO_TYPE (b); ! if (CLASS_TYPE_P (base_type) && dependent_type_p (base_type)) { tree field; *************** cp_parser_diagnose_invalid_type_name (cp *** 1990,1999 **** field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == TYPE_DECL ! && DECL_NAME (field) == name) { ! error ("(perhaps `typename %T::%s' was intended)", ! BINFO_TYPE (b), IDENTIFIER_POINTER (name)); break; } if (field) --- 2027,2036 ---- field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == TYPE_DECL ! && DECL_NAME (field) == id) { ! inform ("(perhaps % was intended)", ! BINFO_TYPE (b), id); break; } if (field) *************** cp_parser_diagnose_invalid_type_name (cp *** 2001,2058 **** } } } - /* Skip to the end of the declaration; there's no point in - trying to process it. */ - cp_parser_skip_to_end_of_statement (parser); - - return true; } ! return false; } ! /* Consume tokens up to, and including, the next non-nested closing `)'. Returns 1 iff we found a closing `)'. RECOVERING is true, if we are doing error recovery. Returns -1 if OR_COMMA is true and we found an unnested comma. */ static int cp_parser_skip_to_closing_parenthesis (cp_parser *parser, ! bool recovering, bool or_comma, bool consume_paren) { unsigned paren_depth = 0; unsigned brace_depth = 0; ! if (recovering && !or_comma && cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) return 0; ! while (true) { cp_token *token; ! /* If we've run out of tokens, then there is no closing `)'. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) ! return 0; token = cp_lexer_peek_token (parser->lexer); ! /* This matches the processing in skip_to_end_of_statement. */ if (token->type == CPP_SEMICOLON && !brace_depth) ! return 0; if (token->type == CPP_OPEN_BRACE) ++brace_depth; if (token->type == CPP_CLOSE_BRACE) { if (!brace_depth--) ! return 0; } if (recovering && or_comma && token->type == CPP_COMMA && !brace_depth && !paren_depth) ! return -1; ! if (!brace_depth) { /* If it is an `(', we have entered another level of nesting. */ --- 2038,2158 ---- } } } } + /* Here we diagnose qualified-ids where the scope is actually correct, + but the identifier does not resolve to a valid type name. */ + else + { + if (TREE_CODE (parser->scope) == NAMESPACE_DECL) + error ("%qE in namespace %qE does not name a type", + id, parser->scope); + else if (TYPE_P (parser->scope)) + error ("%qE in class %qT does not name a type", id, parser->scope); + else + gcc_unreachable (); + } + cp_parser_commit_to_tentative_parse (parser); + } ! /* Check for a common situation where a type-name should be present, ! but is not, and issue a sensible error message. Returns true if an ! invalid type-name was detected. ! ! The situation handled by this function are variable declarations of the ! form `ID a', where `ID' is an id-expression and `a' is a plain identifier. ! Usually, `ID' should name a type, but if we got here it means that it ! does not. We try to emit the best possible error message depending on ! how exactly the id-expression looks like. ! */ ! ! static bool ! cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) ! { ! tree id; ! ! cp_parser_parse_tentatively (parser); ! id = cp_parser_id_expression (parser, ! /*template_keyword_p=*/false, ! /*check_dependency_p=*/true, ! /*template_p=*/NULL, ! /*declarator_p=*/true); ! /* After the id-expression, there should be a plain identifier, ! otherwise this is not a simple variable declaration. Also, if ! the scope is dependent, we cannot do much. */ ! if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! || (parser->scope && TYPE_P (parser->scope) ! && dependent_type_p (parser->scope))) ! { ! cp_parser_abort_tentative_parse (parser); ! return false; ! } ! if (!cp_parser_parse_definitely (parser) ! || TREE_CODE (id) != IDENTIFIER_NODE) ! return false; ! ! /* Emit a diagnostic for the invalid type. */ ! cp_parser_diagnose_invalid_type_name (parser, parser->scope, id); ! /* Skip to the end of the declaration; there's no point in ! trying to process it. */ ! cp_parser_skip_to_end_of_block_or_statement (parser); ! return true; } ! /* Consume tokens up to, and including, the next non-nested closing `)'. Returns 1 iff we found a closing `)'. RECOVERING is true, if we are doing error recovery. Returns -1 if OR_COMMA is true and we found an unnested comma. */ static int cp_parser_skip_to_closing_parenthesis (cp_parser *parser, ! bool recovering, bool or_comma, bool consume_paren) { unsigned paren_depth = 0; unsigned brace_depth = 0; + int result; ! if (recovering && !or_comma ! && cp_parser_uncommitted_to_tentative_parse_p (parser)) return 0; ! while (true) { cp_token *token; ! /* If we've run out of tokens, then there is no closing `)'. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) ! { ! result = 0; ! break; ! } token = cp_lexer_peek_token (parser->lexer); ! /* This matches the processing in skip_to_end_of_statement. */ if (token->type == CPP_SEMICOLON && !brace_depth) ! { ! result = 0; ! break; ! } if (token->type == CPP_OPEN_BRACE) ++brace_depth; if (token->type == CPP_CLOSE_BRACE) { if (!brace_depth--) ! { ! result = 0; ! break; ! } } if (recovering && or_comma && token->type == CPP_COMMA && !brace_depth && !paren_depth) ! { ! result = -1; ! break; ! } ! if (!brace_depth) { /* If it is an `(', we have entered another level of nesting. */ *************** cp_parser_skip_to_closing_parenthesis (c *** 2063,2075 **** { if (consume_paren) cp_lexer_consume_token (parser->lexer); ! return 1; } } ! /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } } /* Consume tokens until we reach the end of the current statement. --- 2163,2180 ---- { if (consume_paren) cp_lexer_consume_token (parser->lexer); ! { ! result = 1; ! break; ! } } } ! /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } + + return result; } /* Consume tokens until we reach the end of the current statement. *************** cp_parser_skip_to_end_of_statement (cp_p *** 2101,2107 **** /* If this is a non-nested `}', stop before consuming it. That way, when confronted with something like: ! { 3 + } we stop before consuming the closing `}', even though we have not yet reached a `;'. */ --- 2206,2212 ---- /* If this is a non-nested `}', stop before consuming it. That way, when confronted with something like: ! { 3 + } we stop before consuming the closing `}', even though we have not yet reached a `;'. */ *************** cp_parser_skip_to_end_of_block_or_statem *** 2180,2186 **** token = cp_lexer_consume_token (parser->lexer); /* If the next token is a non-nested `}', then we have reached the end of the current block. */ ! if (token->type == CPP_CLOSE_BRACE && (nesting_depth == 0 || --nesting_depth == 0)) break; /* If it the next token is a `{', then we are entering a new --- 2285,2291 ---- token = cp_lexer_consume_token (parser->lexer); /* If the next token is a non-nested `}', then we have reached the end of the current block. */ ! if (token->type == CPP_CLOSE_BRACE && (nesting_depth == 0 || --nesting_depth == 0)) break; /* If it the next token is a `{', then we are entering a new *************** cp_parser_skip_to_closing_brace (cp_pars *** 2220,2225 **** --- 2325,2350 ---- } } + /* This is a simple wrapper around make_typename_type. When the id is + an unresolved identifier node, we can provide a superior diagnostic + using cp_parser_diagnose_invalid_type_name. */ + + static tree + cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id) + { + tree result; + if (TREE_CODE (id) == IDENTIFIER_NODE) + { + result = make_typename_type (scope, id, typename_type, + /*complain=*/0); + if (result == error_mark_node) + cp_parser_diagnose_invalid_type_name (parser, scope, id); + return result; + } + return make_typename_type (scope, id, typename_type, tf_error); + } + + /* Create a new C++ parser. */ static cp_parser * *************** cp_parser_new (void) *** 2227,2238 **** { cp_parser *parser; cp_lexer *lexer; /* cp_lexer_new_main is called before calling ggc_alloc because cp_lexer_new_main might load a PCH file. */ lexer = cp_lexer_new_main (); ! parser = ggc_alloc_cleared (sizeof (cp_parser)); parser->lexer = lexer; parser->context = cp_parser_context_new (NULL); --- 2352,2369 ---- { cp_parser *parser; cp_lexer *lexer; + unsigned i; /* cp_lexer_new_main is called before calling ggc_alloc because cp_lexer_new_main might load a PCH file. */ lexer = cp_lexer_new_main (); ! /* Initialize the binops_by_token so that we can get the tree ! directly from the token. */ ! for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++) ! binops_by_token[binops[i].token_type] = binops[i]; ! ! parser = GGC_CNEW (cp_parser); parser->lexer = lexer; parser->context = cp_parser_context_new (NULL); *************** cp_parser_new (void) *** 2244,2258 **** parser->greater_than_is_operator_p = true; parser->default_arg_ok_p = true; ! /* We are not parsing a constant-expression. */ parser->integral_constant_expression_p = false; parser->allow_non_integral_constant_expression_p = false; parser->non_integral_constant_expression_p = false; - /* We are not parsing offsetof. */ - parser->in_offsetof_p = false; - /* Local variable names are not forbidden. */ parser->local_variables_forbidden_p = false; --- 2375,2386 ---- parser->greater_than_is_operator_p = true; parser->default_arg_ok_p = true; ! /* We are not parsing a constant-expression. */ parser->integral_constant_expression_p = false; parser->allow_non_integral_constant_expression_p = false; parser->non_integral_constant_expression_p = false; /* Local variable names are not forbidden. */ parser->local_variables_forbidden_p = false; *************** cp_parser_new (void) *** 2274,2279 **** --- 2402,2413 ---- /* We are not parsing a type-id inside an expression. */ parser->in_type_id_in_expr_p = false; + /* Declarations aren't implicitly extern "C". */ + parser->implicit_extern_c = false; + + /* String literals should be translated to the execution character set. */ + parser->translate_strings_p = true; + /* The unparsed function queue is empty. */ parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE); *************** cp_parser_new (void) *** 2286,2297 **** return parser; } /* Lexical conventions [gram.lex] */ /* Parse an identifier. Returns an IDENTIFIER_NODE representing the identifier. */ ! static tree cp_parser_identifier (cp_parser* parser) { cp_token *token; --- 2420,2461 ---- return parser; } + /* Create a cp_lexer structure which will emit the tokens in CACHE + and push it onto the parser's lexer stack. This is used for delayed + parsing of in-class method bodies and default arguments, and should + not be confused with tentative parsing. */ + static void + cp_parser_push_lexer_for_tokens (cp_parser *parser, cp_token_cache *cache) + { + cp_lexer *lexer = cp_lexer_new_from_tokens (cache); + lexer->next = parser->lexer; + parser->lexer = lexer; + + /* Move the current source position to that of the first token in the + new lexer. */ + cp_lexer_set_source_position_from_token (lexer->next_token); + } + + /* Pop the top lexer off the parser stack. This is never used for the + "main" lexer, only for those pushed by cp_parser_push_lexer_for_tokens. */ + static void + cp_parser_pop_lexer (cp_parser *parser) + { + cp_lexer *lexer = parser->lexer; + parser->lexer = lexer->next; + cp_lexer_destroy (lexer); + + /* Put the current source position back where it was before this + lexer was pushed. */ + cp_lexer_set_source_position_from_token (parser->lexer->next_token); + } + /* Lexical conventions [gram.lex] */ /* Parse an identifier. Returns an IDENTIFIER_NODE representing the identifier. */ ! static tree cp_parser_identifier (cp_parser* parser) { cp_token *token; *************** cp_parser_identifier (cp_parser* parser) *** 2302,2340 **** return token ? token->value : error_mark_node; } /* Basic concepts [gram.basic] */ /* Parse a translation-unit. translation-unit: ! declaration-seq [opt] Returns TRUE if all went well. */ static bool cp_parser_translation_unit (cp_parser* parser) { while (true) { cp_parser_declaration_seq_opt (parser); /* If there are no tokens left then all went well. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) ! break; ! ! /* Otherwise, issue an error message. */ ! cp_parser_error (parser, "expected declaration"); ! return false; } ! /* Consume the EOF token. */ ! cp_parser_require (parser, CPP_EOF, "end-of-file"); ! ! /* Finish up. */ ! finish_translation_unit (); /* All went well. */ ! return true; } /* Expressions [gram.expr] */ --- 2466,2635 ---- return token ? token->value : error_mark_node; } + /* Parse a sequence of adjacent string constants. Returns a + TREE_STRING representing the combined, nul-terminated string + constant. If TRANSLATE is true, translate the string to the + execution character set. If WIDE_OK is true, a wide string is + invalid here. + + C++98 [lex.string] says that if a narrow string literal token is + adjacent to a wide string literal token, the behavior is undefined. + However, C99 6.4.5p4 says that this results in a wide string literal. + We follow C99 here, for consistency with the C front end. + + This code is largely lifted from lex_string() in c-lex.c. + + FUTURE: ObjC++ will need to handle @-strings here. */ + static tree + cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) + { + tree value; + bool wide = false; + size_t count; + struct obstack str_ob; + cpp_string str, istr, *strs; + cp_token *tok; + + tok = cp_lexer_peek_token (parser->lexer); + if (!cp_parser_is_string_literal (tok)) + { + cp_parser_error (parser, "expected string-literal"); + return error_mark_node; + } + + /* Try to avoid the overhead of creating and destroying an obstack + for the common case of just one string. */ + if (!cp_parser_is_string_literal + (cp_lexer_peek_nth_token (parser->lexer, 2))) + { + cp_lexer_consume_token (parser->lexer); + + str.text = (const unsigned char *)TREE_STRING_POINTER (tok->value); + str.len = TREE_STRING_LENGTH (tok->value); + count = 1; + if (tok->type == CPP_WSTRING) + wide = true; + + strs = &str; + } + else + { + gcc_obstack_init (&str_ob); + count = 0; + + do + { + cp_lexer_consume_token (parser->lexer); + count++; + str.text = (unsigned char *)TREE_STRING_POINTER (tok->value); + str.len = TREE_STRING_LENGTH (tok->value); + if (tok->type == CPP_WSTRING) + wide = true; + + obstack_grow (&str_ob, &str, sizeof (cpp_string)); + + tok = cp_lexer_peek_token (parser->lexer); + } + while (cp_parser_is_string_literal (tok)); + + strs = (cpp_string *) obstack_finish (&str_ob); + } + + if (wide && !wide_ok) + { + cp_parser_error (parser, "a wide string is invalid in this context"); + wide = false; + } + + if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate) + (parse_in, strs, count, &istr, wide)) + { + value = build_string (istr.len, (char *)istr.text); + free ((void *)istr.text); + + TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node; + value = fix_string_type (value); + } + else + /* cpp_interpret_string has issued an error. */ + value = error_mark_node; + + if (count > 1) + obstack_free (&str_ob, 0); + + return value; + } + + /* Basic concepts [gram.basic] */ /* Parse a translation-unit. translation-unit: ! declaration-seq [opt] Returns TRUE if all went well. */ static bool cp_parser_translation_unit (cp_parser* parser) { + /* The address of the first non-permanent object on the declarator + obstack. */ + static void *declarator_obstack_base; + + bool success; + + /* Create the declarator obstack, if necessary. */ + if (!cp_error_declarator) + { + gcc_obstack_init (&declarator_obstack); + /* Create the error declarator. */ + cp_error_declarator = make_declarator (cdk_error); + /* Create the empty parameter list. */ + no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE); + /* Remember where the base of the declarator obstack lies. */ + declarator_obstack_base = obstack_next_free (&declarator_obstack); + } + while (true) { cp_parser_declaration_seq_opt (parser); /* If there are no tokens left then all went well. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) ! { ! /* Get rid of the token array; we don't need it any more. */ ! cp_lexer_destroy (parser->lexer); ! parser->lexer = NULL; ! ! /* This file might have been a context that's implicitly extern ! "C". If so, pop the lang context. (Only relevant for PCH.) */ ! if (parser->implicit_extern_c) ! { ! pop_lang_context (); ! parser->implicit_extern_c = false; ! } ! ! /* Finish up. */ ! finish_translation_unit (); ! ! success = true; ! break; ! } ! else ! { ! cp_parser_error (parser, "expected declaration"); ! success = false; ! break; ! } } ! /* Make sure the declarator obstack was fully cleaned up. */ ! gcc_assert (obstack_next_free (&declarator_obstack) ! == declarator_obstack_base); /* All went well. */ ! return success; } /* Expressions [gram.expr] */ *************** cp_parser_translation_unit (cp_parser* p *** 2356,2364 **** literal: __null ! Returns a representation of the expression. ! *IDK indicates what kind of id-expression (if any) was present. *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be used as the operand of a pointer-to-member. In that case, --- 2651,2661 ---- literal: __null ! CAST_P is true if this primary expression is the target of a cast. ! Returns a representation of the expression. ! ! *IDK indicates what kind of id-expression (if any) was present. *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be used as the operand of a pointer-to-member. In that case, *************** cp_parser_translation_unit (cp_parser* p *** 2366,2372 **** class in the pointer-to-member. */ static tree ! cp_parser_primary_expression (cp_parser *parser, cp_id_kind *idk, tree *qualifying_class) { --- 2663,2670 ---- class in the pointer-to-member. */ static tree ! cp_parser_primary_expression (cp_parser *parser, ! bool cast_p, cp_id_kind *idk, tree *qualifying_class) { *************** cp_parser_primary_expression (cp_parser *** 2389,2400 **** boolean-literal */ case CPP_CHAR: case CPP_WCHAR: - case CPP_STRING: - case CPP_WSTRING: case CPP_NUMBER: token = cp_lexer_consume_token (parser->lexer); return token->value; case CPP_OPEN_PAREN: { tree expr; --- 2687,2742 ---- boolean-literal */ case CPP_CHAR: case CPP_WCHAR: case CPP_NUMBER: token = cp_lexer_consume_token (parser->lexer); + /* Floating-point literals are only allowed in an integral + constant expression if they are cast to an integral or + enumeration type. */ + if (TREE_CODE (token->value) == REAL_CST + && parser->integral_constant_expression_p + && pedantic) + { + /* CAST_P will be set even in invalid code like "int(2.7 + + ...)". Therefore, we have to check that the next token + is sure to end the cast. */ + if (cast_p) + { + cp_token *next_token; + + next_token = cp_lexer_peek_token (parser->lexer); + if (/* The comma at the end of an + enumerator-definition. */ + next_token->type != CPP_COMMA + /* The curly brace at the end of an enum-specifier. */ + && next_token->type != CPP_CLOSE_BRACE + /* The end of a statement. */ + && next_token->type != CPP_SEMICOLON + /* The end of the cast-expression. */ + && next_token->type != CPP_CLOSE_PAREN + /* The end of an array bound. */ + && next_token->type != CPP_CLOSE_SQUARE) + cast_p = false; + } + + /* If we are within a cast, then the constraint that the + cast is to an integral or enumeration type will be + checked at that point. If we are not within a cast, then + this code is invalid. */ + if (!cast_p) + cp_parser_non_integral_constant_expression + (parser, "floating-point literal"); + } return token->value; + case CPP_STRING: + case CPP_WSTRING: + /* ??? Should wide strings be allowed when parser->translate_strings_p + is false (i.e. in attributes)? If not, we can kill the third + argument to cp_parser_string_literal. */ + return cp_parser_string_literal (parser, + parser->translate_strings_p, + true); + case CPP_OPEN_PAREN: { tree expr; *************** cp_parser_primary_expression (cp_parser *** 2404,2410 **** cp_lexer_consume_token (parser->lexer); /* Within a parenthesized expression, a `>' token is always the greater-than operator. */ ! saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = true; /* If we see `( { ' then we are looking at the beginning of --- 2746,2752 ---- cp_lexer_consume_token (parser->lexer); /* Within a parenthesized expression, a `>' token is always the greater-than operator. */ ! saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = true; /* If we see `( { ' then we are looking at the beginning of *************** cp_parser_primary_expression (cp_parser *** 2414,2440 **** { /* Statement-expressions are not allowed by the standard. */ if (pedantic) ! pedwarn ("ISO C++ forbids braced-groups within expressions"); ! /* And they're not allowed outside of a function-body; you cannot, for example, write: ! int i = ({ int j = 3; j + 1; }); ! at class or namespace scope. */ if (!at_function_scope_p ()) error ("statement-expressions are allowed only inside functions"); /* Start the statement-expression. */ expr = begin_stmt_expr (); /* Parse the compound-statement. */ ! cp_parser_compound_statement (parser, true); /* Finish up. */ expr = finish_stmt_expr (expr, false); } else { /* Parse the parenthesized expression. */ ! expr = cp_parser_expression (parser); /* Let the front end know that this expression was enclosed in parentheses. This matters in case, for example, the expression is of the form `A::B', since --- 2756,2782 ---- { /* Statement-expressions are not allowed by the standard. */ if (pedantic) ! pedwarn ("ISO C++ forbids braced-groups within expressions"); ! /* And they're not allowed outside of a function-body; you cannot, for example, write: ! int i = ({ int j = 3; j + 1; }); ! at class or namespace scope. */ if (!at_function_scope_p ()) error ("statement-expressions are allowed only inside functions"); /* Start the statement-expression. */ expr = begin_stmt_expr (); /* Parse the compound-statement. */ ! cp_parser_compound_statement (parser, expr, false); /* Finish up. */ expr = finish_stmt_expr (expr, false); } else { /* Parse the parenthesized expression. */ ! expr = cp_parser_expression (parser, cast_p); /* Let the front end know that this expression was enclosed in parentheses. This matters in case, for example, the expression is of the form `A::B', since *************** cp_parser_primary_expression (cp_parser *** 2444,2450 **** } /* The `>' token might be the end of a template-id or template-parameter-list now. */ ! parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; /* Consume the `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) --- 2786,2792 ---- } /* The `>' token might be the end of a template-id or template-parameter-list now. */ ! parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; /* Consume the `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) *************** cp_parser_primary_expression (cp_parser *** 2463,2469 **** case RID_FALSE: cp_lexer_consume_token (parser->lexer); return boolean_false_node; ! /* The `__null' literal. */ case RID_NULL: cp_lexer_consume_token (parser->lexer); --- 2805,2811 ---- case RID_FALSE: cp_lexer_consume_token (parser->lexer); return boolean_false_node; ! /* The `__null' literal. */ case RID_NULL: cp_lexer_consume_token (parser->lexer); *************** cp_parser_primary_expression (cp_parser *** 2474,2480 **** cp_lexer_consume_token (parser->lexer); if (parser->local_variables_forbidden_p) { ! error ("`this' may not be used in this context"); return error_mark_node; } /* Pointers cannot appear in constant-expressions. */ --- 2816,2822 ---- cp_lexer_consume_token (parser->lexer); if (parser->local_variables_forbidden_p) { ! error ("% may not be used in this context"); return error_mark_node; } /* Pointers cannot appear in constant-expressions. */ *************** cp_parser_primary_expression (cp_parser *** 2495,2501 **** __func__ are the names of variables -- but they are treated specially. Therefore, they are handled here, rather than relying on the generic id-expression logic ! below. Grammatically, these names are id-expressions. Consume the token. */ token = cp_lexer_consume_token (parser->lexer); --- 2837,2843 ---- __func__ are the names of variables -- but they are treated specially. Therefore, they are handled here, rather than relying on the generic id-expression logic ! below. Grammatically, these names are id-expressions. Consume the token. */ token = cp_lexer_consume_token (parser->lexer); *************** cp_parser_primary_expression (cp_parser *** 2513,2519 **** /* Look for the opening `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); /* Now, parse the assignment-expression. */ ! expression = cp_parser_assignment_expression (parser); /* Look for the `,'. */ cp_parser_require (parser, CPP_COMMA, "`,'"); /* Parse the type-id. */ --- 2855,2862 ---- /* Look for the opening `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); /* Now, parse the assignment-expression. */ ! expression = cp_parser_assignment_expression (parser, ! /*cast_p=*/false); /* Look for the `,'. */ cp_parser_require (parser, CPP_COMMA, "`,'"); /* Parse the type-id. */ *************** cp_parser_primary_expression (cp_parser *** 2529,2555 **** } case RID_OFFSETOF: ! { ! tree expression; ! bool saved_in_offsetof_p; ! ! /* Consume the "__offsetof__" token. */ ! cp_lexer_consume_token (parser->lexer); ! /* Consume the opening `('. */ ! cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); ! /* Parse the parenthesized (almost) constant-expression. */ ! saved_in_offsetof_p = parser->in_offsetof_p; ! parser->in_offsetof_p = true; ! expression ! = cp_parser_constant_expression (parser, ! /*allow_non_constant_p=*/false, ! /*non_constant_p=*/NULL); ! parser->in_offsetof_p = saved_in_offsetof_p; ! /* Consume the closing ')'. */ ! cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); ! ! return expression; ! } default: cp_parser_error (parser, "expected primary-expression"); --- 2872,2878 ---- } case RID_OFFSETOF: ! return cp_parser_builtin_offsetof (parser); default: cp_parser_error (parser, "expected primary-expression"); *************** cp_parser_primary_expression (cp_parser *** 2570,2577 **** id_expression: /* Parse the id-expression. */ ! id_expression ! = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, --- 2893,2900 ---- id_expression: /* Parse the id-expression. */ ! id_expression ! = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, *************** cp_parser_primary_expression (cp_parser *** 2585,2593 **** || TREE_CODE (id_expression) == TYPE_DECL) decl = id_expression; /* Look up the name. */ ! else { ! decl = cp_parser_lookup_name_simple (parser, id_expression); /* If name lookup gives us a SCOPE_REF, then the qualifying scope was dependent. Just propagate the name. */ --- 2908,2927 ---- || TREE_CODE (id_expression) == TYPE_DECL) decl = id_expression; /* Look up the name. */ ! else { ! bool ambiguous_p; ! ! decl = cp_parser_lookup_name (parser, id_expression, ! none_type, ! /*is_template=*/false, ! /*is_namespace=*/false, ! /*check_dependency=*/true, ! &ambiguous_p); ! /* If the lookup was ambiguous, an error will already have ! been issued. */ ! if (ambiguous_p) ! return error_mark_node; /* If name lookup gives us a SCOPE_REF, then the qualifying scope was dependent. Just propagate the name. */ *************** cp_parser_primary_expression (cp_parser *** 2612,2631 **** extern void f(int j = i); } ! Here, name look up will originally find the out of scope `i'. We need to issue a warning message, but then use the global `i'. */ decl = check_for_out_of_scope_variable (decl); if (local_variable_p (decl)) { ! error ("local variable `%D' may not appear in this context", decl); return error_mark_node; } } } ! ! decl = finish_id_expression (id_expression, decl, parser->scope, idk, qualifying_class, parser->integral_constant_expression_p, parser->allow_non_integral_constant_expression_p, --- 2946,2965 ---- extern void f(int j = i); } ! Here, name look up will originally find the out of scope `i'. We need to issue a warning message, but then use the global `i'. */ decl = check_for_out_of_scope_variable (decl); if (local_variable_p (decl)) { ! error ("local variable %qD may not appear in this context", decl); return error_mark_node; } } } ! ! decl = finish_id_expression (id_expression, decl, parser->scope, idk, qualifying_class, parser->integral_constant_expression_p, parser->allow_non_integral_constant_expression_p, *************** cp_parser_primary_expression (cp_parser *** 2668,2678 **** `template' keyword. If CHECK_DEPENDENCY_P is false, then names are looked up inside ! uninstantiated templates. If *TEMPLATE_P is non-NULL, it is set to true iff the `template' keyword is used to explicitly indicate that the entity ! named is a template. If DECLARATOR_P is true, the id-expression is appearing as part of a declarator, rather than as part of an expression. */ --- 3002,3012 ---- `template' keyword. If CHECK_DEPENDENCY_P is false, then names are looked up inside ! uninstantiated templates. If *TEMPLATE_P is non-NULL, it is set to true iff the `template' keyword is used to explicitly indicate that the entity ! named is a template. If DECLARATOR_P is true, the id-expression is appearing as part of a declarator, rather than as part of an expression. */ *************** cp_parser_id_expression (cp_parser *pars *** 2692,2702 **** *template_p = false; /* Look for the optional `::' operator. */ ! global_scope_p ! = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the optional nested-name-specifier. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, check_dependency_p, --- 3026,3036 ---- *template_p = false; /* Look for the optional `::' operator. */ ! global_scope_p ! = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the optional nested-name-specifier. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, check_dependency_p, *************** cp_parser_id_expression (cp_parser *pars *** 2746,2759 **** /* If it's an identifier, and the next token is not a "<", then we can avoid the template-id case. This is an optimization for this common case. */ ! if (token->type == CPP_NAME ! && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) return cp_parser_identifier (parser); cp_parser_parse_tentatively (parser); /* Try a template-id. */ ! id = cp_parser_template_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, declarator_p); --- 3080,3093 ---- /* If it's an identifier, and the next token is not a "<", then we can avoid the template-id case. This is an optimization for this common case. */ ! if (token->type == CPP_NAME ! && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) return cp_parser_identifier (parser); cp_parser_parse_tentatively (parser); /* Try a template-id. */ ! id = cp_parser_template_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, declarator_p); *************** cp_parser_id_expression (cp_parser *pars *** 2774,2780 **** if (token->keyword == RID_OPERATOR) return cp_parser_operator_function_id (parser); /* Fall through. */ ! default: cp_parser_error (parser, "expected id-expression"); return error_mark_node; --- 3108,3114 ---- if (token->keyword == RID_OPERATOR) return cp_parser_operator_function_id (parser); /* Fall through. */ ! default: cp_parser_error (parser, "expected id-expression"); return error_mark_node; *************** cp_parser_id_expression (cp_parser *pars *** 2809,2815 **** rather than as part of an expression. */ static tree ! cp_parser_unqualified_id (cp_parser* parser, bool template_keyword_p, bool check_dependency_p, bool declarator_p) --- 3143,3149 ---- rather than as part of an expression. */ static tree ! cp_parser_unqualified_id (cp_parser* parser, bool template_keyword_p, bool check_dependency_p, bool declarator_p) *************** cp_parser_unqualified_id (cp_parser* par *** 2818,2824 **** /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! switch (token->type) { case CPP_NAME: --- 3152,3158 ---- /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! switch (token->type) { case CPP_NAME: *************** cp_parser_unqualified_id (cp_parser* par *** 2850,2855 **** --- 3184,3190 ---- tree qualifying_scope; tree object_scope; tree scope; + bool done; /* Consume the `~' token. */ cp_lexer_consume_token (parser->lexer); *************** cp_parser_unqualified_id (cp_parser* par *** 2866,2876 **** template void f(T t) { t.T::~T(); ! } Here, it is not possible to look up `T' in the scope of `T' itself. We must look in both the current scope, and the ! scope of the containing complete expression. Yet another issue is: --- 3201,3211 ---- template void f(T t) { t.T::~T(); ! } Here, it is not possible to look up `T' in the scope of `T' itself. We must look in both the current scope, and the ! scope of the containing complete expression. Yet another issue is: *************** cp_parser_unqualified_id (cp_parser* par *** 2895,2903 **** /* If the name is of the form "X::~X" it's OK. */ if (scope && TYPE_P (scope) && cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_PAREN) ! && (cp_lexer_peek_token (parser->lexer)->value == TYPE_IDENTIFIER (scope))) { cp_lexer_consume_token (parser->lexer); --- 3230,3238 ---- /* If the name is of the form "X::~X" it's OK. */ if (scope && TYPE_P (scope) && cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_PAREN) ! && (cp_lexer_peek_token (parser->lexer)->value == TYPE_IDENTIFIER (scope))) { cp_lexer_consume_token (parser->lexer); *************** cp_parser_unqualified_id (cp_parser* par *** 2906,2972 **** /* If there was an explicit qualification (S::~T), first look in the scope given by the qualification (i.e., S). */ if (scope) { cp_parser_parse_tentatively (parser); ! type_decl = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! /*type_p=*/false, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); } /* In "N::S::~S", look in "N" as well. */ ! if (scope && qualifying_scope) { cp_parser_parse_tentatively (parser); parser->scope = qualifying_scope; parser->object_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! /*type_p=*/false, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); } /* In "p->S::~T", look in the scope given by "*p" as well. */ ! else if (object_scope) { cp_parser_parse_tentatively (parser); parser->scope = object_scope; parser->object_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! /*type_p=*/false, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); } /* Look in the surrounding context. */ ! parser->scope = NULL_TREE; ! parser->object_scope = NULL_TREE; ! parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, ! /*typename_keyword_p=*/false, ! /*template_keyword_p=*/false, ! /*type_p=*/false, ! /*check_dependency=*/false, ! /*class_head_p=*/false, ! declarator_p); /* If an error occurred, assume that the name of the destructor is the same as the name of the qualifying class. That allows us to keep parsing after running --- 3241,3312 ---- /* If there was an explicit qualification (S::~T), first look in the scope given by the qualification (i.e., S). */ + done = false; + type_decl = NULL_TREE; if (scope) { cp_parser_parse_tentatively (parser); ! type_decl = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! none_type, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! done = true; } /* In "N::S::~S", look in "N" as well. */ ! if (!done && scope && qualifying_scope) { cp_parser_parse_tentatively (parser); parser->scope = qualifying_scope; parser->object_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! none_type, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! done = true; } /* In "p->S::~T", look in the scope given by "*p" as well. */ ! else if (!done && object_scope) { cp_parser_parse_tentatively (parser); parser->scope = object_scope; parser->object_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! none_type, /*check_dependency=*/false, /*class_head_p=*/false, declarator_p); if (cp_parser_parse_definitely (parser)) ! done = true; } /* Look in the surrounding context. */ ! if (!done) ! { ! parser->scope = NULL_TREE; ! parser->object_scope = NULL_TREE; ! parser->qualifying_scope = NULL_TREE; ! type_decl ! = cp_parser_class_name (parser, ! /*typename_keyword_p=*/false, ! /*template_keyword_p=*/false, ! none_type, ! /*check_dependency=*/false, ! /*class_head_p=*/false, ! declarator_p); ! } /* If an error occurred, assume that the name of the destructor is the same as the name of the qualifying class. That allows us to keep parsing after running *************** cp_parser_unqualified_id (cp_parser* par *** 2980,2989 **** A typedef-name that names a class shall not be used as the identifier in the declarator for a destructor declaration. */ ! if (declarator_p && !DECL_IMPLICIT_TYPEDEF_P (type_decl) ! && !DECL_SELF_REFERENCE_P (type_decl)) ! error ("typedef-name `%D' used as destructor declarator", type_decl); return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); --- 3320,3330 ---- A typedef-name that names a class shall not be used as the identifier in the declarator for a destructor declaration. */ ! if (declarator_p && !DECL_IMPLICIT_TYPEDEF_P (type_decl) ! && !DECL_SELF_REFERENCE_P (type_decl) ! && !cp_parser_uncommitted_to_tentative_parse_p (parser)) ! error ("typedef-name %qD used as destructor declarator", type_decl); return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); *************** cp_parser_unqualified_id (cp_parser* par *** 3036,3061 **** Sets PARSER->SCOPE to the class (TYPE) or namespace (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves it unchanged if there is no nested-name-specifier. Returns the new ! scope iff there is a nested-name-specifier, or NULL_TREE otherwise. If IS_DECLARATION is TRUE, the nested-name-specifier is known to be part of a declaration and/or decl-specifier. */ static tree ! cp_parser_nested_name_specifier_opt (cp_parser *parser, ! bool typename_keyword_p, bool check_dependency_p, bool type_p, bool is_declaration) { bool success = false; tree access_check = NULL_TREE; ! ptrdiff_t start; ! cp_token* token; /* If the next token corresponds to a nested name specifier, there is no need to reparse it. However, if CHECK_DEPENDENCY_P is ! false, it may have been true before, in which case something like `A::B::C' may have resulted in a nested-name-specifier of `A::', where it should now be `A::B::'. So, when CHECK_DEPENDENCY_P is false, we have to fall through into the --- 3377,3402 ---- Sets PARSER->SCOPE to the class (TYPE) or namespace (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves it unchanged if there is no nested-name-specifier. Returns the new ! scope iff there is a nested-name-specifier, or NULL_TREE otherwise. If IS_DECLARATION is TRUE, the nested-name-specifier is known to be part of a declaration and/or decl-specifier. */ static tree ! cp_parser_nested_name_specifier_opt (cp_parser *parser, ! bool typename_keyword_p, bool check_dependency_p, bool type_p, bool is_declaration) { bool success = false; tree access_check = NULL_TREE; ! cp_token_position start = 0; ! cp_token *token; /* If the next token corresponds to a nested name specifier, there is no need to reparse it. However, if CHECK_DEPENDENCY_P is ! false, it may have been true before, in which case something like `A::B::C' may have resulted in a nested-name-specifier of `A::', where it should now be `A::B::'. So, when CHECK_DEPENDENCY_P is false, we have to fall through into the *************** cp_parser_nested_name_specifier_opt (cp_ *** 3068,3083 **** } /* Remember where the nested-name-specifier starts. */ ! if (cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) ! { ! token = cp_lexer_peek_token (parser->lexer); ! start = cp_lexer_token_difference (parser->lexer, ! parser->lexer->first_token, ! token); ! } ! else ! start = -1; push_deferring_access_checks (dk_deferred); --- 3409,3416 ---- } /* Remember where the nested-name-specifier starts. */ ! if (cp_parser_uncommitted_to_tentative_parse_p (parser)) ! start = cp_lexer_token_position (parser->lexer, false); push_deferring_access_checks (dk_deferred); *************** cp_parser_nested_name_specifier_opt (cp_ *** 3152,3158 **** parser->scope = resolve_typename_type (parser->scope, /*only_current_p=*/false); /* Parse the qualifying entity. */ ! new_scope = cp_parser_class_or_namespace_name (parser, typename_keyword_p, template_keyword_p, --- 3485,3491 ---- parser->scope = resolve_typename_type (parser->scope, /*only_current_p=*/false); /* Parse the qualifying entity. */ ! new_scope = cp_parser_class_or_namespace_name (parser, typename_keyword_p, template_keyword_p, *************** cp_parser_nested_name_specifier_opt (cp_ *** 3177,3199 **** that is a `::', then any valid interpretation would have found a class-or-namespace-name. */ while (cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_SCOPE) ! && (cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_COMPL)) { token = cp_lexer_consume_token (parser->lexer); ! if (!error_p) { tree decl; decl = cp_parser_lookup_name_simple (parser, token->value); if (TREE_CODE (decl) == TEMPLATE_DECL) ! error ("`%D' used without template parameters", ! decl); else ! cp_parser_name_lookup_error ! (parser, token->value, decl, "is not a class or namespace"); parser->scope = NULL_TREE; error_p = true; --- 3510,3531 ---- that is a `::', then any valid interpretation would have found a class-or-namespace-name. */ while (cp_lexer_next_token_is (parser->lexer, CPP_NAME) ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_SCOPE) ! && (cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_COMPL)) { token = cp_lexer_consume_token (parser->lexer); ! if (!error_p) { tree decl; decl = cp_parser_lookup_name_simple (parser, token->value); if (TREE_CODE (decl) == TEMPLATE_DECL) ! error ("%qD used without template parameters", decl); else ! cp_parser_name_lookup_error ! (parser, token->value, decl, "is not a class or namespace"); parser->scope = NULL_TREE; error_p = true; *************** cp_parser_nested_name_specifier_opt (cp_ *** 3216,3222 **** success = true; /* Make sure we look in the right scope the next time through the loop. */ ! parser->scope = (TREE_CODE (new_scope) == TYPE_DECL ? TREE_TYPE (new_scope) : new_scope); /* If it is a class scope, try to complete it; we are about to --- 3548,3554 ---- success = true; /* Make sure we look in the right scope the next time through the loop. */ ! parser->scope = (TREE_CODE (new_scope) == TYPE_DECL ? TREE_TYPE (new_scope) : new_scope); /* If it is a class scope, try to complete it; we are about to *************** cp_parser_nested_name_specifier_opt (cp_ *** 3239,3259 **** token. That way, should we re-parse the token stream, we will not have to repeat the effort required to do the parse, nor will we issue duplicate error messages. */ ! if (success && start >= 0) { ! /* Find the token that corresponds to the start of the ! template-id. */ ! token = cp_lexer_advance_token (parser->lexer, ! parser->lexer->first_token, ! start); ! /* Reset the contents of the START token. */ token->type = CPP_NESTED_NAME_SPECIFIER; token->value = build_tree_list (access_check, parser->scope); TREE_TYPE (token->value) = parser->qualifying_scope; token->keyword = RID_MAX; /* Purge all subsequent tokens. */ ! cp_lexer_purge_tokens_after (parser->lexer, token); } pop_deferring_access_checks (); --- 3571,3588 ---- token. That way, should we re-parse the token stream, we will not have to repeat the effort required to do the parse, nor will we issue duplicate error messages. */ ! if (success && start) { ! cp_token *token = cp_lexer_token_at (parser->lexer, start); ! /* Reset the contents of the START token. */ token->type = CPP_NESTED_NAME_SPECIFIER; token->value = build_tree_list (access_check, parser->scope); TREE_TYPE (token->value) = parser->qualifying_scope; token->keyword = RID_MAX; + /* Purge all subsequent tokens. */ ! cp_lexer_purge_tokens_after (parser->lexer, start); } pop_deferring_access_checks (); *************** cp_parser_nested_name_specifier_opt (cp_ *** 3268,3275 **** is present. */ static tree ! cp_parser_nested_name_specifier (cp_parser *parser, ! bool typename_keyword_p, bool check_dependency_p, bool type_p, bool is_declaration) --- 3597,3604 ---- is present. */ static tree ! cp_parser_nested_name_specifier (cp_parser *parser, ! bool typename_keyword_p, bool check_dependency_p, bool type_p, bool is_declaration) *************** cp_parser_nested_name_specifier (cp_pars *** 3311,3317 **** ERROR_MARK_NODE is returned. */ static tree ! cp_parser_class_or_namespace_name (cp_parser *parser, bool typename_keyword_p, bool template_keyword_p, bool check_dependency_p, --- 3640,3646 ---- ERROR_MARK_NODE is returned. */ static tree ! cp_parser_class_or_namespace_name (cp_parser *parser, bool typename_keyword_p, bool template_keyword_p, bool check_dependency_p, *************** cp_parser_class_or_namespace_name (cp_pa *** 3335,3344 **** only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope)); if (!only_class_p) cp_parser_parse_tentatively (parser); ! scope = cp_parser_class_name (parser, typename_keyword_p, template_keyword_p, ! type_p, check_dependency_p, /*class_head_p=*/false, is_declaration); --- 3664,3673 ---- only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope)); if (!only_class_p) cp_parser_parse_tentatively (parser); ! scope = cp_parser_class_name (parser, typename_keyword_p, template_keyword_p, ! type_p ? class_type : none_type, check_dependency_p, /*class_head_p=*/false, is_declaration); *************** cp_parser_class_or_namespace_name (cp_pa *** 3369,3375 **** postfix-expression [ expression ] postfix-expression ( expression-list [opt] ) simple-type-specifier ( expression-list [opt] ) ! typename :: [opt] nested-name-specifier identifier ( expression-list [opt] ) typename :: [opt] nested-name-specifier template [opt] template-id ( expression-list [opt] ) --- 3698,3704 ---- postfix-expression [ expression ] postfix-expression ( expression-list [opt] ) simple-type-specifier ( expression-list [opt] ) ! typename :: [opt] nested-name-specifier identifier ( expression-list [opt] ) typename :: [opt] nested-name-specifier template [opt] template-id ( expression-list [opt] ) *************** cp_parser_class_or_namespace_name (cp_pa *** 3387,3393 **** typeid ( type-id ) GNU Extension: ! postfix-expression: ( type-id ) { initializer-list , [opt] } --- 3716,3722 ---- typeid ( type-id ) GNU Extension: ! postfix-expression: ( type-id ) { initializer-list , [opt] } *************** cp_parser_class_or_namespace_name (cp_pa *** 3396,3407 **** but they are essentially the same concept.) If ADDRESS_P is true, the postfix expression is the operand of the ! `&' operator. Returns a representation of the expression. */ static tree ! cp_parser_postfix_expression (cp_parser *parser, bool address_p) { cp_token *token; enum rid keyword; --- 3725,3737 ---- but they are essentially the same concept.) If ADDRESS_P is true, the postfix expression is the operand of the ! `&' operator. CAST_P is true if this expression is the target of a ! cast. Returns a representation of the expression. */ static tree ! cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) { cp_token *token; enum rid keyword; *************** cp_parser_postfix_expression (cp_parser *** 3431,3437 **** of view of parsing. Begin by consuming the token identifying the cast. */ cp_lexer_consume_token (parser->lexer); ! /* New types cannot be defined in the cast. */ saved_message = parser->type_definition_forbidden_message; parser->type_definition_forbidden_message --- 3761,3767 ---- of view of parsing. Begin by consuming the token identifying the cast. */ cp_lexer_consume_token (parser->lexer); ! /* New types cannot be defined in the cast. */ saved_message = parser->type_definition_forbidden_message; parser->type_definition_forbidden_message *************** cp_parser_postfix_expression (cp_parser *** 3448,3454 **** /* And the expression which is being cast. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); ! expression = cp_parser_expression (parser); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Only type conversions to integral or enumeration types --- 3778,3784 ---- /* And the expression which is being cast. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); ! expression = cp_parser_expression (parser, /*cast_p=*/true); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Only type conversions to integral or enumeration types *************** cp_parser_postfix_expression (cp_parser *** 3456,3465 **** if (parser->integral_constant_expression_p && !dependent_type_p (type) && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) ! /* A cast to pointer or reference type is allowed in the ! implementation of "offsetof". */ ! && !(parser->in_offsetof_p && POINTER_TYPE_P (type)) ! && (cp_parser_non_integral_constant_expression (parser, "a cast to a type other than an integral or " "enumeration type"))) --- 3786,3792 ---- if (parser->integral_constant_expression_p && !dependent_type_p (type) && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) ! && (cp_parser_non_integral_constant_expression (parser, "a cast to a type other than an integral or " "enumeration type"))) *************** cp_parser_postfix_expression (cp_parser *** 3484,3490 **** = build_const_cast (type, expression); break; default: ! abort (); } } break; --- 3811,3817 ---- = build_const_cast (type, expression); break; default: ! gcc_unreachable (); } } break; *************** cp_parser_postfix_expression (cp_parser *** 3524,3561 **** tree expression; /* Look for an expression. */ ! expression = cp_parser_expression (parser); /* Compute its typeid. */ postfix_expression = build_typeid (expression); /* Look for the `)' token. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); } /* `typeid' may not appear in an integral constant expression. */ ! if (cp_parser_non_integral_constant_expression(parser, "`typeid' operator")) return error_mark_node; /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; } break; ! case RID_TYPENAME: { bool template_p = false; tree id; tree type; /* Consume the `typename' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the optional `::' operator. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); ! /* Look for the nested-name-specifier. */ ! cp_parser_nested_name_specifier (parser, ! /*typename_keyword_p=*/true, ! /*check_dependency_p=*/true, ! /*type_p=*/true, ! /*is_declaration=*/true); /* Look for the optional `template' keyword. */ template_p = cp_parser_optional_template_keyword (parser); /* We don't know whether we're looking at a template-id or an --- 3851,3892 ---- tree expression; /* Look for an expression. */ ! expression = cp_parser_expression (parser, /*cast_p=*/false); /* Compute its typeid. */ postfix_expression = build_typeid (expression); /* Look for the `)' token. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); } /* `typeid' may not appear in an integral constant expression. */ ! if (cp_parser_non_integral_constant_expression(parser, "`typeid' operator")) return error_mark_node; /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; } break; ! case RID_TYPENAME: { bool template_p = false; tree id; tree type; + tree scope; /* Consume the `typename' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the optional `::' operator. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); ! /* Look for the nested-name-specifier. In case of error here, ! consume the trailing id to avoid subsequent error messages ! for usual cases. */ ! scope = cp_parser_nested_name_specifier (parser, ! /*typename_keyword_p=*/true, ! /*check_dependency_p=*/true, ! /*type_p=*/true, ! /*is_declaration=*/true); ! /* Look for the optional `template' keyword. */ template_p = cp_parser_optional_template_keyword (parser); /* We don't know whether we're looking at a template-id or an *************** cp_parser_postfix_expression (cp_parser *** 3568,3582 **** /* If that didn't work, try an identifier. */ if (!cp_parser_parse_definitely (parser)) id = cp_parser_identifier (parser); /* If we look up a template-id in a non-dependent qualifying scope, there's no need to create a dependent type. */ ! if (TREE_CODE (id) == TYPE_DECL && !dependent_type_p (parser->scope)) type = TREE_TYPE (id); /* Create a TYPENAME_TYPE to represent the type to which the functional cast is being performed. */ else ! type = make_typename_type (parser->scope, id, /*complain=*/1); postfix_expression = cp_parser_functional_cast (parser, type); --- 3899,3918 ---- /* If that didn't work, try an identifier. */ if (!cp_parser_parse_definitely (parser)) id = cp_parser_identifier (parser); + + /* Don't process id if nested name specifier is invalid. */ + if (scope == error_mark_node) + return error_mark_node; /* If we look up a template-id in a non-dependent qualifying scope, there's no need to create a dependent type. */ ! else if (TREE_CODE (id) == TYPE_DECL && !dependent_type_p (parser->scope)) type = TREE_TYPE (id); /* Create a TYPENAME_TYPE to represent the type to which the functional cast is being performed. */ else ! type = make_typename_type (parser->scope, id, ! typename_type, /*complain=*/1); postfix_expression = cp_parser_functional_cast (parser, type); *************** cp_parser_postfix_expression (cp_parser *** 3593,3604 **** that doesn't work we fall back to the primary-expression. */ cp_parser_parse_tentatively (parser); /* Look for the simple-type-specifier. */ ! type = cp_parser_simple_type_specifier (parser, ! CP_PARSER_FLAGS_NONE, ! /*identifier_p=*/false); /* Parse the cast itself. */ if (!cp_parser_error_occurred (parser)) ! postfix_expression = cp_parser_functional_cast (parser, type); /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) --- 3929,3940 ---- that doesn't work we fall back to the primary-expression. */ cp_parser_parse_tentatively (parser); /* Look for the simple-type-specifier. */ ! type = cp_parser_simple_type_specifier (parser, ! /*decl_specs=*/NULL, ! CP_PARSER_FLAGS_NONE); /* Parse the cast itself. */ if (!cp_parser_error_occurred (parser)) ! postfix_expression = cp_parser_functional_cast (parser, type); /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) *************** cp_parser_postfix_expression (cp_parser *** 3630,3636 **** { bool non_constant_p; /* Parse the initializer-list. */ ! initializer_list = cp_parser_initializer_list (parser, &non_constant_p); /* Allow a trailing `,'. */ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) --- 3966,3972 ---- { bool non_constant_p; /* Parse the initializer-list. */ ! initializer_list = cp_parser_initializer_list (parser, &non_constant_p); /* Allow a trailing `,'. */ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) *************** cp_parser_postfix_expression (cp_parser *** 3647,3660 **** if (pedantic) pedwarn ("ISO C++ forbids compound-literals"); /* Form the representation of the compound-literal. */ ! postfix_expression = finish_compound_literal (type, initializer_list); break; } } /* It must be a primary-expression. */ ! postfix_expression = cp_parser_primary_expression (parser, &idk, &qualifying_class); } --- 3983,3997 ---- if (pedantic) pedwarn ("ISO C++ forbids compound-literals"); /* Form the representation of the compound-literal. */ ! postfix_expression = finish_compound_literal (type, initializer_list); break; } } /* It must be a primary-expression. */ ! postfix_expression = cp_parser_primary_expression (parser, ! cast_p, &idk, &qualifying_class); } *************** cp_parser_postfix_expression (cp_parser *** 3692,3748 **** && TREE_CODE (postfix_expression) == IDENTIFIER_NODE && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) /* It is not a Koenig lookup function call. */ ! postfix_expression = unqualified_name_lookup_error (postfix_expression); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); switch (token->type) { case CPP_OPEN_SQUARE: ! /* postfix-expression [ expression ] */ ! { ! tree index; ! ! /* Consume the `[' token. */ ! cp_lexer_consume_token (parser->lexer); ! /* Parse the index expression. */ ! index = cp_parser_expression (parser); ! /* Look for the closing `]'. */ ! cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); ! ! /* Build the ARRAY_REF. */ ! postfix_expression ! = grok_array_decl (postfix_expression, index); ! idk = CP_ID_KIND_NONE; ! /* Array references are not permitted in ! constant-expressions (but they are allowed ! in offsetof). */ ! if (!parser->in_offsetof_p ! && cp_parser_non_integral_constant_expression ! (parser, "an array reference")) ! postfix_expression = error_mark_node; ! } break; case CPP_OPEN_PAREN: /* postfix-expression ( expression-list [opt] ) */ { bool koenig_p; ! tree args = (cp_parser_parenthesized_expression_list ! (parser, false, /*non_constant_p=*/NULL)); if (args == error_mark_node) { postfix_expression = error_mark_node; break; } ! /* Function calls are not permitted in constant-expressions. */ ! if (cp_parser_non_integral_constant_expression (parser, ! "a function call")) { postfix_expression = error_mark_node; break; --- 4029,4070 ---- && TREE_CODE (postfix_expression) == IDENTIFIER_NODE && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) /* It is not a Koenig lookup function call. */ ! postfix_expression = unqualified_name_lookup_error (postfix_expression); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); switch (token->type) { case CPP_OPEN_SQUARE: ! postfix_expression ! = cp_parser_postfix_open_square_expression (parser, ! postfix_expression, ! false); ! idk = CP_ID_KIND_NONE; break; case CPP_OPEN_PAREN: /* postfix-expression ( expression-list [opt] ) */ { bool koenig_p; ! tree args = (cp_parser_parenthesized_expression_list ! (parser, false, ! /*cast_p=*/false, ! /*non_constant_p=*/NULL)); if (args == error_mark_node) { postfix_expression = error_mark_node; break; } ! /* Function calls are not permitted in constant-expressions. */ ! if (! builtin_valid_in_constant_expr_p (postfix_expression) ! && cp_parser_non_integral_constant_expression (parser, ! "a function call")) { postfix_expression = error_mark_node; break; *************** cp_parser_postfix_expression (cp_parser *** 3762,3788 **** else postfix_expression = unqualified_fn_lookup_error (postfix_expression); ! } /* We do not perform argument-dependent lookup if normal lookup finds a non-function, in accordance with the expected resolution of DR 218. */ else if (args && is_overloaded_fn (postfix_expression)) { tree fn = get_first_fn (postfix_expression); if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) fn = OVL_CURRENT (TREE_OPERAND (fn, 0)); /* Only do argument dependent lookup if regular lookup does not find a set of member functions. [basic.lookup.koenig]/2a */ ! if (!DECL_FUNCTION_MEMBER_P (fn)) ! { ! koenig_p = true; ! postfix_expression ! = perform_koenig_lookup (postfix_expression, args); ! } } } ! if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); --- 4084,4112 ---- else postfix_expression = unqualified_fn_lookup_error (postfix_expression); ! } /* We do not perform argument-dependent lookup if normal lookup finds a non-function, in accordance with the expected resolution of DR 218. */ else if (args && is_overloaded_fn (postfix_expression)) { tree fn = get_first_fn (postfix_expression); + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) fn = OVL_CURRENT (TREE_OPERAND (fn, 0)); + /* Only do argument dependent lookup if regular lookup does not find a set of member functions. [basic.lookup.koenig]/2a */ ! if (!DECL_FUNCTION_MEMBER_P (fn)) ! { ! koenig_p = true; ! postfix_expression ! = perform_koenig_lookup (postfix_expression, args); ! } } } ! if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); *************** cp_parser_postfix_expression (cp_parser *** 3796,3810 **** || any_type_dependent_arguments_p (args))) { postfix_expression ! = build_min_nt (CALL_EXPR, postfix_expression, args); break; } if (BASELINK_P (fn)) postfix_expression ! = (build_new_method_call ! (instance, fn, args, NULL_TREE, ! (idk == CP_ID_KIND_QUALIFIED ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); else postfix_expression --- 4120,4135 ---- || any_type_dependent_arguments_p (args))) { postfix_expression ! = build_min_nt (CALL_EXPR, postfix_expression, ! args, NULL_TREE); break; } if (BASELINK_P (fn)) postfix_expression ! = (build_new_method_call ! (instance, fn, args, NULL_TREE, ! (idk == CP_ID_KIND_QUALIFIED ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); else postfix_expression *************** cp_parser_postfix_expression (cp_parser *** 3826,3833 **** koenig_p); else /* All other function calls. */ ! postfix_expression ! = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, koenig_p); --- 4151,4158 ---- koenig_p); else /* All other function calls. */ ! postfix_expression ! = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, koenig_p); *************** cp_parser_postfix_expression (cp_parser *** 3835,3984 **** idk = CP_ID_KIND_NONE; } break; ! case CPP_DOT: case CPP_DEREF: ! /* postfix-expression . template [opt] id-expression ! postfix-expression . pseudo-destructor-name postfix-expression -> template [opt] id-expression postfix-expression -> pseudo-destructor-name */ - { - tree name; - bool dependent_p; - bool template_p; - bool pseudo_destructor_p; - tree scope = NULL_TREE; - enum cpp_ttype token_type = token->type; ! /* If this is a `->' operator, dereference the pointer. */ ! if (token->type == CPP_DEREF) ! postfix_expression = build_x_arrow (postfix_expression); ! /* Check to see whether or not the expression is ! type-dependent. */ ! dependent_p = type_dependent_expression_p (postfix_expression); ! /* The identifier following the `->' or `.' is not ! qualified. */ ! parser->scope = NULL_TREE; ! parser->qualifying_scope = NULL_TREE; ! parser->object_scope = NULL_TREE; ! idk = CP_ID_KIND_NONE; ! /* Enter the scope corresponding to the type of the object ! given by the POSTFIX_EXPRESSION. */ ! if (!dependent_p ! && TREE_TYPE (postfix_expression) != NULL_TREE) ! { ! scope = TREE_TYPE (postfix_expression); ! /* According to the standard, no expression should ! ever have reference type. Unfortunately, we do not ! currently match the standard in this respect in ! that our internal representation of an expression ! may have reference type even when the standard says ! it does not. Therefore, we have to manually obtain ! the underlying type here. */ ! scope = non_reference (scope); ! /* The type of the POSTFIX_EXPRESSION must be ! complete. */ ! scope = complete_type_or_else (scope, NULL_TREE); ! /* Let the name lookup machinery know that we are ! processing a class member access expression. */ ! parser->context->object_type = scope; ! /* If something went wrong, we want to be able to ! discern that case, as opposed to the case where ! there was no SCOPE due to the type of expression ! being dependent. */ ! if (!scope) ! scope = error_mark_node; ! /* If the SCOPE was erroneous, make the various ! semantic analysis functions exit quickly -- and ! without issuing additional error messages. */ ! if (scope == error_mark_node) ! postfix_expression = error_mark_node; ! } ! ! /* Consume the `.' or `->' operator. */ ! cp_lexer_consume_token (parser->lexer); ! ! /* Assume this expression is not a pseudo-destructor access. */ ! pseudo_destructor_p = false; ! ! /* If the SCOPE is a scalar type, then, if this is a valid program, ! we must be looking at a pseudo-destructor-name. */ ! if (scope && SCALAR_TYPE_P (scope)) ! { ! tree s = NULL_TREE; ! tree type; ! ! cp_parser_parse_tentatively (parser); ! /* Parse the pseudo-destructor-name. */ ! cp_parser_pseudo_destructor_name (parser, &s, &type); ! if (cp_parser_parse_definitely (parser)) ! { ! pseudo_destructor_p = true; ! postfix_expression ! = finish_pseudo_destructor_expr (postfix_expression, ! s, TREE_TYPE (type)); ! } ! } ! ! if (!pseudo_destructor_p) ! { ! /* If the SCOPE is not a scalar type, we are looking ! at an ordinary class member access expression, ! rather than a pseudo-destructor-name. */ ! template_p = cp_parser_optional_template_keyword (parser); ! /* Parse the id-expression. */ ! name = cp_parser_id_expression (parser, ! template_p, ! /*check_dependency_p=*/true, ! /*template_p=*/NULL, ! /*declarator_p=*/false); ! /* In general, build a SCOPE_REF if the member name is ! qualified. However, if the name was not dependent ! and has already been resolved; there is no need to ! build the SCOPE_REF. For example; ! ! struct X { void f(); }; ! template void f(T* t) { t->X::f(); } ! ! Even though "t" is dependent, "X::f" is not and has ! been resolved to a BASELINK; there is no need to ! include scope information. */ ! ! /* But we do need to remember that there was an explicit ! scope for virtual function calls. */ ! if (parser->scope) ! idk = CP_ID_KIND_QUALIFIED; ! ! if (name != error_mark_node ! && !BASELINK_P (name) ! && parser->scope) ! { ! name = build_nt (SCOPE_REF, parser->scope, name); ! parser->scope = NULL_TREE; ! parser->qualifying_scope = NULL_TREE; ! parser->object_scope = NULL_TREE; ! } ! if (scope && name && BASELINK_P (name)) ! adjust_result_of_qualified_name_lookup ! (name, BINFO_TYPE (BASELINK_BINFO (name)), scope); ! postfix_expression ! = finish_class_member_access_expr (postfix_expression, name); ! } ! /* We no longer need to look up names in the scope of the ! object on the left-hand side of the `.' or `->' ! operator. */ ! parser->context->object_type = NULL_TREE; ! /* These operators may not appear in constant-expressions. */ ! if (/* The "->" operator is allowed in the implementation ! of "offsetof". The "." operator may appear in the ! name of the member. */ ! !parser->in_offsetof_p ! && (cp_parser_non_integral_constant_expression ! (parser, ! token_type == CPP_DEREF ? "'->'" : "`.'"))) ! postfix_expression = error_mark_node; ! } break; case CPP_PLUS_PLUS: --- 4160,4180 ---- idk = CP_ID_KIND_NONE; } break; ! case CPP_DOT: case CPP_DEREF: ! /* postfix-expression . template [opt] id-expression ! postfix-expression . pseudo-destructor-name postfix-expression -> template [opt] id-expression postfix-expression -> pseudo-destructor-name */ ! /* Consume the `.' or `->' operator. */ ! cp_lexer_consume_token (parser->lexer); ! postfix_expression ! = cp_parser_postfix_dot_deref_expression (parser, token->type, ! postfix_expression, ! false, &idk); break; case CPP_PLUS_PLUS: *************** cp_parser_postfix_expression (cp_parser *** 3986,3993 **** /* Consume the `++' token. */ cp_lexer_consume_token (parser->lexer); /* Generate a representation for the complete expression. */ ! postfix_expression ! = finish_increment_expr (postfix_expression, POSTINCREMENT_EXPR); /* Increments may not appear in constant-expressions. */ if (cp_parser_non_integral_constant_expression (parser, --- 4182,4189 ---- /* Consume the `++' token. */ cp_lexer_consume_token (parser->lexer); /* Generate a representation for the complete expression. */ ! postfix_expression ! = finish_increment_expr (postfix_expression, POSTINCREMENT_EXPR); /* Increments may not appear in constant-expressions. */ if (cp_parser_non_integral_constant_expression (parser, *************** cp_parser_postfix_expression (cp_parser *** 4001,4008 **** /* Consume the `--' token. */ cp_lexer_consume_token (parser->lexer); /* Generate a representation for the complete expression. */ ! postfix_expression ! = finish_increment_expr (postfix_expression, POSTDECREMENT_EXPR); /* Decrements may not appear in constant-expressions. */ if (cp_parser_non_integral_constant_expression (parser, --- 4197,4204 ---- /* Consume the `--' token. */ cp_lexer_consume_token (parser->lexer); /* Generate a representation for the complete expression. */ ! postfix_expression ! = finish_increment_expr (postfix_expression, POSTDECREMENT_EXPR); /* Decrements may not appear in constant-expressions. */ if (cp_parser_non_integral_constant_expression (parser, *************** cp_parser_postfix_expression (cp_parser *** 4017,4026 **** } /* We should never get here. */ ! abort (); return error_mark_node; } /* Parse a parenthesized expression-list. expression-list: --- 4213,4420 ---- } /* We should never get here. */ ! gcc_unreachable (); return error_mark_node; } + /* A subroutine of cp_parser_postfix_expression that also gets hijacked + by cp_parser_builtin_offsetof. We're looking for + + postfix-expression [ expression ] + + FOR_OFFSETOF is set if we're being called in that context, which + changes how we deal with integer constant expressions. */ + + static tree + cp_parser_postfix_open_square_expression (cp_parser *parser, + tree postfix_expression, + bool for_offsetof) + { + tree index; + + /* Consume the `[' token. */ + cp_lexer_consume_token (parser->lexer); + + /* Parse the index expression. */ + /* ??? For offsetof, there is a question of what to allow here. If + offsetof is not being used in an integral constant expression context, + then we *could* get the right answer by computing the value at runtime. + If we are in an integral constant expression context, then we might + could accept any constant expression; hard to say without analysis. + Rather than open the barn door too wide right away, allow only integer + constant expressions here. */ + if (for_offsetof) + index = cp_parser_constant_expression (parser, false, NULL); + else + index = cp_parser_expression (parser, /*cast_p=*/false); + + /* Look for the closing `]'. */ + cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + + /* Build the ARRAY_REF. */ + postfix_expression = grok_array_decl (postfix_expression, index); + + /* When not doing offsetof, array references are not permitted in + constant-expressions. */ + if (!for_offsetof + && (cp_parser_non_integral_constant_expression + (parser, "an array reference"))) + postfix_expression = error_mark_node; + + return postfix_expression; + } + + /* A subroutine of cp_parser_postfix_expression that also gets hijacked + by cp_parser_builtin_offsetof. We're looking for + + postfix-expression . template [opt] id-expression + postfix-expression . pseudo-destructor-name + postfix-expression -> template [opt] id-expression + postfix-expression -> pseudo-destructor-name + + FOR_OFFSETOF is set if we're being called in that context. That sorta + limits what of the above we'll actually accept, but nevermind. + TOKEN_TYPE is the "." or "->" token, which will already have been + removed from the stream. */ + + static tree + cp_parser_postfix_dot_deref_expression (cp_parser *parser, + enum cpp_ttype token_type, + tree postfix_expression, + bool for_offsetof, cp_id_kind *idk) + { + tree name; + bool dependent_p; + bool template_p; + bool pseudo_destructor_p; + tree scope = NULL_TREE; + + /* If this is a `->' operator, dereference the pointer. */ + if (token_type == CPP_DEREF) + postfix_expression = build_x_arrow (postfix_expression); + /* Check to see whether or not the expression is type-dependent. */ + dependent_p = type_dependent_expression_p (postfix_expression); + /* The identifier following the `->' or `.' is not qualified. */ + parser->scope = NULL_TREE; + parser->qualifying_scope = NULL_TREE; + parser->object_scope = NULL_TREE; + *idk = CP_ID_KIND_NONE; + /* Enter the scope corresponding to the type of the object + given by the POSTFIX_EXPRESSION. */ + if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE) + { + scope = TREE_TYPE (postfix_expression); + /* According to the standard, no expression should ever have + reference type. Unfortunately, we do not currently match + the standard in this respect in that our internal representation + of an expression may have reference type even when the standard + says it does not. Therefore, we have to manually obtain the + underlying type here. */ + scope = non_reference (scope); + /* The type of the POSTFIX_EXPRESSION must be complete. */ + scope = complete_type_or_else (scope, NULL_TREE); + /* Let the name lookup machinery know that we are processing a + class member access expression. */ + parser->context->object_type = scope; + /* If something went wrong, we want to be able to discern that case, + as opposed to the case where there was no SCOPE due to the type + of expression being dependent. */ + if (!scope) + scope = error_mark_node; + /* If the SCOPE was erroneous, make the various semantic analysis + functions exit quickly -- and without issuing additional error + messages. */ + if (scope == error_mark_node) + postfix_expression = error_mark_node; + } + + /* Assume this expression is not a pseudo-destructor access. */ + pseudo_destructor_p = false; + + /* If the SCOPE is a scalar type, then, if this is a valid program, + we must be looking at a pseudo-destructor-name. */ + if (scope && SCALAR_TYPE_P (scope)) + { + tree s; + tree type; + + cp_parser_parse_tentatively (parser); + /* Parse the pseudo-destructor-name. */ + s = NULL_TREE; + cp_parser_pseudo_destructor_name (parser, &s, &type); + if (cp_parser_parse_definitely (parser)) + { + pseudo_destructor_p = true; + postfix_expression + = finish_pseudo_destructor_expr (postfix_expression, + s, TREE_TYPE (type)); + } + } + + if (!pseudo_destructor_p) + { + /* If the SCOPE is not a scalar type, we are looking at an + ordinary class member access expression, rather than a + pseudo-destructor-name. */ + template_p = cp_parser_optional_template_keyword (parser); + /* Parse the id-expression. */ + name = cp_parser_id_expression (parser, template_p, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false); + /* In general, build a SCOPE_REF if the member name is qualified. + However, if the name was not dependent and has already been + resolved; there is no need to build the SCOPE_REF. For example; + + struct X { void f(); }; + template void f(T* t) { t->X::f(); } + + Even though "t" is dependent, "X::f" is not and has been resolved + to a BASELINK; there is no need to include scope information. */ + + /* But we do need to remember that there was an explicit scope for + virtual function calls. */ + if (parser->scope) + *idk = CP_ID_KIND_QUALIFIED; + + /* If the name is a template-id that names a type, we will get a + TYPE_DECL here. That is invalid code. */ + if (TREE_CODE (name) == TYPE_DECL) + { + error ("invalid use of %qD", name); + postfix_expression = error_mark_node; + } + else + { + if (name != error_mark_node && !BASELINK_P (name) && parser->scope) + { + name = build_nt (SCOPE_REF, parser->scope, name); + parser->scope = NULL_TREE; + parser->qualifying_scope = NULL_TREE; + parser->object_scope = NULL_TREE; + } + if (scope && name && BASELINK_P (name)) + adjust_result_of_qualified_name_lookup + (name, BINFO_TYPE (BASELINK_BINFO (name)), scope); + postfix_expression + = finish_class_member_access_expr (postfix_expression, name); + } + } + + /* We no longer need to look up names in the scope of the object on + the left-hand side of the `.' or `->' operator. */ + parser->context->object_type = NULL_TREE; + + /* Outside of offsetof, these operators may not appear in + constant-expressions. */ + if (!for_offsetof + && (cp_parser_non_integral_constant_expression + (parser, token_type == CPP_DEREF ? "'->'" : "`.'"))) + postfix_expression = error_mark_node; + + return postfix_expression; + } + /* Parse a parenthesized expression-list. expression-list: *************** cp_parser_postfix_expression (cp_parser *** 4032,4037 **** --- 4426,4433 ---- identifier identifier, expression-list + CAST_P is true if this expression is the target of a cast. + Returns a TREE_LIST. The TREE_VALUE of each node is a representation of an assignment-expression. Note that a TREE_LIST is returned even if there is only a single expression in the list. *************** cp_parser_postfix_expression (cp_parser *** 4043,4053 **** constant. */ static tree ! cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_list, bool *non_constant_p) { tree expression_list = NULL_TREE; tree identifier = NULL_TREE; /* Assume all the expressions will be constant. */ --- 4439,4451 ---- constant. */ static tree ! cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_list, + bool cast_p, bool *non_constant_p) { tree expression_list = NULL_TREE; + bool fold_expr_p = is_attribute_list; tree identifier = NULL_TREE; /* Assume all the expressions will be constant. */ *************** cp_parser_parenthesized_expression_list *** 4056,4075 **** if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) return error_mark_node; ! /* Consume expressions until there are no more. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) while (true) { tree expr; ! /* At the beginning of attribute lists, check to see if the next token is an identifier. */ if (is_attribute_list && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME) { cp_token *token; ! /* Consume the identifier. */ token = cp_lexer_consume_token (parser->lexer); /* Save the identifier. */ --- 4454,4473 ---- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) return error_mark_node; ! /* Consume expressions until there are no more. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) while (true) { tree expr; ! /* At the beginning of attribute lists, check to see if the next token is an identifier. */ if (is_attribute_list && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME) { cp_token *token; ! /* Consume the identifier. */ token = cp_lexer_consume_token (parser->lexer); /* Save the identifier. */ *************** cp_parser_parenthesized_expression_list *** 4081,4094 **** if (non_constant_p) { bool expr_non_constant_p; ! expr = (cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, &expr_non_constant_p)); if (expr_non_constant_p) *non_constant_p = true; } else ! expr = cp_parser_assignment_expression (parser); /* Add it to the list. We add error_mark_node expressions to the list, so that we can still tell if --- 4479,4495 ---- if (non_constant_p) { bool expr_non_constant_p; ! expr = (cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, &expr_non_constant_p)); if (expr_non_constant_p) *non_constant_p = true; } else ! expr = cp_parser_assignment_expression (parser, cast_p); ! ! if (fold_expr_p) ! expr = fold_non_dependent_expr (expr); /* Add it to the list. We add error_mark_node expressions to the list, so that we can still tell if *************** cp_parser_parenthesized_expression_list *** 4103,4109 **** /* After the first item, attribute lists look the same as expression lists. */ is_attribute_list = false; ! get_comma:; /* If the next token isn't a `,', then we are done. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) --- 4504,4510 ---- /* After the first item, attribute lists look the same as expression lists. */ is_attribute_list = false; ! get_comma:; /* If the next token isn't a `,', then we are done. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) *************** cp_parser_parenthesized_expression_list *** 4112,4127 **** /* Otherwise, consume the `,' and keep going. */ cp_lexer_consume_token (parser->lexer); } ! if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) { int ending; ! skip_comma:; /* We try and resync to an unnested comma, as that will give the user better diagnostics. */ ! ending = cp_parser_skip_to_closing_parenthesis (parser, ! /*recovering=*/true, /*or_comma=*/true, /*consume_paren=*/true); if (ending < 0) --- 4513,4528 ---- /* Otherwise, consume the `,' and keep going. */ cp_lexer_consume_token (parser->lexer); } ! if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) { int ending; ! skip_comma:; /* We try and resync to an unnested comma, as that will give the user better diagnostics. */ ! ending = cp_parser_skip_to_closing_parenthesis (parser, ! /*recovering=*/true, /*or_comma=*/true, /*consume_paren=*/true); if (ending < 0) *************** cp_parser_parenthesized_expression_list *** 4134,4140 **** expression_list = nreverse (expression_list); if (identifier) expression_list = tree_cons (NULL_TREE, identifier, expression_list); ! return expression_list; } --- 4535,4541 ---- expression_list = nreverse (expression_list); if (identifier) expression_list = tree_cons (NULL_TREE, identifier, expression_list); ! return expression_list; } *************** cp_parser_parenthesized_expression_list *** 4151,4181 **** or ERROR_MARK_NODE if the parse fails. */ static void ! cp_parser_pseudo_destructor_name (cp_parser* parser, ! tree* scope, tree* type) { bool nested_name_specifier_p; /* Look for the optional `::' operator. */ cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true); /* Look for the optional nested-name-specifier. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/true, /*type_p=*/false, ! /*is_declaration=*/true) != NULL_TREE); /* Now, if we saw a nested-name-specifier, we might be doing the second production. */ ! if (nested_name_specifier_p && cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { /* Consume the `template' keyword. */ cp_lexer_consume_token (parser->lexer); /* Parse the template-id. */ ! cp_parser_template_id (parser, /*template_keyword_p=*/true, /*check_dependency_p=*/false, /*is_declaration=*/true); --- 4552,4585 ---- or ERROR_MARK_NODE if the parse fails. */ static void ! cp_parser_pseudo_destructor_name (cp_parser* parser, ! tree* scope, tree* type) { bool nested_name_specifier_p; + /* Assume that things will not work out. */ + *type = error_mark_node; + /* Look for the optional `::' operator. */ cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true); /* Look for the optional nested-name-specifier. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/true, /*type_p=*/false, ! /*is_declaration=*/true) != NULL_TREE); /* Now, if we saw a nested-name-specifier, we might be doing the second production. */ ! if (nested_name_specifier_p && cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { /* Consume the `template' keyword. */ cp_lexer_consume_token (parser->lexer); /* Parse the template-id. */ ! cp_parser_template_id (parser, /*template_keyword_p=*/true, /*check_dependency_p=*/false, /*is_declaration=*/true); *************** cp_parser_pseudo_destructor_name (cp_par *** 4189,4205 **** /* Look for the type-name. */ *scope = TREE_TYPE (cp_parser_type_name (parser)); ! /* If we didn't get an aggregate type, or we don't have ::~, ! then something has gone wrong. Since the only caller of this ! function is looking for something after `.' or `->' after a ! scalar type, most likely the program is trying to get a ! member of a non-aggregate type. */ ! if (*scope == error_mark_node ! || cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL) { cp_parser_error (parser, "request for member of non-aggregate type"); - *type = error_mark_node; return; } --- 4593,4610 ---- /* Look for the type-name. */ *scope = TREE_TYPE (cp_parser_type_name (parser)); ! if (*scope == error_mark_node) ! return; ! ! /* If we don't have ::~, then something has gone wrong. Since ! the only caller of this function is looking for something ! after `.' or `->' after a scalar type, most likely the ! program is trying to get a member of a non-aggregate ! type. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL) { cp_parser_error (parser, "request for member of non-aggregate type"); return; } *************** cp_parser_pseudo_destructor_name (cp_par *** 4239,4250 **** && identifier ADDRESS_P is true iff the unary-expression is appearing as the ! operand of the `&' operator. Returns a representation of the expression. */ static tree ! cp_parser_unary_expression (cp_parser *parser, bool address_p) { cp_token *token; enum tree_code unary_operator; --- 4644,4656 ---- && identifier ADDRESS_P is true iff the unary-expression is appearing as the ! operand of the `&' operator. CAST_P is true if this expression is ! the target of a cast. Returns a representation of the expression. */ static tree ! cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) { cp_token *token; enum tree_code unary_operator; *************** cp_parser_unary_expression (cp_parser *p *** 4263,4269 **** { tree operand; enum tree_code op; ! op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); --- 4669,4675 ---- { tree operand; enum tree_code op; ! op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); *************** cp_parser_unary_expression (cp_parser *p *** 4281,4287 **** case RID_DELETE: return cp_parser_delete_expression (parser); ! case RID_EXTENSION: { /* The saved value of the PEDANTIC flag. */ --- 4687,4693 ---- case RID_DELETE: return cp_parser_delete_expression (parser); ! case RID_EXTENSION: { /* The saved value of the PEDANTIC flag. */ *************** cp_parser_unary_expression (cp_parser *p *** 4371,4378 **** /* Consume the operator token. */ token = cp_lexer_consume_token (parser->lexer); /* Parse the cast-expression. */ ! cast_expression ! = cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR); /* Now, build an appropriate representation. */ switch (unary_operator) { --- 4777,4786 ---- /* Consume the operator token. */ token = cp_lexer_consume_token (parser->lexer); /* Parse the cast-expression. */ ! cast_expression ! = cp_parser_cast_expression (parser, ! unary_operator == ADDR_EXPR, ! /*cast_p=*/false); /* Now, build an appropriate representation. */ switch (unary_operator) { *************** cp_parser_unary_expression (cp_parser *p *** 4382,4391 **** break; case ADDR_EXPR: ! /* The "&" operator is allowed in the implementation of ! "offsetof". */ ! if (!parser->in_offsetof_p) ! non_constant_p = "`&'"; /* Fall through. */ case BIT_NOT_EXPR: expression = build_x_unary_op (unary_operator, cast_expression); --- 4790,4796 ---- break; case ADDR_EXPR: ! non_constant_p = "`&'"; /* Fall through. */ case BIT_NOT_EXPR: expression = build_x_unary_op (unary_operator, cast_expression); *************** cp_parser_unary_expression (cp_parser *p *** 4403,4412 **** break; default: ! abort (); } ! if (non_constant_p && cp_parser_non_integral_constant_expression (parser, non_constant_p)) expression = error_mark_node; --- 4808,4817 ---- break; default: ! gcc_unreachable (); } ! if (non_constant_p && cp_parser_non_integral_constant_expression (parser, non_constant_p)) expression = error_mark_node; *************** cp_parser_unary_expression (cp_parser *p *** 4414,4420 **** return expression; } ! return cp_parser_postfix_expression (parser, address_p); } /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a --- 4819,4825 ---- return expression; } ! return cp_parser_postfix_expression (parser, address_p, cast_p); } /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a *************** cp_parser_unary_operator (cp_token* toke *** 4439,4445 **** case CPP_NOT: return TRUTH_NOT_EXPR; ! case CPP_COMPL: return BIT_NOT_EXPR; --- 4844,4850 ---- case CPP_NOT: return TRUTH_NOT_EXPR; ! case CPP_COMPL: return BIT_NOT_EXPR; *************** cp_parser_new_expression (cp_parser* par *** 4463,4471 **** tree placement; tree type; tree initializer; /* Look for the optional `::' operator. */ ! global_scope_p = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) != NULL_TREE); --- 4868,4877 ---- tree placement; tree type; tree initializer; + tree nelts; /* Look for the optional `::' operator. */ ! global_scope_p = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) != NULL_TREE); *************** cp_parser_new_expression (cp_parser* par *** 4490,4496 **** type = cp_parser_type_id (parser); /* Look for the closing `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); ! /* There should not be a direct-new-declarator in this production, but GCC used to allowed this, so we check and emit a sensible error message for this case. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) --- 4896,4902 ---- type = cp_parser_type_id (parser); /* Look for the closing `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); ! /* There should not be a direct-new-declarator in this production, but GCC used to allowed this, so we check and emit a sensible error message for this case. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) *************** cp_parser_new_expression (cp_parser* par *** 4499,4508 **** inform ("try removing the parentheses around the type-id"); cp_parser_direct_new_declarator (parser); } } /* Otherwise, there must be a new-type-id. */ else ! type = cp_parser_new_type_id (parser); /* If the next token is a `(', then we have a new-initializer. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) --- 4905,4915 ---- inform ("try removing the parentheses around the type-id"); cp_parser_direct_new_declarator (parser); } + nelts = NULL_TREE; } /* Otherwise, there must be a new-type-id. */ else ! type = cp_parser_new_type_id (parser, &nelts); /* If the next token is a `(', then we have a new-initializer. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) *************** cp_parser_new_expression (cp_parser* par *** 4516,4522 **** return error_mark_node; /* Create a representation of the new-expression. */ ! return build_new (placement, type, initializer, global_scope_p); } /* Parse a new-placement. --- 4923,4929 ---- return error_mark_node; /* Create a representation of the new-expression. */ ! return build_new (placement, type, nelts, initializer, global_scope_p); } /* Parse a new-placement. *************** cp_parser_new_placement (cp_parser* pars *** 4532,4539 **** tree expression_list; /* Parse the expression-list. */ ! expression_list = (cp_parser_parenthesized_expression_list ! (parser, false, /*non_constant_p=*/NULL)); return expression_list; } --- 4939,4947 ---- tree expression_list; /* Parse the expression-list. */ ! expression_list = (cp_parser_parenthesized_expression_list ! (parser, false, /*cast_p=*/false, ! /*non_constant_p=*/NULL)); return expression_list; } *************** cp_parser_new_placement (cp_parser* pars *** 4543,4557 **** new-type-id: type-specifier-seq new-declarator [opt] ! Returns a TREE_LIST whose TREE_PURPOSE is the type-specifier-seq, ! and whose TREE_VALUE is the new-declarator. */ static tree ! cp_parser_new_type_id (cp_parser* parser) { ! tree type_specifier_seq; ! tree declarator; const char *saved_message; /* The type-specifier sequence must not contain type definitions. (It cannot contain declarations of new types either, but if they --- 4951,4969 ---- new-type-id: type-specifier-seq new-declarator [opt] ! Returns the TYPE allocated. If the new-type-id indicates an array ! type, *NELTS is set to the number of elements in the last array ! bound; the TYPE will not include the last array bound. */ static tree ! cp_parser_new_type_id (cp_parser* parser, tree *nelts) { ! cp_decl_specifier_seq type_specifier_seq; ! cp_declarator *new_declarator; ! cp_declarator *declarator; ! cp_declarator *outer_declarator; const char *saved_message; + tree type; /* The type-specifier sequence must not contain type definitions. (It cannot contain declarations of new types either, but if they *************** cp_parser_new_type_id (cp_parser* parser *** 4561,4573 **** parser->type_definition_forbidden_message = "types may not be defined in a new-type-id"; /* Parse the type-specifier-seq. */ ! type_specifier_seq = cp_parser_type_specifier_seq (parser); /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; /* Parse the new-declarator. */ ! declarator = cp_parser_new_declarator_opt (parser); ! return build_tree_list (type_specifier_seq, declarator); } /* Parse an (optional) new-declarator. --- 4973,5025 ---- parser->type_definition_forbidden_message = "types may not be defined in a new-type-id"; /* Parse the type-specifier-seq. */ ! cp_parser_type_specifier_seq (parser, /*is_condition=*/false, ! &type_specifier_seq); /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; /* Parse the new-declarator. */ ! new_declarator = cp_parser_new_declarator_opt (parser); ! /* Determine the number of elements in the last array dimension, if ! any. */ ! *nelts = NULL_TREE; ! /* Skip down to the last array dimension. */ ! declarator = new_declarator; ! outer_declarator = NULL; ! while (declarator && (declarator->kind == cdk_pointer ! || declarator->kind == cdk_ptrmem)) ! { ! outer_declarator = declarator; ! declarator = declarator->declarator; ! } ! while (declarator ! && declarator->kind == cdk_array ! && declarator->declarator ! && declarator->declarator->kind == cdk_array) ! { ! outer_declarator = declarator; ! declarator = declarator->declarator; ! } ! ! if (declarator && declarator->kind == cdk_array) ! { ! *nelts = declarator->u.array.bounds; ! if (*nelts == error_mark_node) ! *nelts = integer_one_node; ! ! if (outer_declarator) ! outer_declarator->declarator = declarator->declarator; ! else ! new_declarator = NULL; ! } ! ! type = groktypename (&type_specifier_seq, new_declarator); ! if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE) ! { ! *nelts = array_type_nelts_top (type); ! type = TREE_TYPE (type); ! } ! return type; } /* Parse an (optional) new-declarator. *************** cp_parser_new_type_id (cp_parser* parser *** 4576,4614 **** ptr-operator new-declarator [opt] direct-new-declarator ! Returns a representation of the declarator. See ! cp_parser_declarator for the representations used. */ ! static tree cp_parser_new_declarator_opt (cp_parser* parser) { enum tree_code code; tree type; ! tree cv_qualifier_seq; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Look for a ptr-operator. */ ! code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq); /* If that worked, look for more new-declarators. */ if (cp_parser_parse_definitely (parser)) { ! tree declarator; /* Parse another optional declarator. */ declarator = cp_parser_new_declarator_opt (parser); /* Create the representation of the declarator. */ ! if (code == INDIRECT_REF) ! declarator = make_pointer_declarator (cv_qualifier_seq, ! declarator); else ! declarator = make_reference_declarator (cv_qualifier_seq, ! declarator); ! ! /* Handle the pointer-to-member case. */ ! if (type) ! declarator = build_nt (SCOPE_REF, type, declarator); return declarator; } --- 5028,5061 ---- ptr-operator new-declarator [opt] direct-new-declarator ! Returns the declarator. */ ! static cp_declarator * cp_parser_new_declarator_opt (cp_parser* parser) { enum tree_code code; tree type; ! cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Look for a ptr-operator. */ ! code = cp_parser_ptr_operator (parser, &type, &cv_quals); /* If that worked, look for more new-declarators. */ if (cp_parser_parse_definitely (parser)) { ! cp_declarator *declarator; /* Parse another optional declarator. */ declarator = cp_parser_new_declarator_opt (parser); /* Create the representation of the declarator. */ ! if (type) ! declarator = make_ptrmem_declarator (cv_quals, type, declarator); ! else if (code == INDIRECT_REF) ! declarator = make_pointer_declarator (cv_quals, declarator); else ! declarator = make_reference_declarator (cv_quals, declarator); return declarator; } *************** cp_parser_new_declarator_opt (cp_parser* *** 4617,4638 **** if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) return cp_parser_direct_new_declarator (parser); ! return NULL_TREE; } /* Parse a direct-new-declarator. direct-new-declarator: [ expression ] ! direct-new-declarator [constant-expression] ! Returns an ARRAY_REF, following the same conventions as are ! documented for cp_parser_direct_declarator. */ ! static tree cp_parser_direct_new_declarator (cp_parser* parser) { ! tree declarator = NULL_TREE; while (true) { --- 5064,5084 ---- if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) return cp_parser_direct_new_declarator (parser); ! return NULL; } /* Parse a direct-new-declarator. direct-new-declarator: [ expression ] ! direct-new-declarator [constant-expression] ! */ ! static cp_declarator * cp_parser_direct_new_declarator (cp_parser* parser) { ! cp_declarator *declarator = NULL; while (true) { *************** cp_parser_direct_new_declarator (cp_pars *** 4643,4649 **** /* The first expression is not required to be constant. */ if (!declarator) { ! expression = cp_parser_expression (parser); /* The standard requires that the expression have integral type. DR 74 adds enumeration types. We believe that the real intent is that these expressions be handled like the --- 5089,5095 ---- /* The first expression is not required to be constant. */ if (!declarator) { ! expression = cp_parser_expression (parser, /*cast_p=*/false); /* The standard requires that the expression have integral type. DR 74 adds enumeration types. We believe that the real intent is that these expressions be handled like the *************** cp_parser_direct_new_declarator (cp_pars *** 4652,4679 **** enumeration type. */ if (!processing_template_decl) { ! expression = build_expr_type_conversion (WANT_INT | WANT_ENUM, expression, /*complain=*/true); if (!expression) { ! error ("expression in new-declarator must have integral or enumeration type"); expression = error_mark_node; } } } /* But all the other expressions must be. */ else ! expression ! = cp_parser_constant_expression (parser, /*allow_non_constant=*/false, NULL); /* Look for the closing `]'. */ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); /* Add this bound to the declarator. */ ! declarator = build_nt (ARRAY_REF, declarator, expression); /* If the next token is not a `[', then there are no more bounds. */ --- 5098,5126 ---- enumeration type. */ if (!processing_template_decl) { ! expression = build_expr_type_conversion (WANT_INT | WANT_ENUM, expression, /*complain=*/true); if (!expression) { ! error ("expression in new-declarator must have integral " ! "or enumeration type"); expression = error_mark_node; } } } /* But all the other expressions must be. */ else ! expression ! = cp_parser_constant_expression (parser, /*allow_non_constant=*/false, NULL); /* Look for the closing `]'. */ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); /* Add this bound to the declarator. */ ! declarator = make_array_declarator (declarator, expression); /* If the next token is not a `[', then there are no more bounds. */ *************** cp_parser_new_initializer (cp_parser* pa *** 4697,4704 **** { tree expression_list; ! expression_list = (cp_parser_parenthesized_expression_list ! (parser, false, /*non_constant_p=*/NULL)); if (!expression_list) expression_list = void_zero_node; --- 5144,5152 ---- { tree expression_list; ! expression_list = (cp_parser_parenthesized_expression_list ! (parser, false, /*cast_p=*/false, ! /*non_constant_p=*/NULL)); if (!expression_list) expression_list = void_zero_node; *************** cp_parser_delete_expression (cp_parser* *** 4757,4766 **** unary-expression ( type-id ) cast-expression Returns a representation of the expression. */ static tree ! cp_parser_cast_expression (cp_parser *parser, bool address_p) { /* If it's a `(', then we might be looking at a cast. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) --- 5205,5218 ---- unary-expression ( type-id ) cast-expression + ADDRESS_P is true iff the unary-expression is appearing as the + operand of the `&' operator. CAST_P is true if this expression is + the target of a cast. + Returns a representation of the expression. */ static tree ! cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) { /* If it's a `(', then we might be looking at a cast. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) *************** cp_parser_cast_expression (cp_parser *pa *** 4789,4806 **** the type-id, and it happens to be a class-specifier, then we will commit to the parse at that point, because we cannot undo the action that is done when creating a new class. So, ! then we cannot back up and do a postfix-expression. Therefore, we scan ahead to the closing `)', and check to see if the token after the `)' is a `{'. If so, we are not ! looking at a cast-expression. Save tokens so that we can put them back. */ cp_lexer_save_tokens (parser->lexer); /* Skip tokens until the next token is a closing parenthesis. If we find the closing `)', and the next token is a `{', then we are looking at a compound-literal. */ ! compound_literal_p = (cp_parser_skip_to_closing_parenthesis (parser, false, false, /*consume_paren=*/true) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); --- 5241,5258 ---- the type-id, and it happens to be a class-specifier, then we will commit to the parse at that point, because we cannot undo the action that is done when creating a new class. So, ! then we cannot back up and do a postfix-expression. Therefore, we scan ahead to the closing `)', and check to see if the token after the `)' is a `{'. If so, we are not ! looking at a cast-expression. Save tokens so that we can put them back. */ cp_lexer_save_tokens (parser->lexer); /* Skip tokens until the next token is a closing parenthesis. If we find the closing `)', and the next token is a `{', then we are looking at a compound-literal. */ ! compound_literal_p = (cp_parser_skip_to_closing_parenthesis (parser, false, false, /*consume_paren=*/true) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); *************** cp_parser_cast_expression (cp_parser *pa *** 4830,4843 **** ctor of T, but looks like a cast to function returning T without a dependent expression. */ if (!cp_parser_error_occurred (parser)) ! expr = cp_parser_simple_cast_expression (parser); if (cp_parser_parse_definitely (parser)) { /* Warn about old-style casts, if so requested. */ ! if (warn_old_style_cast ! && !in_system_header ! && !VOID_TYPE_P (type) && current_lang_name != lang_name_c) warning ("use of old-style cast"); --- 5282,5297 ---- ctor of T, but looks like a cast to function returning T without a dependent expression. */ if (!cp_parser_error_occurred (parser)) ! expr = cp_parser_cast_expression (parser, ! /*address_p=*/false, ! /*cast_p=*/true); if (cp_parser_parse_definitely (parser)) { /* Warn about old-style casts, if so requested. */ ! if (warn_old_style_cast ! && !in_system_header ! && !VOID_TYPE_P (type) && current_lang_name != lang_name_c) warning ("use of old-style cast"); *************** cp_parser_cast_expression (cp_parser *pa *** 4846,4854 **** if (parser->integral_constant_expression_p && !dependent_type_p (type) && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) ! && (cp_parser_non_integral_constant_expression (parser, ! "a casts to a type other than an integral or " "enumeration type"))) return error_mark_node; --- 5300,5308 ---- if (parser->integral_constant_expression_p && !dependent_type_p (type) && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) ! && (cp_parser_non_integral_constant_expression (parser, ! "a cast to a type other than an integral or " "enumeration type"))) return error_mark_node; *************** cp_parser_cast_expression (cp_parser *pa *** 4860,4963 **** /* If we get here, then it's not a cast, so it must be a unary-expression. */ ! return cp_parser_unary_expression (parser, address_p); } ! /* Parse a pm-expression. pm-expression: cast-expression pm-expression .* cast-expression pm-expression ->* cast-expression ! Returns a representation of the expression. */ ! ! static tree ! cp_parser_pm_expression (cp_parser* parser) ! { ! static const cp_parser_token_tree_map map = { ! { CPP_DEREF_STAR, MEMBER_REF }, ! { CPP_DOT_STAR, DOTSTAR_EXPR }, ! { CPP_EOF, ERROR_MARK } ! }; ! ! return cp_parser_binary_expression (parser, map, ! cp_parser_simple_cast_expression); ! } ! ! /* Parse a multiplicative-expression. ! ! mulitplicative-expression: pm-expression multiplicative-expression * pm-expression multiplicative-expression / pm-expression multiplicative-expression % pm-expression - Returns a representation of the expression. */ - - static tree - cp_parser_multiplicative_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_MULT, MULT_EXPR }, - { CPP_DIV, TRUNC_DIV_EXPR }, - { CPP_MOD, TRUNC_MOD_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_pm_expression); - } - - /* Parse an additive-expression. - additive-expression: multiplicative-expression additive-expression + multiplicative-expression additive-expression - multiplicative-expression - Returns a representation of the expression. */ - - static tree - cp_parser_additive_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_PLUS, PLUS_EXPR }, - { CPP_MINUS, MINUS_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_multiplicative_expression); - } - - /* Parse a shift-expression. - shift-expression: additive-expression shift-expression << additive-expression shift-expression >> additive-expression - Returns a representation of the expression. */ - - static tree - cp_parser_shift_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_LSHIFT, LSHIFT_EXPR }, - { CPP_RSHIFT, RSHIFT_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_additive_expression); - } - - /* Parse a relational-expression. - relational-expression: shift-expression relational-expression < shift-expression --- 5314,5345 ---- /* If we get here, then it's not a cast, so it must be a unary-expression. */ ! return cp_parser_unary_expression (parser, address_p, cast_p); } ! /* Parse a binary expression of the general form: pm-expression: cast-expression pm-expression .* cast-expression pm-expression ->* cast-expression ! multiplicative-expression: pm-expression multiplicative-expression * pm-expression multiplicative-expression / pm-expression multiplicative-expression % pm-expression additive-expression: multiplicative-expression additive-expression + multiplicative-expression additive-expression - multiplicative-expression shift-expression: additive-expression shift-expression << additive-expression shift-expression >> additive-expression relational-expression: shift-expression relational-expression < shift-expression *************** cp_parser_shift_expression (cp_parser* p *** 4965,5125 **** relational-expression <= shift-expression relational-expression >= shift-expression ! GNU Extension: ! relational-expression: relational-expression ? shift-expression - Returns a representation of the expression. */ - - static tree - cp_parser_relational_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_LESS, LT_EXPR }, - { CPP_GREATER, GT_EXPR }, - { CPP_LESS_EQ, LE_EXPR }, - { CPP_GREATER_EQ, GE_EXPR }, - { CPP_MIN, MIN_EXPR }, - { CPP_MAX, MAX_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_shift_expression); - } - - /* Parse an equality-expression. - equality-expression: relational-expression equality-expression == relational-expression equality-expression != relational-expression - Returns a representation of the expression. */ - - static tree - cp_parser_equality_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_EQ_EQ, EQ_EXPR }, - { CPP_NOT_EQ, NE_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_relational_expression); - } - - /* Parse an and-expression. - and-expression: equality-expression and-expression & equality-expression - Returns a representation of the expression. */ - - static tree - cp_parser_and_expression (cp_parser* parser) - { - static const cp_parser_token_tree_map map = { - { CPP_AND, BIT_AND_EXPR }, - { CPP_EOF, ERROR_MARK } - }; - - return cp_parser_binary_expression (parser, - map, - cp_parser_equality_expression); - } - - /* Parse an exclusive-or-expression. - exclusive-or-expression: and-expression exclusive-or-expression ^ and-expression ! Returns a representation of the expression. */ ! static tree ! cp_parser_exclusive_or_expression (cp_parser* parser) ! { ! static const cp_parser_token_tree_map map = { ! { CPP_XOR, BIT_XOR_EXPR }, ! { CPP_EOF, ERROR_MARK } ! }; ! return cp_parser_binary_expression (parser, ! map, ! cp_parser_and_expression); ! } ! /* Parse an inclusive-or-expression. ! inclusive-or-expression: ! exclusive-or-expression ! inclusive-or-expression | exclusive-or-expression ! Returns a representation of the expression. */ static tree ! cp_parser_inclusive_or_expression (cp_parser* parser) { ! static const cp_parser_token_tree_map map = { ! { CPP_OR, BIT_IOR_EXPR }, ! { CPP_EOF, ERROR_MARK } ! }; ! return cp_parser_binary_expression (parser, ! map, ! cp_parser_exclusive_or_expression); ! } ! /* Parse a logical-and-expression. ! logical-and-expression: ! inclusive-or-expression ! logical-and-expression && inclusive-or-expression ! Returns a representation of the expression. */ ! static tree ! cp_parser_logical_and_expression (cp_parser* parser) ! { ! static const cp_parser_token_tree_map map = { ! { CPP_AND_AND, TRUTH_ANDIF_EXPR }, ! { CPP_EOF, ERROR_MARK } ! }; ! return cp_parser_binary_expression (parser, ! map, ! cp_parser_inclusive_or_expression); ! } ! /* Parse a logical-or-expression. ! logical-or-expression: ! logical-and-expression ! logical-or-expression || logical-and-expression ! Returns a representation of the expression. */ ! static tree ! cp_parser_logical_or_expression (cp_parser* parser) ! { ! static const cp_parser_token_tree_map map = { ! { CPP_OR_OR, TRUTH_ORIF_EXPR }, ! { CPP_EOF, ERROR_MARK } ! }; ! return cp_parser_binary_expression (parser, ! map, ! cp_parser_logical_and_expression); } /* Parse the `? expression : assignment-expression' part of a conditional-expression. The LOGICAL_OR_EXPR is the logical-or-expression that started the conditional-expression. --- 5347,5501 ---- relational-expression <= shift-expression relational-expression >= shift-expression ! GNU Extension: ! relational-expression: relational-expression ? shift-expression equality-expression: relational-expression equality-expression == relational-expression equality-expression != relational-expression and-expression: equality-expression and-expression & equality-expression exclusive-or-expression: and-expression exclusive-or-expression ^ and-expression ! inclusive-or-expression: ! exclusive-or-expression ! inclusive-or-expression | exclusive-or-expression ! logical-and-expression: ! inclusive-or-expression ! logical-and-expression && inclusive-or-expression ! logical-or-expression: ! logical-and-expression ! logical-or-expression || logical-and-expression + All these are implemented with a single function like: ! binary-expression: ! simple-cast-expression ! binary-expression binary-expression ! CAST_P is true if this expression is the target of a cast. ! The binops_by_token map is used to get the tree codes for each type. ! binary-expressions are associated according to a precedence table. */ ! ! #define TOKEN_PRECEDENCE(token) \ ! ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \ ! ? PREC_NOT_OPERATOR \ ! : binops_by_token[token->type].prec) static tree ! cp_parser_binary_expression (cp_parser* parser, bool cast_p) { ! cp_parser_expression_stack stack; ! cp_parser_expression_stack_entry *sp = &stack[0]; ! tree lhs, rhs; ! cp_token *token; ! enum tree_code tree_type; ! enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec; ! bool overloaded_p; ! /* Parse the first expression. */ ! lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p); ! for (;;) ! { ! /* Get an operator token. */ ! token = cp_lexer_peek_token (parser->lexer); ! if (token->type == CPP_MIN || token->type == CPP_MAX) ! cp_parser_warn_min_max (); ! new_prec = TOKEN_PRECEDENCE (token); ! /* Popping an entry off the stack means we completed a subexpression: ! - either we found a token which is not an operator (`>' where it is not ! an operator, or prec == PREC_NOT_OPERATOR), in which case popping ! will happen repeatedly; ! - or, we found an operator which has lower priority. This is the case ! where the recursive descent *ascends*, as in `3 * 4 + 5' after ! parsing `3 * 4'. */ ! if (new_prec <= prec) ! { ! if (sp == stack) ! break; ! else ! goto pop; ! } ! get_rhs: ! tree_type = binops_by_token[token->type].tree_type; ! /* We used the operator token. */ ! cp_lexer_consume_token (parser->lexer); ! /* Extract another operand. It may be the RHS of this expression ! or the LHS of a new, higher priority expression. */ ! rhs = cp_parser_simple_cast_expression (parser); ! /* Get another operator token. Look up its precedence to avoid ! building a useless (immediately popped) stack entry for common ! cases such as 3 + 4 + 5 or 3 * 4 + 5. */ ! token = cp_lexer_peek_token (parser->lexer); ! lookahead_prec = TOKEN_PRECEDENCE (token); ! if (lookahead_prec > new_prec) ! { ! /* ... and prepare to parse the RHS of the new, higher priority ! expression. Since precedence levels on the stack are ! monotonically increasing, we do not have to care about ! stack overflows. */ ! sp->prec = prec; ! sp->tree_type = tree_type; ! sp->lhs = lhs; ! sp++; ! lhs = rhs; ! prec = new_prec; ! new_prec = lookahead_prec; ! goto get_rhs; ! pop: ! /* If the stack is not empty, we have parsed into LHS the right side ! (`4' in the example above) of an expression we had suspended. ! We can use the information on the stack to recover the LHS (`3') ! from the stack together with the tree code (`MULT_EXPR'), and ! the precedence of the higher level subexpression ! (`PREC_ADDITIVE_EXPRESSION'). TOKEN is the CPP_PLUS token, ! which will be used to actually build the additive expression. */ ! --sp; ! prec = sp->prec; ! tree_type = sp->tree_type; ! rhs = lhs; ! lhs = sp->lhs; ! } ! overloaded_p = false; ! lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p); ! /* If the binary operator required the use of an overloaded operator, ! then this expression cannot be an integral constant-expression. ! An overloaded operator can be used even if both operands are ! otherwise permissible in an integral constant-expression if at ! least one of the operands is of enumeration type. */ ! ! if (overloaded_p ! && (cp_parser_non_integral_constant_expression ! (parser, "calls to overloaded operators"))) ! return error_mark_node; ! } ! ! return lhs; } + /* Parse the `? expression : assignment-expression' part of a conditional-expression. The LOGICAL_OR_EXPR is the logical-or-expression that started the conditional-expression. *************** cp_parser_logical_or_expression (cp_pars *** 5128,5136 **** This routine is used by cp_parser_assignment_expression. ? expression : assignment-expression ! GNU Extensions: ! ? : assignment-expression */ static tree --- 5504,5512 ---- This routine is used by cp_parser_assignment_expression. ? expression : assignment-expression ! GNU Extensions: ! ? : assignment-expression */ static tree *************** cp_parser_question_colon_clause (cp_pars *** 5147,5158 **** expr = NULL_TREE; else /* Parse the expression. */ ! expr = cp_parser_expression (parser); ! /* The next token should be a `:'. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the assignment-expression. */ ! assignment_expr = cp_parser_assignment_expression (parser); /* Build the conditional-expression. */ return build_x_conditional_expr (logical_or_expr, --- 5523,5534 ---- expr = NULL_TREE; else /* Parse the expression. */ ! expr = cp_parser_expression (parser, /*cast_p=*/false); ! /* The next token should be a `:'. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the assignment-expression. */ ! assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false); /* Build the conditional-expression. */ return build_x_conditional_expr (logical_or_expr, *************** cp_parser_question_colon_clause (cp_pars *** 5167,5176 **** logical-or-expression assignment-operator assignment_expression throw-expression Returns a representation for the expression. */ static tree ! cp_parser_assignment_expression (cp_parser* parser) { tree expr; --- 5543,5554 ---- logical-or-expression assignment-operator assignment_expression throw-expression + CAST_P is true if this expression is the target of a cast. + Returns a representation for the expression. */ static tree ! cp_parser_assignment_expression (cp_parser* parser, bool cast_p) { tree expr; *************** cp_parser_assignment_expression (cp_pars *** 5182,5215 **** logical-or-expression. */ else { ! /* Parse the logical-or-expression. */ ! expr = cp_parser_logical_or_expression (parser); /* If the next token is a `?' then we're actually looking at a conditional-expression. */ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) return cp_parser_question_colon_clause (parser, expr); ! else { enum tree_code assignment_operator; /* If it's an assignment-operator, we're using the second production. */ ! assignment_operator = cp_parser_assignment_operator_opt (parser); if (assignment_operator != ERROR_MARK) { tree rhs; /* Parse the right-hand side of the assignment. */ ! rhs = cp_parser_assignment_expression (parser); /* An assignment may not appear in a constant-expression. */ if (cp_parser_non_integral_constant_expression (parser, "an assignment")) return error_mark_node; /* Build the assignment expression. */ ! expr = build_x_modify_expr (expr, ! assignment_operator, rhs); } } --- 5560,5593 ---- logical-or-expression. */ else { ! /* Parse the binary expressions (logical-or-expression). */ ! expr = cp_parser_binary_expression (parser, cast_p); /* If the next token is a `?' then we're actually looking at a conditional-expression. */ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) return cp_parser_question_colon_clause (parser, expr); ! else { enum tree_code assignment_operator; /* If it's an assignment-operator, we're using the second production. */ ! assignment_operator = cp_parser_assignment_operator_opt (parser); if (assignment_operator != ERROR_MARK) { tree rhs; /* Parse the right-hand side of the assignment. */ ! rhs = cp_parser_assignment_expression (parser, cast_p); /* An assignment may not appear in a constant-expression. */ if (cp_parser_non_integral_constant_expression (parser, "an assignment")) return error_mark_node; /* Build the assignment expression. */ ! expr = build_x_modify_expr (expr, ! assignment_operator, rhs); } } *************** cp_parser_assignment_expression (cp_pars *** 5220,5230 **** /* Parse an (optional) assignment-operator. ! assignment-operator: one of ! = *= /= %= += -= >>= <<= &= ^= |= GNU Extension: ! assignment-operator: one of ?= --- 5598,5608 ---- /* Parse an (optional) assignment-operator. ! assignment-operator: one of ! = *= /= %= += -= >>= <<= &= ^= |= GNU Extension: ! assignment-operator: one of ?= *************** cp_parser_assignment_operator_opt (cp_pa *** 5292,5304 **** case CPP_MIN_EQ: op = MIN_EXPR; break; case CPP_MAX_EQ: op = MAX_EXPR; break; ! default: /* Nothing else is an assignment operator. */ op = ERROR_MARK; } --- 5670,5684 ---- case CPP_MIN_EQ: op = MIN_EXPR; + cp_parser_warn_min_max (); break; case CPP_MAX_EQ: op = MAX_EXPR; + cp_parser_warn_min_max (); break; ! default: /* Nothing else is an assignment operator. */ op = ERROR_MARK; } *************** cp_parser_assignment_operator_opt (cp_pa *** 5316,5325 **** assignment-expression expression , assignment-expression Returns a representation of the expression. */ static tree ! cp_parser_expression (cp_parser* parser) { tree expression = NULL_TREE; --- 5696,5707 ---- assignment-expression expression , assignment-expression + CAST_P is true if this expression is the target of a cast. + Returns a representation of the expression. */ static tree ! cp_parser_expression (cp_parser* parser, bool cast_p) { tree expression = NULL_TREE; *************** cp_parser_expression (cp_parser* parser) *** 5328,5335 **** tree assignment_expression; /* Parse the next assignment-expression. */ ! assignment_expression ! = cp_parser_assignment_expression (parser); /* If this is the first assignment-expression, we can just save it away. */ if (!expression) --- 5710,5717 ---- tree assignment_expression; /* Parse the next assignment-expression. */ ! assignment_expression ! = cp_parser_assignment_expression (parser, cast_p); /* If this is the first assignment-expression, we can just save it away. */ if (!expression) *************** cp_parser_expression (cp_parser* parser) *** 5352,5361 **** return expression; } ! /* Parse a constant-expression. constant-expression: ! conditional-expression If ALLOW_NON_CONSTANT_P a non-constant expression is silently accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not --- 5734,5743 ---- return expression; } ! /* Parse a constant-expression. constant-expression: ! conditional-expression If ALLOW_NON_CONSTANT_P a non-constant expression is silently accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not *************** cp_parser_expression (cp_parser* parser) *** 5363,5369 **** is false, NON_CONSTANT_P should be NULL. */ static tree ! cp_parser_constant_expression (cp_parser* parser, bool allow_non_constant_p, bool *non_constant_p) { --- 5745,5751 ---- is false, NON_CONSTANT_P should be NULL. */ static tree ! cp_parser_constant_expression (cp_parser* parser, bool allow_non_constant_p, bool *non_constant_p) { *************** cp_parser_constant_expression (cp_parser *** 5391,5397 **** /* Save the old settings. */ saved_integral_constant_expression_p = parser->integral_constant_expression_p; ! saved_allow_non_integral_constant_expression_p = parser->allow_non_integral_constant_expression_p; saved_non_integral_constant_expression_p = parser->non_integral_constant_expression_p; /* We are now parsing a constant-expression. */ --- 5773,5779 ---- /* Save the old settings. */ saved_integral_constant_expression_p = parser->integral_constant_expression_p; ! saved_allow_non_integral_constant_expression_p = parser->allow_non_integral_constant_expression_p; saved_non_integral_constant_expression_p = parser->non_integral_constant_expression_p; /* We are now parsing a constant-expression. */ *************** cp_parser_constant_expression (cp_parser *** 5407,5427 **** For example, cp_parser_initializer_clauses uses this function to determine whether a particular assignment-expression is in fact constant. */ ! expression = cp_parser_assignment_expression (parser); /* Restore the old settings. */ ! parser->integral_constant_expression_p = saved_integral_constant_expression_p; ! parser->allow_non_integral_constant_expression_p = saved_allow_non_integral_constant_expression_p; if (allow_non_constant_p) *non_constant_p = parser->non_integral_constant_expression_p; ! parser->non_integral_constant_expression_p = saved_non_integral_constant_expression_p; return expression; } /* Statements [gram.stmt.stmt] */ ! /* Parse a statement. statement: labeled-statement --- 5789,5899 ---- For example, cp_parser_initializer_clauses uses this function to determine whether a particular assignment-expression is in fact constant. */ ! expression = cp_parser_assignment_expression (parser, /*cast_p=*/false); /* Restore the old settings. */ ! parser->integral_constant_expression_p ! = saved_integral_constant_expression_p; ! parser->allow_non_integral_constant_expression_p = saved_allow_non_integral_constant_expression_p; if (allow_non_constant_p) *non_constant_p = parser->non_integral_constant_expression_p; ! else if (parser->non_integral_constant_expression_p) ! expression = error_mark_node; ! parser->non_integral_constant_expression_p ! = saved_non_integral_constant_expression_p; return expression; } + /* Parse __builtin_offsetof. + + offsetof-expression: + "__builtin_offsetof" "(" type-id "," offsetof-member-designator ")" + + offsetof-member-designator: + id-expression + | offsetof-member-designator "." id-expression + | offsetof-member-designator "[" expression "]" + */ + + static tree + cp_parser_builtin_offsetof (cp_parser *parser) + { + int save_ice_p, save_non_ice_p; + tree type, expr; + cp_id_kind dummy; + + /* We're about to accept non-integral-constant things, but will + definitely yield an integral constant expression. Save and + restore these values around our local parsing. */ + save_ice_p = parser->integral_constant_expression_p; + save_non_ice_p = parser->non_integral_constant_expression_p; + + /* Consume the "__builtin_offsetof" token. */ + cp_lexer_consume_token (parser->lexer); + /* Consume the opening `('. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + /* Parse the type-id. */ + type = cp_parser_type_id (parser); + /* Look for the `,'. */ + cp_parser_require (parser, CPP_COMMA, "`,'"); + + /* Build the (type *)null that begins the traditional offsetof macro. */ + expr = build_static_cast (build_pointer_type (type), null_pointer_node); + + /* Parse the offsetof-member-designator. We begin as if we saw "expr->". */ + expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr, + true, &dummy); + while (true) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + switch (token->type) + { + case CPP_OPEN_SQUARE: + /* offsetof-member-designator "[" expression "]" */ + expr = cp_parser_postfix_open_square_expression (parser, expr, true); + break; + + case CPP_DOT: + /* offsetof-member-designator "." identifier */ + cp_lexer_consume_token (parser->lexer); + expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr, + true, &dummy); + break; + + case CPP_CLOSE_PAREN: + /* Consume the ")" token. */ + cp_lexer_consume_token (parser->lexer); + goto success; + + default: + /* Error. We know the following require will fail, but + that gives the proper error message. */ + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_skip_to_closing_parenthesis (parser, true, false, true); + expr = error_mark_node; + goto failure; + } + } + + success: + /* If we're processing a template, we can't finish the semantics yet. + Otherwise we can fold the entire expression now. */ + if (processing_template_decl) + expr = build1 (OFFSETOF_EXPR, size_type_node, expr); + else + expr = fold_offsetof (expr); + + failure: + parser->integral_constant_expression_p = save_ice_p; + parser->non_integral_constant_expression_p = save_non_ice_p; + + return expr; + } + /* Statements [gram.stmt.stmt] */ ! /* Parse a statement. statement: labeled-statement *************** cp_parser_constant_expression (cp_parser *** 5434,5451 **** try-block */ static void ! cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) { tree statement; cp_token *token; ! int statement_line_number; /* There is no statement yet. */ statement = NULL_TREE; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! /* Remember the line number of the first token in the statement. */ ! statement_line_number = token->location.line; /* If this is a keyword, then that will often determine what kind of statement we have. */ if (token->type == CPP_KEYWORD) --- 5906,5923 ---- try-block */ static void ! cp_parser_statement (cp_parser* parser, tree in_statement_expr) { tree statement; cp_token *token; ! location_t statement_location; /* There is no statement yet. */ statement = NULL_TREE; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! /* Remember the location of the first token in the statement. */ ! statement_location = token->location; /* If this is a keyword, then that will often determine what kind of statement we have. */ if (token->type == CPP_KEYWORD) *************** cp_parser_statement (cp_parser* parser, *** 5457,5463 **** case RID_CASE: case RID_DEFAULT: statement = cp_parser_labeled_statement (parser, ! in_statement_expr_p); break; case RID_IF: --- 5929,5935 ---- case RID_CASE: case RID_DEFAULT: statement = cp_parser_labeled_statement (parser, ! in_statement_expr); break; case RID_IF: *************** cp_parser_statement (cp_parser* parser, *** 5494,5507 **** labeled-statement. */ token = cp_lexer_peek_nth_token (parser->lexer, 2); if (token->type == CPP_COLON) ! statement = cp_parser_labeled_statement (parser, in_statement_expr_p); } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) ! statement = cp_parser_compound_statement (parser, false); /* Everything else must be a declaration-statement or an ! expression-statement. Try for the declaration-statement first, unless we are looking at a `;', in which case we know that we have an expression-statement. */ if (!statement) --- 5966,5986 ---- labeled-statement. */ token = cp_lexer_peek_nth_token (parser->lexer, 2); if (token->type == CPP_COLON) ! statement = cp_parser_labeled_statement (parser, in_statement_expr); } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) ! statement = cp_parser_compound_statement (parser, NULL, false); ! /* CPP_PRAGMA is a #pragma inside a function body, which constitutes ! a statement all its own. */ ! else if (token->type == CPP_PRAGMA) ! { ! cp_lexer_handle_pragma (parser->lexer); ! return; ! } /* Everything else must be a declaration-statement or an ! expression-statement. Try for the declaration-statement first, unless we are looking at a `;', in which case we know that we have an expression-statement. */ if (!statement) *************** cp_parser_statement (cp_parser* parser, *** 5516,5527 **** return; } /* Look for an expression-statement instead. */ ! statement = cp_parser_expression_statement (parser, in_statement_expr_p); } /* Set the line number for the statement. */ if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) ! STMT_LINENO (statement) = statement_line_number; } /* Parse a labeled-statement. --- 5995,6006 ---- return; } /* Look for an expression-statement instead. */ ! statement = cp_parser_expression_statement (parser, in_statement_expr); } /* Set the line number for the statement. */ if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) ! SET_EXPR_LOCATION (statement, statement_location); } /* Parse a labeled-statement. *************** cp_parser_statement (cp_parser* parser, *** 5532,5546 **** default : statement GNU Extension: ! labeled-statement: case constant-expression ... constant-expression : statement ! Returns the new CASE_LABEL, for a `case' or `default' label. For ! an ordinary label, returns a LABEL_STMT. */ static tree ! cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) { cp_token *token; tree statement = error_mark_node; --- 6011,6025 ---- default : statement GNU Extension: ! labeled-statement: case constant-expression ... constant-expression : statement ! Returns the new CASE_LABEL_EXPR, for a `case' or `default' label. ! For an ordinary label, returns a LABEL_EXPR. */ static tree ! cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr) { cp_token *token; tree statement = error_mark_node; *************** cp_parser_labeled_statement (cp_parser* *** 5564,5570 **** /* Consume the `case' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the constant-expression. */ ! expr = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, NULL); --- 6043,6049 ---- /* Consume the `case' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the constant-expression. */ ! expr = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, NULL); *************** cp_parser_labeled_statement (cp_parser* *** 5584,5590 **** expr_hi = NULL_TREE; if (!parser->in_switch_statement_p) ! error ("case label `%E' not within a switch statement", expr); else statement = finish_case_label (expr, expr_hi); } --- 6063,6069 ---- expr_hi = NULL_TREE; if (!parser->in_switch_statement_p) ! error ("case label %qE not within a switch statement", expr); else statement = finish_case_label (expr, expr_hi); } *************** cp_parser_labeled_statement (cp_parser* *** 5608,5614 **** /* Require the `:' token. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the labeled statement. */ ! cp_parser_statement (parser, in_statement_expr_p); /* Return the label, in the case of a `case' or `default' label. */ return statement; --- 6087,6093 ---- /* Require the `:' token. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the labeled statement. */ ! cp_parser_statement (parser, in_statement_expr); /* Return the label, in the case of a `case' or `default' label. */ return statement; *************** cp_parser_labeled_statement (cp_parser* *** 5625,5654 **** expression statement. */ static tree ! cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p) { tree statement = NULL_TREE; /* If the next token is a ';', then there is no expression statement. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) ! statement = cp_parser_expression (parser); ! /* Consume the final `;'. */ cp_parser_consume_semicolon_at_end_of_statement (parser); ! if (in_statement_expr_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) ! { ! /* This is the final expression statement of a statement ! expression. */ ! statement = finish_stmt_expr_expr (statement); ! } else if (statement) statement = finish_expr_stmt (statement); else finish_stmt (); ! return statement; } --- 6104,6131 ---- expression statement. */ static tree ! cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) { tree statement = NULL_TREE; /* If the next token is a ';', then there is no expression statement. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) ! statement = cp_parser_expression (parser, /*cast_p=*/false); ! /* Consume the final `;'. */ cp_parser_consume_semicolon_at_end_of_statement (parser); ! if (in_statement_expr && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) ! /* This is the final expression statement of a statement ! expression. */ ! statement = finish_stmt_expr_expr (statement, in_statement_expr); else if (statement) statement = finish_expr_stmt (statement); else finish_stmt (); ! return statement; } *************** cp_parser_expression_statement (cp_parse *** 5656,5666 **** compound-statement: { statement-seq [opt] } ! ! Returns a COMPOUND_STMT representing the statement. */ static tree ! cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p) { tree compound_stmt; --- 6133,6144 ---- compound-statement: { statement-seq [opt] } ! ! Returns a tree representing the statement. */ static tree ! cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, ! bool in_try) { tree compound_stmt; *************** cp_parser_compound_statement (cp_parser *** 5668,5676 **** if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) return error_mark_node; /* Begin the compound-statement. */ ! compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); /* Parse an (optional) statement-seq. */ ! cp_parser_statement_seq_opt (parser, in_statement_expr_p); /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ --- 6146,6154 ---- if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) return error_mark_node; /* Begin the compound-statement. */ ! compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); /* Parse an (optional) statement-seq. */ ! cp_parser_statement_seq_opt (parser, in_statement_expr); /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ *************** cp_parser_compound_statement (cp_parser *** 5686,5692 **** statement-seq [opt] statement */ static void ! cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p) { /* Scan statements until there aren't any more. */ while (true) --- 6164,6170 ---- statement-seq [opt] statement */ static void ! cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) { /* Scan statements until there aren't any more. */ while (true) *************** cp_parser_statement_seq_opt (cp_parser* *** 5697,5703 **** break; /* Parse the statement. */ ! cp_parser_statement (parser, in_statement_expr_p); } } --- 6175,6181 ---- break; /* Parse the statement. */ ! cp_parser_statement (parser, in_statement_expr); } } *************** cp_parser_statement_seq_opt (cp_parser* *** 5706,5712 **** selection-statement: if ( condition ) statement if ( condition ) statement else statement ! switch ( condition ) statement Returns the new IF_STMT or SWITCH_STMT. */ --- 6184,6190 ---- selection-statement: if ( condition ) statement if ( condition ) statement else statement ! switch ( condition ) statement Returns the new IF_STMT or SWITCH_STMT. */ *************** cp_parser_selection_statement (cp_parser *** 5751,5785 **** if (keyword == RID_IF) { - tree then_stmt; - /* Add the condition. */ finish_if_stmt_cond (condition, statement); /* Parse the then-clause. */ ! then_stmt = cp_parser_implicitly_scoped_statement (parser); finish_then_clause (statement); /* If the next token is `else', parse the else-clause. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE)) { - tree else_stmt; - /* Consume the `else' keyword. */ cp_lexer_consume_token (parser->lexer); /* Parse the else-clause. */ ! else_stmt ! = cp_parser_implicitly_scoped_statement (parser); finish_else_clause (statement); } /* Now we're all done with the if-statement. */ ! finish_if_stmt (); } else { - tree body; bool in_switch_statement_p; /* Add the condition. */ --- 6229,6258 ---- if (keyword == RID_IF) { /* Add the condition. */ finish_if_stmt_cond (condition, statement); /* Parse the then-clause. */ ! cp_parser_implicitly_scoped_statement (parser); finish_then_clause (statement); /* If the next token is `else', parse the else-clause. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE)) { /* Consume the `else' keyword. */ cp_lexer_consume_token (parser->lexer); + begin_else_clause (statement); /* Parse the else-clause. */ ! cp_parser_implicitly_scoped_statement (parser); finish_else_clause (statement); } /* Now we're all done with the if-statement. */ ! finish_if_stmt (statement); } else { bool in_switch_statement_p; /* Add the condition. */ *************** cp_parser_selection_statement (cp_parser *** 5788,5794 **** /* Parse the body of the switch-statement. */ in_switch_statement_p = parser->in_switch_statement_p; parser->in_switch_statement_p = true; ! body = cp_parser_implicitly_scoped_statement (parser); parser->in_switch_statement_p = in_switch_statement_p; /* Now we're all done with the switch-statement. */ --- 6261,6267 ---- /* Parse the body of the switch-statement. */ in_switch_statement_p = parser->in_switch_statement_p; parser->in_switch_statement_p = true; ! cp_parser_implicitly_scoped_statement (parser); parser->in_switch_statement_p = in_switch_statement_p; /* Now we're all done with the switch-statement. */ *************** cp_parser_selection_statement (cp_parser *** 5805,5828 **** } } ! /* Parse a condition. condition: expression ! type-specifier-seq declarator = assignment-expression GNU Extension: ! condition: ! type-specifier-seq declarator asm-specification [opt] attributes [opt] = assignment-expression ! Returns the expression that should be tested. */ static tree cp_parser_condition (cp_parser* parser) { ! tree type_specifiers; const char *saved_message; /* Try the declaration first. */ --- 6278,6301 ---- } } ! /* Parse a condition. condition: expression ! type-specifier-seq declarator = assignment-expression GNU Extension: ! condition: ! type-specifier-seq declarator asm-specification [opt] attributes [opt] = assignment-expression ! Returns the expression that should be tested. */ static tree cp_parser_condition (cp_parser* parser) { ! cp_decl_specifier_seq type_specifiers; const char *saved_message; /* Try the declaration first. */ *************** cp_parser_condition (cp_parser* parser) *** 5833,5839 **** parser->type_definition_forbidden_message = "types may not be defined in conditions"; /* Parse the type-specifier-seq. */ ! type_specifiers = cp_parser_type_specifier_seq (parser); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* If all is well, we might be looking at a declaration. */ --- 6306,6313 ---- parser->type_definition_forbidden_message = "types may not be defined in conditions"; /* Parse the type-specifier-seq. */ ! cp_parser_type_specifier_seq (parser, /*is_condition==*/true, ! &type_specifiers); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* If all is well, we might be looking at a declaration. */ *************** cp_parser_condition (cp_parser* parser) *** 5842,5850 **** tree decl; tree asm_specification; tree attributes; ! tree declarator; tree initializer = NULL_TREE; ! /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, --- 6316,6324 ---- tree decl; tree asm_specification; tree attributes; ! cp_declarator *declarator; tree initializer = NULL_TREE; ! /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, *************** cp_parser_condition (cp_parser* parser) *** 5856,5864 **** asm_specification = cp_parser_asm_specification_opt (parser); /* If the next token is not an `=', then we might still be looking at an expression. For example: ! if (A(a).x) ! looks like a decl-specifier-seq and a declarator -- but then there is no `=', so this is an expression. */ cp_parser_require (parser, CPP_EQ, "`='"); --- 6330,6338 ---- asm_specification = cp_parser_asm_specification_opt (parser); /* If the next token is not an `=', then we might still be looking at an expression. For example: ! if (A(a).x) ! looks like a decl-specifier-seq and a declarator -- but then there is no `=', so this is an expression. */ cp_parser_require (parser, CPP_EQ, "`='"); *************** cp_parser_condition (cp_parser* parser) *** 5866,5884 **** for sure. */ if (cp_parser_parse_definitely (parser)) { /* Create the declaration. */ ! decl = start_decl (declarator, type_specifiers, /*initialized_p=*/true, ! attributes, /*prefix_attributes=*/NULL_TREE); /* Parse the assignment-expression. */ ! initializer = cp_parser_assignment_expression (parser); ! /* Process the initializer. */ ! cp_finish_decl (decl, ! initializer, ! asm_specification, LOOKUP_ONLYCONVERTING); ! return convert_from_reference (decl); } } --- 6340,6365 ---- for sure. */ if (cp_parser_parse_definitely (parser)) { + tree pushed_scope; + /* Create the declaration. */ ! decl = start_decl (declarator, &type_specifiers, /*initialized_p=*/true, ! attributes, /*prefix_attributes=*/NULL_TREE, ! &pushed_scope); /* Parse the assignment-expression. */ ! initializer = cp_parser_assignment_expression (parser, ! /*cast_p=*/false); ! /* Process the initializer. */ ! cp_finish_decl (decl, ! initializer, ! asm_specification, LOOKUP_ONLYCONVERTING); ! ! if (pushed_scope) ! pop_scope (pushed_scope); ! return convert_from_reference (decl); } } *************** cp_parser_condition (cp_parser* parser) *** 5888,5894 **** cp_parser_abort_tentative_parse (parser); /* Otherwise, we are looking at an expression. */ ! return cp_parser_expression (parser); } /* Parse an iteration-statement. --- 6369,6375 ---- cp_parser_abort_tentative_parse (parser); /* Otherwise, we are looking at an expression. */ ! return cp_parser_expression (parser, /*cast_p=*/false); } /* Parse an iteration-statement. *************** cp_parser_iteration_statement (cp_parser *** 5916,5922 **** return error_mark_node; /* Remember whether or not we are already within an iteration ! statement. */ in_iteration_statement_p = parser->in_iteration_statement_p; /* See what kind of keyword it is. */ --- 6397,6403 ---- return error_mark_node; /* Remember whether or not we are already within an iteration ! statement. */ in_iteration_statement_p = parser->in_iteration_statement_p; /* See what kind of keyword it is. */ *************** cp_parser_iteration_statement (cp_parser *** 5961,5967 **** /* Look for the `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); /* Parse the expression. */ ! expression = cp_parser_expression (parser); /* We're done with the do-statement. */ finish_do_stmt (expression, statement); /* Look for the `)'. */ --- 6442,6448 ---- /* Look for the `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); /* Parse the expression. */ ! expression = cp_parser_expression (parser, /*cast_p=*/false); /* We're done with the do-statement. */ finish_do_stmt (expression, statement); /* Look for the `)'. */ *************** cp_parser_iteration_statement (cp_parser *** 5993,6003 **** /* If there's an expression, process it. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) ! expression = cp_parser_expression (parser); finish_for_expr (expression, statement); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); ! /* Parse the body of the for-statement. */ parser->in_iteration_statement_p = true; cp_parser_already_scoped_statement (parser); --- 6474,6484 ---- /* If there's an expression, process it. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) ! expression = cp_parser_expression (parser, /*cast_p=*/false); finish_for_expr (expression, statement); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); ! /* Parse the body of the for-statement. */ parser->in_iteration_statement_p = true; cp_parser_already_scoped_statement (parser); *************** cp_parser_for_init_statement (cp_parser* *** 6055,6069 **** break ; continue ; return expression [opt] ; ! goto identifier ; GNU extension: jump-statement: goto * expression ; ! Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_STMT, or ! GOTO_STMT. */ static tree cp_parser_jump_statement (cp_parser* parser) --- 6536,6549 ---- break ; continue ; return expression [opt] ; ! goto identifier ; GNU extension: jump-statement: goto * expression ; ! Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_EXPR, or GOTO_EXPR. */ static tree cp_parser_jump_statement (cp_parser* parser) *************** cp_parser_jump_statement (cp_parser* par *** 6090,6096 **** } else statement = finish_break_stmt (); ! cp_parser_require (parser, CPP_SEMICOLON, "`;'"); break; case RID_CONTINUE: --- 6570,6576 ---- } else statement = finish_break_stmt (); ! cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); break; case RID_CONTINUE: *************** cp_parser_jump_statement (cp_parser* par *** 6101,6123 **** } else statement = finish_continue_stmt (); ! cp_parser_require (parser, CPP_SEMICOLON, "`;'"); break; case RID_RETURN: { tree expr; ! /* If the next token is a `;', then there is no expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) ! expr = cp_parser_expression (parser); else expr = NULL_TREE; /* Build the return-statement. */ statement = finish_return_stmt (expr); /* Look for the final `;'. */ ! cp_parser_require (parser, CPP_SEMICOLON, "`;'"); } break; --- 6581,6603 ---- } else statement = finish_continue_stmt (); ! cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); break; case RID_RETURN: { tree expr; ! /* If the next token is a `;', then there is no expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) ! expr = cp_parser_expression (parser, /*cast_p=*/false); else expr = NULL_TREE; /* Build the return-statement. */ statement = finish_return_stmt (expr); /* Look for the final `;'. */ ! cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); } break; *************** cp_parser_jump_statement (cp_parser* par *** 6131,6142 **** /* Consume the '*' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the dependent expression. */ ! finish_goto_stmt (cp_parser_expression (parser)); } else finish_goto_stmt (cp_parser_identifier (parser)); /* Look for the final `;'. */ ! cp_parser_require (parser, CPP_SEMICOLON, "`;'"); break; default: --- 6611,6622 ---- /* Consume the '*' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the dependent expression. */ ! finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false)); } else finish_goto_stmt (cp_parser_identifier (parser)); /* Look for the final `;'. */ ! cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); break; default: *************** cp_parser_jump_statement (cp_parser* par *** 6155,6163 **** static void cp_parser_declaration_statement (cp_parser* parser) { ! /* Parse the block-declaration. */ cp_parser_block_declaration (parser, /*statement_p=*/true); /* Finish off the statement. */ finish_stmt (); } --- 6635,6651 ---- static void cp_parser_declaration_statement (cp_parser* parser) { ! void *p; ! ! /* Get the high-water mark for the DECLARATOR_OBSTACK. */ ! p = obstack_alloc (&declarator_obstack, 0); ! ! /* Parse the block-declaration. */ cp_parser_block_declaration (parser, /*statement_p=*/true); + /* Free any declarators allocated. */ + obstack_free (&declarator_obstack, p); + /* Finish off the statement. */ finish_stmt (); } *************** cp_parser_declaration_statement (cp_pars *** 6169,6175 **** declarations appearing in the dependent statement are out of scope after control passes that point. This function parses a statement, but ensures that is in its own scope, even if it is not a ! compound-statement. Returns the new statement. */ --- 6657,6663 ---- declarations appearing in the dependent statement are out of scope after control passes that point. This function parses a statement, but ensures that is in its own scope, even if it is not a ! compound-statement. Returns the new statement. */ *************** cp_parser_implicitly_scoped_statement (c *** 6182,6188 **** if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) { /* Create a compound-statement. */ ! statement = begin_compound_stmt (/*has_no_scope=*/false); /* Parse the dependent-statement. */ cp_parser_statement (parser, false); /* Finish the dummy compound-statement. */ --- 6670,6676 ---- if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) { /* Create a compound-statement. */ ! statement = begin_compound_stmt (0); /* Parse the dependent-statement. */ cp_parser_statement (parser, false); /* Finish the dummy compound-statement. */ *************** cp_parser_implicitly_scoped_statement (c *** 6190,6196 **** } /* Otherwise, we simply parse the statement directly. */ else ! statement = cp_parser_compound_statement (parser, false); /* Return the statement. */ return statement; --- 6678,6684 ---- } /* Otherwise, we simply parse the statement directly. */ else ! statement = cp_parser_compound_statement (parser, NULL, false); /* Return the statement. */ return statement; *************** cp_parser_implicitly_scoped_statement (c *** 6204,6224 **** static void cp_parser_already_scoped_statement (cp_parser* parser) { ! /* If the token is not a `{', then we must take special action. */ ! if (cp_lexer_next_token_is_not(parser->lexer, CPP_OPEN_BRACE)) { ! tree statement; ! ! /* Create a compound-statement. */ ! statement = begin_compound_stmt (/*has_no_scope=*/true); ! /* Parse the dependent-statement. */ ! cp_parser_statement (parser, false); ! /* Finish the dummy compound-statement. */ ! finish_compound_stmt (statement); } - /* Otherwise, we simply parse the statement directly. */ - else - cp_parser_statement (parser, false); } /* Declarations [gram.dcl.dcl] */ --- 6692,6708 ---- static void cp_parser_already_scoped_statement (cp_parser* parser) { ! /* If the token is a `{', then we must take special action. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) ! cp_parser_statement (parser, false); ! else { ! /* Avoid calling cp_parser_compound_statement, so that we ! don't create a new scope. Do everything else by hand. */ ! cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); ! cp_parser_statement_seq_opt (parser, false); ! cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); } } /* Declarations [gram.dcl.dcl] */ *************** cp_parser_declaration_seq_opt (cp_parser *** 6242,6268 **** || token->type == CPP_EOF) break; ! if (token->type == CPP_SEMICOLON) { /* A declaration consisting of a single semicolon is invalid. Allow it unless we're being pedantic. */ - if (pedantic && !in_system_header) - pedwarn ("extra `;'"); cp_lexer_consume_token (parser->lexer); continue; } ! /* The C lexer modifies PENDING_LANG_CHANGE when it wants the ! parser to enter or exit implicit `extern "C"' blocks. */ ! while (pending_lang_change > 0) { push_lang_context (lang_name_c); ! --pending_lang_change; } ! while (pending_lang_change < 0) { pop_lang_context (); ! ++pending_lang_change; } /* Parse the declaration itself. */ --- 6726,6762 ---- || token->type == CPP_EOF) break; ! if (token->type == CPP_SEMICOLON) { /* A declaration consisting of a single semicolon is invalid. Allow it unless we're being pedantic. */ cp_lexer_consume_token (parser->lexer); + if (pedantic && !in_system_header) + pedwarn ("extra %<;%>"); continue; } ! /* If we're entering or exiting a region that's implicitly ! extern "C", modify the lang context appropriately. */ ! if (!parser->implicit_extern_c && token->implicit_extern_c) { push_lang_context (lang_name_c); ! parser->implicit_extern_c = true; } ! else if (parser->implicit_extern_c && !token->implicit_extern_c) { pop_lang_context (); ! parser->implicit_extern_c = false; ! } ! ! if (token->type == CPP_PRAGMA) ! { ! /* A top-level declaration can consist solely of a #pragma. ! A nested declaration cannot, so this is done here and not ! in cp_parser_declaration. (A #pragma at block scope is ! handled in cp_parser_statement.) */ ! cp_lexer_handle_pragma (parser->lexer); ! continue; } /* Parse the declaration itself. */ *************** cp_parser_declaration_seq_opt (cp_parser *** 6279,6285 **** explicit-instantiation explicit-specialization linkage-specification ! namespace-definition GNU extension: --- 6773,6779 ---- explicit-instantiation explicit-specialization linkage-specification ! namespace-definition GNU extension: *************** cp_parser_declaration (cp_parser* parser *** 6292,6297 **** --- 6786,6792 ---- cp_token token1; cp_token token2; int saved_pedantic; + void *p; /* Check for the `__extension__' keyword. */ if (cp_parser_extension_opt (parser, &saved_pedantic)) *************** cp_parser_declaration (cp_parser* parser *** 6306,6314 **** --- 6801,6813 ---- /* Try to figure out what kind of declaration is present. */ token1 = *cp_lexer_peek_token (parser->lexer); + if (token1.type != CPP_EOF) token2 = *cp_lexer_peek_nth_token (parser->lexer, 2); + /* Get the high-water mark for the DECLARATOR_OBSTACK. */ + p = obstack_alloc (&declarator_obstack, 0); + /* If the next token is `extern' and the following token is a string literal, then we have a linkage specification. */ if (token1.keyword == RID_EXTERN *************** cp_parser_declaration (cp_parser* parser *** 6348,6354 **** else if (token1.keyword == RID_NAMESPACE && (/* A named namespace definition. */ (token2.type == CPP_NAME ! && (cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_BRACE)) /* An unnamed namespace definition. */ || token2.type == CPP_OPEN_BRACE)) --- 6847,6853 ---- else if (token1.keyword == RID_NAMESPACE && (/* A named namespace definition. */ (token2.type == CPP_NAME ! && (cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_BRACE)) /* An unnamed namespace definition. */ || token2.type == CPP_OPEN_BRACE)) *************** cp_parser_declaration (cp_parser* parser *** 6358,6385 **** else /* Try to parse a block-declaration, or a function-definition. */ cp_parser_block_declaration (parser, /*statement_p=*/false); } ! /* Parse a block-declaration. block-declaration: simple-declaration asm-definition namespace-alias-definition using-declaration ! using-directive GNU Extension: block-declaration: ! __extension__ block-declaration label-declaration If STATEMENT_P is TRUE, then this block-declaration is occurring as part of a declaration-statement. */ static void ! cp_parser_block_declaration (cp_parser *parser, bool statement_p) { cp_token *token1; --- 6857,6887 ---- else /* Try to parse a block-declaration, or a function-definition. */ cp_parser_block_declaration (parser, /*statement_p=*/false); + + /* Free any declarators allocated. */ + obstack_free (&declarator_obstack, p); } ! /* Parse a block-declaration. block-declaration: simple-declaration asm-definition namespace-alias-definition using-declaration ! using-directive GNU Extension: block-declaration: ! __extension__ block-declaration label-declaration If STATEMENT_P is TRUE, then this block-declaration is occurring as part of a declaration-statement. */ static void ! cp_parser_block_declaration (cp_parser *parser, bool statement_p) { cp_token *token1; *************** cp_parser_block_declaration (cp_parser * *** 6443,6463 **** /* Parse a simple-declaration. simple-declaration: ! decl-specifier-seq [opt] init-declarator-list [opt] ; init-declarator-list: init-declarator ! init-declarator-list , init-declarator If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a function-definition as a simple-declaration. */ static void ! cp_parser_simple_declaration (cp_parser* parser, bool function_definition_allowed_p) { ! tree decl_specifiers; ! tree attributes; int declares_class_or_enum; bool saw_declarator; --- 6945,6964 ---- /* Parse a simple-declaration. simple-declaration: ! decl-specifier-seq [opt] init-declarator-list [opt] ; init-declarator-list: init-declarator ! init-declarator-list , init-declarator If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a function-definition as a simple-declaration. */ static void ! cp_parser_simple_declaration (cp_parser* parser, bool function_definition_allowed_p) { ! cp_decl_specifier_seq decl_specifiers; int declares_class_or_enum; bool saw_declarator; *************** cp_parser_simple_declaration (cp_parser* *** 6469,6475 **** /* Parse the decl-specifier-seq. We have to keep track of whether or not the decl-specifier-seq declares a named class or enumeration type, since that is the only case in which the ! init-declarator-list is allowed to be empty. [dcl.dcl] --- 6970,6976 ---- /* Parse the decl-specifier-seq. We have to keep track of whether or not the decl-specifier-seq declares a named class or enumeration type, since that is the only case in which the ! init-declarator-list is allowed to be empty. [dcl.dcl] *************** cp_parser_simple_declaration (cp_parser* *** 6477,6494 **** omitted only when declaring a class or enumeration, that is when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier, or an enum-specifier. */ ! decl_specifiers ! = cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_OPTIONAL, ! &attributes, ! &declares_class_or_enum); /* We no longer need to defer access checks. */ stop_deferring_access_checks (); /* In a block scope, a valid declaration must always have a decl-specifier-seq. By not trying to parse declarators, we can resolve the declaration/expression ambiguity more quickly. */ ! if (!function_definition_allowed_p && !decl_specifiers) { cp_parser_error (parser, "expected declaration"); goto done; --- 6978,6995 ---- omitted only when declaring a class or enumeration, that is when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier, or an enum-specifier. */ ! cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_OPTIONAL, ! &decl_specifiers, ! &declares_class_or_enum); /* We no longer need to defer access checks. */ stop_deferring_access_checks (); /* In a block scope, a valid declaration must always have a decl-specifier-seq. By not trying to parse declarators, we can resolve the declaration/expression ambiguity more quickly. */ ! if (!function_definition_allowed_p ! && !decl_specifiers.any_specifiers_p) { cp_parser_error (parser, "expected declaration"); goto done; *************** cp_parser_simple_declaration (cp_parser* *** 6500,6506 **** T t; where "T" should name a type -- but does not. */ ! if (cp_parser_diagnose_invalid_type_name (parser)) { /* If parsing tentatively, we should commit; we really are looking at a declaration. */ --- 7001,7008 ---- T t; where "T" should name a type -- but does not. */ ! if (!decl_specifiers.type ! && cp_parser_parse_and_diagnose_invalid_type_name (parser)) { /* If parsing tentatively, we should commit; we really are looking at a declaration. */ *************** cp_parser_simple_declaration (cp_parser* *** 6508,6518 **** /* Give up. */ goto done; } /* Keep going until we hit the `;' at the end of the simple declaration. */ saw_declarator = false; ! while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { cp_token *token; --- 7010,7027 ---- /* Give up. */ goto done; } + + /* If we have seen at least one decl-specifier, and the next token + is not a parenthesis, then we must be looking at a declaration. + (After "int (" we might be looking at a functional cast.) */ + if (decl_specifiers.any_specifiers_p + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + cp_parser_commit_to_tentative_parse (parser); /* Keep going until we hit the `;' at the end of the simple declaration. */ saw_declarator = false; ! while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { cp_token *token; *************** cp_parser_simple_declaration (cp_parser* *** 6521,6527 **** saw_declarator = true; /* Parse the init-declarator. */ ! decl = cp_parser_init_declarator (parser, decl_specifiers, attributes, function_definition_allowed_p, /*member_p=*/false, declares_class_or_enum, --- 7030,7036 ---- saw_declarator = true; /* Parse the init-declarator. */ ! decl = cp_parser_init_declarator (parser, &decl_specifiers, function_definition_allowed_p, /*member_p=*/false, declares_class_or_enum, *************** cp_parser_simple_declaration (cp_parser* *** 6561,6567 **** /* Anything else is an error. */ else { ! cp_parser_error (parser, "expected `,' or `;'"); /* Skip tokens until we reach the end of the statement. */ cp_parser_skip_to_end_of_statement (parser); /* If the next token is now a `;', consume it. */ --- 7070,7080 ---- /* Anything else is an error. */ else { ! /* If we have already issued an error message we don't need ! to issue another one. */ ! if (decl != error_mark_node ! || cp_parser_uncommitted_to_tentative_parse_p (parser)) ! cp_parser_error (parser, "expected %<,%> or %<;%>"); /* Skip tokens until we reach the end of the statement. */ cp_parser_skip_to_end_of_statement (parser); /* If the next token is now a `;', consume it. */ *************** cp_parser_simple_declaration (cp_parser* *** 6584,6590 **** if (!saw_declarator) { if (cp_parser_declares_only_class_p (parser)) ! shadow_tag (decl_specifiers); /* Perform any deferred access checks. */ perform_deferred_access_checks (); } --- 7097,7103 ---- if (!saw_declarator) { if (cp_parser_declares_only_class_p (parser)) ! shadow_tag (&decl_specifiers); /* Perform any deferred access checks. */ perform_deferred_access_checks (); } *************** cp_parser_simple_declaration (cp_parser* *** 6606,6632 **** type-specifier function-specifier friend ! typedef GNU Extension: decl-specifier: attributes ! Returns a TREE_LIST, giving the decl-specifiers in the order they ! appear in the source code. The TREE_VALUE of each node is the ! decl-specifier. For a keyword (such as `auto' or `friend'), the ! TREE_VALUE is simply the corresponding TREE_IDENTIFIER. For the ! representation of a type-specifier, see cp_parser_type_specifier. ! ! If there are attributes, they will be stored in *ATTRIBUTES, ! represented as described above cp_parser_attributes. ! If FRIEND_IS_NOT_CLASS_P is non-NULL, and the `friend' specifier ! appears, and the entity that will be a friend is not going to be a ! class, then *FRIEND_IS_NOT_CLASS_P will be set to TRUE. Note that ! even if *FRIEND_IS_NOT_CLASS_P is FALSE, the entity to which ! friendship is granted might not be a class. *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following flags: --- 7119,7134 ---- type-specifier function-specifier friend ! typedef GNU Extension: decl-specifier: attributes ! Set *DECL_SPECS to a representation of the decl-specifier-seq. ! The parser flags FLAGS is used to control type-specifier parsing. *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following flags: *************** cp_parser_simple_declaration (cp_parser* *** 6638,6664 **** */ ! static tree ! cp_parser_decl_specifier_seq (cp_parser* parser, ! cp_parser_flags flags, ! tree* attributes, int* declares_class_or_enum) { - tree decl_specs = NULL_TREE; - bool friend_p = false; bool constructor_possible_p = !parser->in_declarator_p; ! /* Assume no class or enumeration type is declared. */ *declares_class_or_enum = 0; - /* Assume there are no attributes. */ - *attributes = NULL_TREE; - /* Keep reading specifiers until there are no more to read. */ while (true) { - tree decl_spec = NULL_TREE; bool constructor_p; cp_token *token; /* Peek at the next token. */ --- 7140,7164 ---- */ ! static void ! cp_parser_decl_specifier_seq (cp_parser* parser, ! cp_parser_flags flags, ! cp_decl_specifier_seq *decl_specs, int* declares_class_or_enum) { bool constructor_possible_p = !parser->in_declarator_p; ! ! /* Clear DECL_SPECS. */ ! clear_decl_specs (decl_specs); ! /* Assume no class or enumeration type is declared. */ *declares_class_or_enum = 0; /* Keep reading specifiers until there are no more to read. */ while (true) { bool constructor_p; + bool found_decl_spec; cp_token *token; /* Peek at the next token. */ *************** cp_parser_decl_specifier_seq (cp_parser* *** 6667,6691 **** if (token->keyword == RID_ATTRIBUTE) { /* Parse the attributes. */ ! decl_spec = cp_parser_attributes_opt (parser); ! /* Add them to the list. */ ! *attributes = chainon (*attributes, decl_spec); continue; } /* If the next token is an appropriate keyword, we can simply add it to the list. */ switch (token->keyword) { - case RID_FRIEND: /* decl-specifier: friend */ ! if (friend_p) ! error ("duplicate `friend'"); ! else ! friend_p = true; ! /* The representation of the specifier is simply the ! appropriate TREE_IDENTIFIER node. */ ! decl_spec = token->value; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); break; --- 7167,7188 ---- if (token->keyword == RID_ATTRIBUTE) { /* Parse the attributes. */ ! decl_specs->attributes ! = chainon (decl_specs->attributes, ! cp_parser_attributes_opt (parser)); continue; } + /* Assume we will find a decl-specifier keyword. */ + found_decl_spec = true; /* If the next token is an appropriate keyword, we can simply add it to the list. */ switch (token->keyword) { /* decl-specifier: friend */ ! case RID_FRIEND: ! if (decl_specs->specs[(int) ds_friend]++) ! error ("duplicate %"); /* Consume the token. */ cp_lexer_consume_token (parser->lexer); break; *************** cp_parser_decl_specifier_seq (cp_parser* *** 6697,6711 **** case RID_INLINE: case RID_VIRTUAL: case RID_EXPLICIT: ! decl_spec = cp_parser_function_specifier_opt (parser); break; ! /* decl-specifier: typedef */ case RID_TYPEDEF: ! /* The representation of the specifier is simply the ! appropriate TREE_IDENTIFIER node. */ ! decl_spec = token->value; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); /* A constructor declarator cannot appear in a typedef. */ --- 7194,7206 ---- case RID_INLINE: case RID_VIRTUAL: case RID_EXPLICIT: ! cp_parser_function_specifier_opt (parser, decl_specs); break; ! /* decl-specifier: typedef */ case RID_TYPEDEF: ! ++decl_specs->specs[(int) ds_typedef]; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); /* A constructor declarator cannot appear in a typedef. */ *************** cp_parser_decl_specifier_seq (cp_parser* *** 6720,6759 **** register static extern ! mutable GNU Extension: thread */ case RID_AUTO: case RID_REGISTER: case RID_STATIC: case RID_EXTERN: case RID_MUTABLE: case RID_THREAD: ! decl_spec = cp_parser_storage_class_specifier_opt (parser); break; ! default: break; } /* Constructors are a special case. The `S' in `S()' is not a decl-specifier; it is the beginning of the declarator. */ ! constructor_p = (!decl_spec ! && constructor_possible_p ! && cp_parser_constructor_declarator_p (parser, ! friend_p)); /* If we don't have a DECL_SPEC yet, then we must be looking at a type-specifier. */ ! if (!decl_spec && !constructor_p) { int decl_spec_declares_class_or_enum; bool is_cv_qualifier; ! decl_spec = cp_parser_type_specifier (parser, flags, ! friend_p, /*is_declaration=*/true, &decl_spec_declares_class_or_enum, &is_cv_qualifier); --- 7215,7290 ---- register static extern ! mutable GNU Extension: thread */ case RID_AUTO: + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + cp_parser_set_storage_class (decl_specs, sc_auto); + break; case RID_REGISTER: + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + cp_parser_set_storage_class (decl_specs, sc_register); + break; case RID_STATIC: + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + if (decl_specs->specs[(int) ds_thread]) + { + error ("%<__thread%> before %"); + decl_specs->specs[(int) ds_thread] = 0; + } + cp_parser_set_storage_class (decl_specs, sc_static); + break; case RID_EXTERN: + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + if (decl_specs->specs[(int) ds_thread]) + { + error ("%<__thread%> before %"); + decl_specs->specs[(int) ds_thread] = 0; + } + cp_parser_set_storage_class (decl_specs, sc_extern); + break; case RID_MUTABLE: + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + cp_parser_set_storage_class (decl_specs, sc_mutable); + break; case RID_THREAD: ! /* Consume the token. */ ! cp_lexer_consume_token (parser->lexer); ! ++decl_specs->specs[(int) ds_thread]; break; ! default: + /* We did not yet find a decl-specifier yet. */ + found_decl_spec = false; break; } /* Constructors are a special case. The `S' in `S()' is not a decl-specifier; it is the beginning of the declarator. */ ! constructor_p ! = (!found_decl_spec ! && constructor_possible_p ! && (cp_parser_constructor_declarator_p ! (parser, decl_specs->specs[(int) ds_friend] != 0))); /* If we don't have a DECL_SPEC yet, then we must be looking at a type-specifier. */ ! if (!found_decl_spec && !constructor_p) { int decl_spec_declares_class_or_enum; bool is_cv_qualifier; + tree type_spec; ! type_spec = cp_parser_type_specifier (parser, flags, ! decl_specs, /*is_declaration=*/true, &decl_spec_declares_class_or_enum, &is_cv_qualifier); *************** cp_parser_decl_specifier_seq (cp_parser* *** 6778,6784 **** only exceptions are the following: -- const or volatile can be combined with any other ! type-specifier. -- signed or unsigned can be combined with char, long, short, or int. --- 7309,7315 ---- only exceptions are the following: -- const or volatile can be combined with any other ! type-specifier. -- signed or unsigned can be combined with char, long, short, or int. *************** cp_parser_decl_specifier_seq (cp_parser* *** 6796,6849 **** user-defined types. We *do* still allow things like `int int' to be considered a decl-specifier-seq, and issue the error message later. */ ! if (decl_spec && !is_cv_qualifier) flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; /* A constructor declarator cannot follow a type-specifier. */ ! if (decl_spec) ! constructor_possible_p = false; ! } ! ! /* If we still do not have a DECL_SPEC, then there are no more ! decl-specifiers. */ ! if (!decl_spec) ! { ! /* Issue an error message, unless the entire construct was ! optional. */ ! if (!(flags & CP_PARSER_FLAGS_OPTIONAL)) { ! cp_parser_error (parser, "expected decl specifier"); ! return error_mark_node; } - - break; } ! /* Add the DECL_SPEC to the list of specifiers. */ ! if (decl_specs == NULL || TREE_VALUE (decl_specs) != error_mark_node) ! decl_specs = tree_cons (NULL_TREE, decl_spec, decl_specs); /* After we see one decl-specifier, further decl-specifiers are always optional. */ flags |= CP_PARSER_FLAGS_OPTIONAL; } /* Don't allow a friend specifier with a class definition. */ ! if (friend_p && (*declares_class_or_enum & 2)) error ("class definition may not be declared a friend"); - - /* We have built up the DECL_SPECS in reverse order. Return them in - the correct order. */ - return nreverse (decl_specs); } ! /* Parse an (optional) storage-class-specifier. storage-class-specifier: auto register static extern ! mutable GNU Extension: --- 7327,7367 ---- user-defined types. We *do* still allow things like `int int' to be considered a decl-specifier-seq, and issue the error message later. */ ! if (type_spec && !is_cv_qualifier) flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; /* A constructor declarator cannot follow a type-specifier. */ ! if (type_spec) { ! constructor_possible_p = false; ! found_decl_spec = true; } } ! /* If we still do not have a DECL_SPEC, then there are no more ! decl-specifiers. */ ! if (!found_decl_spec) ! break; + decl_specs->any_specifiers_p = true; /* After we see one decl-specifier, further decl-specifiers are always optional. */ flags |= CP_PARSER_FLAGS_OPTIONAL; } /* Don't allow a friend specifier with a class definition. */ ! if (decl_specs->specs[(int) ds_friend] != 0 ! && (*declares_class_or_enum & 2)) error ("class definition may not be declared a friend"); } ! /* Parse an (optional) storage-class-specifier. storage-class-specifier: auto register static extern ! mutable GNU Extension: *************** cp_parser_decl_specifier_seq (cp_parser* *** 6851,6857 **** thread Returns an IDENTIFIER_NODE corresponding to the keyword used. */ ! static tree cp_parser_storage_class_specifier_opt (cp_parser* parser) { --- 7369,7375 ---- thread Returns an IDENTIFIER_NODE corresponding to the keyword used. */ ! static tree cp_parser_storage_class_specifier_opt (cp_parser* parser) { *************** cp_parser_storage_class_specifier_opt (c *** 6871,6899 **** } } ! /* Parse an (optional) function-specifier. function-specifier: inline virtual explicit ! Returns an IDENTIFIER_NODE corresponding to the keyword used. */ ! static tree ! cp_parser_function_specifier_opt (cp_parser* parser) { switch (cp_lexer_peek_token (parser->lexer)->keyword) { case RID_INLINE: case RID_VIRTUAL: case RID_EXPLICIT: ! /* Consume the token. */ ! return cp_lexer_consume_token (parser->lexer)->value; default: return NULL_TREE; } } /* Parse a linkage-specification. --- 7389,7431 ---- } } ! /* Parse an (optional) function-specifier. function-specifier: inline virtual explicit ! Returns an IDENTIFIER_NODE corresponding to the keyword used. ! Updates DECL_SPECS, if it is non-NULL. */ ! static tree ! cp_parser_function_specifier_opt (cp_parser* parser, ! cp_decl_specifier_seq *decl_specs) { switch (cp_lexer_peek_token (parser->lexer)->keyword) { case RID_INLINE: + if (decl_specs) + ++decl_specs->specs[(int) ds_inline]; + break; + case RID_VIRTUAL: + if (decl_specs) + ++decl_specs->specs[(int) ds_virtual]; + break; + case RID_EXPLICIT: ! if (decl_specs) ! ++decl_specs->specs[(int) ds_explicit]; ! break; default: return NULL_TREE; } + + /* Consume the token. */ + return cp_lexer_consume_token (parser->lexer)->value; } /* Parse a linkage-specification. *************** cp_parser_function_specifier_opt (cp_par *** 6905,6941 **** static void cp_parser_linkage_specification (cp_parser* parser) { - cp_token *token; tree linkage; /* Look for the `extern' keyword. */ cp_parser_require_keyword (parser, RID_EXTERN, "`extern'"); ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* If it's not a string-literal, then there's a problem. */ ! if (!cp_parser_is_string_literal (token)) ! { ! cp_parser_error (parser, "expected language-name"); ! return; ! } ! /* Consume the token. */ ! cp_lexer_consume_token (parser->lexer); /* Transform the literal into an identifier. If the literal is a wide-character string, or contains embedded NULs, then we can't handle it as the user wants. */ ! if (token->type == CPP_WSTRING ! || (strlen (TREE_STRING_POINTER (token->value)) ! != (size_t) (TREE_STRING_LENGTH (token->value) - 1))) { cp_parser_error (parser, "invalid linkage-specification"); /* Assume C++ linkage. */ ! linkage = get_identifier ("c++"); } - /* If it's a simple string constant, things are easier. */ else ! linkage = get_identifier (TREE_STRING_POINTER (token->value)); /* We're now using the new linkage. */ push_lang_context (linkage); --- 7437,7462 ---- static void cp_parser_linkage_specification (cp_parser* parser) { tree linkage; /* Look for the `extern' keyword. */ cp_parser_require_keyword (parser, RID_EXTERN, "`extern'"); ! /* Look for the string-literal. */ ! linkage = cp_parser_string_literal (parser, false, false); /* Transform the literal into an identifier. If the literal is a wide-character string, or contains embedded NULs, then we can't handle it as the user wants. */ ! if (strlen (TREE_STRING_POINTER (linkage)) ! != (size_t) (TREE_STRING_LENGTH (linkage) - 1)) { cp_parser_error (parser, "invalid linkage-specification"); /* Assume C++ linkage. */ ! linkage = lang_name_cplusplus; } else ! linkage = get_identifier (TREE_STRING_POINTER (linkage)); /* We're now using the new linkage. */ push_lang_context (linkage); *************** cp_parser_linkage_specification (cp_pars *** 6956,6968 **** { bool saved_in_unbraced_linkage_specification_p; ! saved_in_unbraced_linkage_specification_p = parser->in_unbraced_linkage_specification_p; parser->in_unbraced_linkage_specification_p = true; have_extern_spec = true; cp_parser_declaration (parser); have_extern_spec = false; ! parser->in_unbraced_linkage_specification_p = saved_in_unbraced_linkage_specification_p; } --- 7477,7489 ---- { bool saved_in_unbraced_linkage_specification_p; ! saved_in_unbraced_linkage_specification_p = parser->in_unbraced_linkage_specification_p; parser->in_unbraced_linkage_specification_p = true; have_extern_spec = true; cp_parser_declaration (parser); have_extern_spec = false; ! parser->in_unbraced_linkage_specification_p = saved_in_unbraced_linkage_specification_p; } *************** cp_parser_linkage_specification (cp_pars *** 6975,6992 **** /* Parse a conversion-function-id. conversion-function-id: ! operator conversion-type-id Returns an IDENTIFIER_NODE representing the operator. */ ! static tree cp_parser_conversion_function_id (cp_parser* parser) { tree type; tree saved_scope; tree saved_qualifying_scope; tree saved_object_scope; ! bool pop_p = false; /* Look for the `operator' token. */ if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'")) --- 7496,7513 ---- /* Parse a conversion-function-id. conversion-function-id: ! operator conversion-type-id Returns an IDENTIFIER_NODE representing the operator. */ ! static tree cp_parser_conversion_function_id (cp_parser* parser) { tree type; tree saved_scope; tree saved_qualifying_scope; tree saved_object_scope; ! tree pushed_scope = NULL_TREE; /* Look for the `operator' token. */ if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'")) *************** cp_parser_conversion_function_id (cp_par *** 7001,7007 **** entities declared within the class are available in the conversion-type-id. For example, consider: ! struct S { typedef int I; operator I(); }; --- 7522,7528 ---- entities declared within the class are available in the conversion-type-id. For example, consider: ! struct S { typedef int I; operator I(); }; *************** cp_parser_conversion_function_id (cp_par *** 7011,7022 **** In order to see that `I' is a type-name in the definition, we must be in the scope of `S'. */ if (saved_scope) ! pop_p = push_scope (saved_scope); /* Parse the conversion-type-id. */ type = cp_parser_conversion_type_id (parser); /* Leave the scope of the class, if any. */ ! if (pop_p) ! pop_scope (saved_scope); /* Restore the saved scope. */ parser->scope = saved_scope; parser->qualifying_scope = saved_qualifying_scope; --- 7532,7543 ---- In order to see that `I' is a type-name in the definition, we must be in the scope of `S'. */ if (saved_scope) ! pushed_scope = push_scope (saved_scope); /* Parse the conversion-type-id. */ type = cp_parser_conversion_type_id (parser); /* Leave the scope of the class, if any. */ ! if (pushed_scope) ! pop_scope (pushed_scope); /* Restore the saved scope. */ parser->scope = saved_scope; parser->qualifying_scope = saved_qualifying_scope; *************** static tree *** 7038,7110 **** cp_parser_conversion_type_id (cp_parser* parser) { tree attributes; ! tree type_specifiers; ! tree declarator; /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); /* Parse the type-specifiers. */ ! type_specifiers = cp_parser_type_specifier_seq (parser); /* If that didn't work, stop. */ ! if (type_specifiers == error_mark_node) return error_mark_node; /* Parse the conversion-declarator. */ declarator = cp_parser_conversion_declarator_opt (parser); ! return grokdeclarator (declarator, type_specifiers, TYPENAME, ! /*initialized=*/0, &attributes); } /* Parse an (optional) conversion-declarator. conversion-declarator: ! ptr-operator conversion-declarator [opt] ! Returns a representation of the declarator. See ! cp_parser_declarator for details. */ ! static tree cp_parser_conversion_declarator_opt (cp_parser* parser) { enum tree_code code; tree class_type; ! tree cv_qualifier_seq; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Try the ptr-operator. */ ! code = cp_parser_ptr_operator (parser, &class_type, ! &cv_qualifier_seq); /* If it worked, look for more conversion-declarators. */ if (cp_parser_parse_definitely (parser)) { ! tree declarator; ! /* Parse another optional declarator. */ ! declarator = cp_parser_conversion_declarator_opt (parser); ! /* Create the representation of the declarator. */ ! if (code == INDIRECT_REF) ! declarator = make_pointer_declarator (cv_qualifier_seq, declarator); ! else ! declarator = make_reference_declarator (cv_qualifier_seq, ! declarator); ! ! /* Handle the pointer-to-member case. */ ! if (class_type) ! declarator = build_nt (SCOPE_REF, class_type, declarator); ! return declarator; } ! return NULL_TREE; } /* Parse an (optional) ctor-initializer. ctor-initializer: ! : mem-initializer-list Returns TRUE iff the ctor-initializer was actually present. */ --- 7559,7631 ---- cp_parser_conversion_type_id (cp_parser* parser) { tree attributes; ! cp_decl_specifier_seq type_specifiers; ! cp_declarator *declarator; ! tree type_specified; /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); /* Parse the type-specifiers. */ ! cp_parser_type_specifier_seq (parser, /*is_condition=*/false, ! &type_specifiers); /* If that didn't work, stop. */ ! if (type_specifiers.type == error_mark_node) return error_mark_node; /* Parse the conversion-declarator. */ declarator = cp_parser_conversion_declarator_opt (parser); ! type_specified = grokdeclarator (declarator, &type_specifiers, TYPENAME, ! /*initialized=*/0, &attributes); ! if (attributes) ! cplus_decl_attributes (&type_specified, attributes, /*flags=*/0); ! return type_specified; } /* Parse an (optional) conversion-declarator. conversion-declarator: ! ptr-operator conversion-declarator [opt] ! */ ! static cp_declarator * cp_parser_conversion_declarator_opt (cp_parser* parser) { enum tree_code code; tree class_type; ! cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Try the ptr-operator. */ ! code = cp_parser_ptr_operator (parser, &class_type, &cv_quals); /* If it worked, look for more conversion-declarators. */ if (cp_parser_parse_definitely (parser)) { ! cp_declarator *declarator; ! /* Parse another optional declarator. */ ! declarator = cp_parser_conversion_declarator_opt (parser); ! /* Create the representation of the declarator. */ ! if (class_type) ! declarator = make_ptrmem_declarator (cv_quals, class_type, declarator); ! else if (code == INDIRECT_REF) ! declarator = make_pointer_declarator (cv_quals, declarator); ! else ! declarator = make_reference_declarator (cv_quals, declarator); ! return declarator; } ! return NULL; } /* Parse an (optional) ctor-initializer. ctor-initializer: ! : mem-initializer-list Returns TRUE iff the ctor-initializer was actually present. */ *************** cp_parser_mem_initializer_list (cp_parse *** 7174,7183 **** /* Parse a mem-initializer. mem-initializer: ! mem-initializer-id ( expression-list [opt] ) GNU extension: ! mem-initializer: ( expression-list [opt] ) --- 7695,7704 ---- /* Parse a mem-initializer. mem-initializer: ! mem-initializer-id ( expression-list [opt] ) GNU extension: ! mem-initializer: ( expression-list [opt] ) *************** cp_parser_mem_initializer (cp_parser* pa *** 7191,7197 **** tree mem_initializer_id; tree expression_list; tree member; ! /* Find out what is being initialized. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { --- 7712,7718 ---- tree mem_initializer_id; tree expression_list; tree member; ! /* Find out what is being initialized. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { *************** cp_parser_mem_initializer (cp_parser* pa *** 7204,7217 **** if (member && !DECL_P (member)) in_base_initializer = 1; ! expression_list = cp_parser_parenthesized_expression_list (parser, false, /*non_constant_p=*/NULL); if (!expression_list) expression_list = void_type_node; in_base_initializer = 0; ! return member ? build_tree_list (member, expression_list) : NULL_TREE; } --- 7725,7739 ---- if (member && !DECL_P (member)) in_base_initializer = 1; ! expression_list = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, /*non_constant_p=*/NULL); if (!expression_list) expression_list = void_type_node; in_base_initializer = 0; ! return member ? build_tree_list (member, expression_list) : NULL_TREE; } *************** cp_parser_mem_initializer (cp_parser* pa *** 7219,7225 **** mem-initializer-id: :: [opt] nested-name-specifier [opt] class-name ! identifier Returns a TYPE indicating the class to be initializer for the first production. Returns an IDENTIFIER_NODE indicating the data member --- 7741,7747 ---- mem-initializer-id: :: [opt] nested-name-specifier [opt] class-name ! identifier Returns a TYPE indicating the class to be initializer for the first production. Returns an IDENTIFIER_NODE indicating the data member *************** cp_parser_mem_initializer_id (cp_parser* *** 7236,7249 **** /* `typename' is not allowed in this context ([temp.res]). */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)) { ! error ("keyword `typename' not allowed in this context (a qualified " "member initializer is implicitly a type)"); cp_lexer_consume_token (parser->lexer); } /* Look for the optional `::' operator. */ ! global_scope_p ! = (cp_parser_global_scope_opt (parser, ! /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the optional nested-name-specifier. The simplest way to implement: --- 7758,7771 ---- /* `typename' is not allowed in this context ([temp.res]). */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)) { ! error ("keyword % not allowed in this context (a qualified " "member initializer is implicitly a type)"); cp_lexer_consume_token (parser->lexer); } /* Look for the optional `::' operator. */ ! global_scope_p ! = (cp_parser_global_scope_opt (parser, ! /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the optional nested-name-specifier. The simplest way to implement: *************** cp_parser_mem_initializer_id (cp_parser* *** 7257,7263 **** is to assume that we have seen the `typename' keyword at this point. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/true, /*check_dependency_p=*/true, --- 7779,7785 ---- is to assume that we have seen the `typename' keyword at this point. */ ! nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/true, /*check_dependency_p=*/true, *************** cp_parser_mem_initializer_id (cp_parser* *** 7272,7288 **** return cp_parser_class_name (parser, /*typename_keyword_p=*/true, /*template_keyword_p=*/template_p, ! /*type_p=*/false, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); /* Otherwise, we could also be looking for an ordinary identifier. */ cp_parser_parse_tentatively (parser); /* Try a class-name. */ ! id = cp_parser_class_name (parser, /*typename_keyword_p=*/true, /*template_keyword_p=*/false, ! /*type_p=*/false, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); --- 7794,7810 ---- return cp_parser_class_name (parser, /*typename_keyword_p=*/true, /*template_keyword_p=*/template_p, ! none_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); /* Otherwise, we could also be looking for an ordinary identifier. */ cp_parser_parse_tentatively (parser); /* Try a class-name. */ ! id = cp_parser_class_name (parser, /*typename_keyword_p=*/true, /*template_keyword_p=*/false, ! none_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); *************** cp_parser_mem_initializer_id (cp_parser* *** 7298,7309 **** /* Parse an operator-function-id. operator-function-id: ! operator operator Returns an IDENTIFIER_NODE for the operator which is a human-readable spelling of the identifier, e.g., `operator +'. */ ! static tree cp_parser_operator_function_id (cp_parser* parser) { /* Look for the `operator' keyword. */ --- 7820,7831 ---- /* Parse an operator-function-id. operator-function-id: ! operator operator Returns an IDENTIFIER_NODE for the operator which is a human-readable spelling of the identifier, e.g., `operator +'. */ ! static tree cp_parser_operator_function_id (cp_parser* parser) { /* Look for the `operator' keyword. */ *************** cp_parser_operator_function_id (cp_parse *** 7321,7333 **** || ++ -- , ->* -> () [] GNU Extensions: ! operator: ? ?= Returns an IDENTIFIER_NODE for the operator which is a human-readable spelling of the identifier, e.g., `operator +'. */ ! static tree cp_parser_operator (cp_parser* parser) { --- 7843,7855 ---- || ++ -- , ->* -> () [] GNU Extensions: ! operator: ? ?= Returns an IDENTIFIER_NODE for the operator which is a human-readable spelling of the identifier, e.g., `operator +'. */ ! static tree cp_parser_operator (cp_parser* parser) { *************** cp_parser_operator (cp_parser* parser) *** 7364,7370 **** cp_lexer_consume_token (parser->lexer); /* Look for the `]' token. */ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); ! id = ansi_opname (op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR); } /* Otherwise, we have the non-array variant. */ --- 7886,7892 ---- cp_lexer_consume_token (parser->lexer); /* Look for the `]' token. */ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); ! id = ansi_opname (op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR); } /* Otherwise, we have the non-array variant. */ *************** cp_parser_operator (cp_parser* parser) *** 7409,7415 **** case CPP_COMPL: id = ansi_opname (BIT_NOT_EXPR); break; ! case CPP_NOT: id = ansi_opname (TRUTH_NOT_EXPR); break; --- 7931,7937 ---- case CPP_COMPL: id = ansi_opname (BIT_NOT_EXPR); break; ! case CPP_NOT: id = ansi_opname (TRUTH_NOT_EXPR); break; *************** cp_parser_operator (cp_parser* parser) *** 7497,7503 **** case CPP_OR_OR: id = ansi_opname (TRUTH_ORIF_EXPR); break; ! case CPP_PLUS_PLUS: id = ansi_opname (POSTINCREMENT_EXPR); break; --- 8019,8025 ---- case CPP_OR_OR: id = ansi_opname (TRUTH_ORIF_EXPR); break; ! case CPP_PLUS_PLUS: id = ansi_opname (POSTINCREMENT_EXPR); break; *************** cp_parser_operator (cp_parser* parser) *** 7535,7552 **** --- 8057,8078 ---- /* Extensions. */ case CPP_MIN: id = ansi_opname (MIN_EXPR); + cp_parser_warn_min_max (); break; case CPP_MAX: id = ansi_opname (MAX_EXPR); + cp_parser_warn_min_max (); break; case CPP_MIN_EQ: id = ansi_assopname (MIN_EXPR); + cp_parser_warn_min_max (); break; case CPP_MAX_EQ: id = ansi_assopname (MAX_EXPR); + cp_parser_warn_min_max (); break; default: *************** cp_parser_operator (cp_parser* parser) *** 7571,7588 **** /* Parse a template-declaration. template-declaration: ! export [opt] template < template-parameter-list > declaration If MEMBER_P is TRUE, this template-declaration occurs within a ! class-specifier. The grammar rule given by the standard isn't correct. What is really meant is: template-declaration: ! export [opt] template-parameter-list-seq decl-specifier-seq [opt] init-declarator [opt] ; ! export [opt] template-parameter-list-seq function-definition template-parameter-list-seq: --- 8097,8114 ---- /* Parse a template-declaration. template-declaration: ! export [opt] template < template-parameter-list > declaration If MEMBER_P is TRUE, this template-declaration occurs within a ! class-specifier. The grammar rule given by the standard isn't correct. What is really meant is: template-declaration: ! export [opt] template-parameter-list-seq decl-specifier-seq [opt] init-declarator [opt] ; ! export [opt] template-parameter-list-seq function-definition template-parameter-list-seq: *************** cp_parser_template_declaration (cp_parse *** 7598,7604 **** /* Consume the `export' token. */ cp_lexer_consume_token (parser->lexer); /* Warn that we do not support `export'. */ ! warning ("keyword `export' not implemented, and will be ignored"); } cp_parser_template_declaration_after_export (parser, member_p); --- 8124,8130 ---- /* Consume the `export' token. */ cp_lexer_consume_token (parser->lexer); /* Warn that we do not support `export'. */ ! warning ("keyword % not implemented, and will be ignored"); } cp_parser_template_declaration_after_export (parser, member_p); *************** cp_parser_template_parameter_list (cp_pa *** 7622,7634 **** { tree parameter; cp_token *token; /* Parse the template-parameter. */ ! parameter = cp_parser_template_parameter (parser); /* Add it to the list. */ ! parameter_list = process_template_parm (parameter_list, ! parameter); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it's not a `,', we're done. */ --- 8148,8162 ---- { tree parameter; cp_token *token; + bool is_non_type; /* Parse the template-parameter. */ ! parameter = cp_parser_template_parameter (parser, &is_non_type); /* Add it to the list. */ ! if (parameter != error_mark_node) ! parameter_list = process_template_parm (parameter_list, ! parameter, ! is_non_type); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it's not a `,', we're done. */ *************** cp_parser_template_parameter_list (cp_pa *** 7647,7660 **** type-parameter parameter-declaration ! Returns a TREE_LIST. The TREE_VALUE represents the parameter. The ! TREE_PURPOSE is the default value, if any. */ static tree ! cp_parser_template_parameter (cp_parser* parser) { cp_token *token; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it is `class' or `template', we have a type-parameter. */ --- 8175,8194 ---- type-parameter parameter-declaration ! If all goes well, returns a TREE_LIST. The TREE_VALUE represents ! the parameter. The TREE_PURPOSE is the default value, if any. ! Returns ERROR_MARK_NODE on failure. *IS_NON_TYPE is set to true ! iff this parameter is a non-type parameter. */ static tree ! cp_parser_template_parameter (cp_parser* parser, bool *is_non_type) { cp_token *token; + cp_parameter_declarator *parameter_declarator; + tree parm; + /* Assume it is a type parameter or a template parameter. */ + *is_non_type = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it is `class' or `template', we have a type-parameter. */ *************** cp_parser_template_parameter (cp_parser* *** 7666,7672 **** template ... or: ! template ... Here, the first parameter is a type parameter, and the second is --- 8200,8206 ---- template ... or: ! template ... Here, the first parameter is a type parameter, and the second is *************** cp_parser_template_parameter (cp_parser* *** 7682,7694 **** token = cp_lexer_peek_nth_token (parser->lexer, 3); /* Now, see if the token looks like the end of a template parameter. */ ! if (token->type == CPP_COMMA || token->type == CPP_EQ || token->type == CPP_GREATER) return cp_parser_type_parameter (parser); } ! /* Otherwise, it is a non-type parameter. [temp.param] --- 8216,8228 ---- token = cp_lexer_peek_nth_token (parser->lexer, 3); /* Now, see if the token looks like the end of a template parameter. */ ! if (token->type == CPP_COMMA || token->type == CPP_EQ || token->type == CPP_GREATER) return cp_parser_type_parameter (parser); } ! /* Otherwise, it is a non-type parameter. [temp.param] *************** cp_parser_template_parameter (cp_parser* *** 7696,7704 **** template-parameter, the first non-nested `>' is taken as the end of the template parameter-list rather than a greater-than operator. */ ! return ! cp_parser_parameter_declaration (parser, /*template_parm_p=*/true, ! /*parenthesized_p=*/NULL); } /* Parse a type-parameter. --- 8230,8246 ---- template-parameter, the first non-nested `>' is taken as the end of the template parameter-list rather than a greater-than operator. */ ! *is_non_type = true; ! parameter_declarator ! = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true, ! /*parenthesized_p=*/NULL); ! parm = grokdeclarator (parameter_declarator->declarator, ! ¶meter_declarator->decl_specifiers, ! PARM, /*initialized=*/0, ! /*attrlist=*/NULL); ! if (parm == error_mark_node) ! return error_mark_node; ! return build_tree_list (parameter_declarator->default_argument, parm); } /* Parse a type-parameter. *************** cp_parser_template_parameter (cp_parser* *** 7709,7716 **** typename identifier [opt] typename identifier [opt] = type-id template < template-parameter-list > class identifier [opt] ! template < template-parameter-list > class identifier [opt] ! = id-expression Returns a TREE_LIST. The TREE_VALUE is itself a TREE_LIST. The TREE_PURPOSE is the default-argument, if any. The TREE_VALUE is --- 8251,8258 ---- typename identifier [opt] typename identifier [opt] = type-id template < template-parameter-list > class identifier [opt] ! template < template-parameter-list > class identifier [opt] ! = id-expression Returns a TREE_LIST. The TREE_VALUE is itself a TREE_LIST. The TREE_PURPOSE is the default-argument, if any. The TREE_VALUE is *************** cp_parser_type_parameter (cp_parser* par *** 7723,7729 **** tree parameter; /* Look for a keyword to tell us what kind of parameter this is. */ ! token = cp_parser_require (parser, CPP_KEYWORD, "`class', `typename', or `template'"); if (!token) return error_mark_node; --- 8265,8271 ---- tree parameter; /* Look for a keyword to tell us what kind of parameter this is. */ ! token = cp_parser_require (parser, CPP_KEYWORD, "`class', `typename', or `template'"); if (!token) return error_mark_node; *************** cp_parser_type_parameter (cp_parser* par *** 7773,7779 **** cp_parser_require (parser, CPP_LESS, "`<'"); /* Parse the template-parameter-list. */ begin_template_parm_list (); ! parameter_list = cp_parser_template_parameter_list (parser); parameter_list = end_template_parm_list (parameter_list); /* Look for the `>'. */ --- 8315,8321 ---- cp_parser_require (parser, CPP_LESS, "`<'"); /* Parse the template-parameter-list. */ begin_template_parm_list (); ! parameter_list = cp_parser_template_parameter_list (parser); parameter_list = end_template_parm_list (parameter_list); /* Look for the `>'. */ *************** cp_parser_type_parameter (cp_parser* par *** 7787,7799 **** if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ) && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER) && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) ! identifier = cp_parser_identifier (parser); else identifier = NULL_TREE; /* Create the template parameter. */ parameter = finish_template_template_parm (class_type_node, identifier); ! /* If the next token is an `=', then there is a default-argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) --- 8329,8347 ---- if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ) && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER) && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) ! { ! identifier = cp_parser_identifier (parser); ! /* Treat invalid names as if the parameter were nameless. */ ! if (identifier == error_mark_node) ! identifier = NULL_TREE; ! } else identifier = NULL_TREE; + /* Create the template parameter. */ parameter = finish_template_template_parm (class_type_node, identifier); ! /* If the next token is an `=', then there is a default-argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) *************** cp_parser_type_parameter (cp_parser* par *** 7803,7809 **** /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); /* Parse the id-expression. */ ! default_argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, --- 8351,8357 ---- /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); /* Parse the id-expression. */ ! default_argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, *************** cp_parser_type_parameter (cp_parser* par *** 7816,7827 **** ; else /* Look up the name. */ ! default_argument = cp_parser_lookup_name (parser, default_argument, ! /*is_type=*/false, ! /*is_template=*/is_template, ! /*is_namespace=*/false, ! /*check_dependency=*/true); /* See if the default argument is valid. */ default_argument = check_template_template_default_arg (default_argument); --- 8364,8376 ---- ; else /* Look up the name. */ ! default_argument = cp_parser_lookup_name (parser, default_argument, ! none_type, ! /*is_template=*/is_template, ! /*is_namespace=*/false, ! /*check_dependency=*/true, ! /*ambiguous_p=*/NULL); /* See if the default argument is valid. */ default_argument = check_template_template_default_arg (default_argument); *************** cp_parser_type_parameter (cp_parser* par *** 7831,7847 **** /* Create the combined representation of the parameter and the default argument. */ ! parameter = build_tree_list (default_argument, parameter); } break; default: ! /* Anything else is an error. */ ! cp_parser_error (parser, ! "expected `class', `typename', or `template'"); ! parameter = error_mark_node; } ! return parameter; } --- 8380,8394 ---- /* Create the combined representation of the parameter and the default argument. */ ! parameter = build_tree_list (default_argument, parameter); } break; default: ! gcc_unreachable (); ! break; } ! return parameter; } *************** cp_parser_type_parameter (cp_parser* par *** 7854,7874 **** `template' keyword. In this case, a TEMPLATE_ID_EXPR will be returned. Otherwise, if the template-name names a function, or set of functions, returns a TEMPLATE_ID_EXPR. If the template-name ! names a class, returns a TYPE_DECL for the specialization. If CHECK_DEPENDENCY_P is FALSE, names are looked up in uninstantiated templates. */ static tree ! cp_parser_template_id (cp_parser *parser, ! bool template_keyword_p, bool check_dependency_p, bool is_declaration) { tree template; tree arguments; tree template_id; ! ptrdiff_t start_of_id; tree access_check = NULL_TREE; cp_token *next_token, *next_token_2; bool is_identifier; --- 8401,8421 ---- `template' keyword. In this case, a TEMPLATE_ID_EXPR will be returned. Otherwise, if the template-name names a function, or set of functions, returns a TEMPLATE_ID_EXPR. If the template-name ! names a class, returns a TYPE_DECL for the specialization. If CHECK_DEPENDENCY_P is FALSE, names are looked up in uninstantiated templates. */ static tree ! cp_parser_template_id (cp_parser *parser, ! bool template_keyword_p, bool check_dependency_p, bool is_declaration) { tree template; tree arguments; tree template_id; ! cp_token_position start_of_id = 0; tree access_check = NULL_TREE; cp_token *next_token, *next_token_2; bool is_identifier; *************** cp_parser_template_id (cp_parser *parser *** 7895,7901 **** finding a template-id. */ if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR) || (next_token->type == CPP_NAME ! && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))) { cp_parser_error (parser, "expected template-id"); --- 8442,8448 ---- finding a template-id. */ if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR) || (next_token->type == CPP_NAME ! && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))) { cp_parser_error (parser, "expected template-id"); *************** cp_parser_template_id (cp_parser *parser *** 7903,7918 **** } /* Remember where the template-id starts. */ ! if (cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) ! { ! next_token = cp_lexer_peek_token (parser->lexer); ! start_of_id = cp_lexer_token_difference (parser->lexer, ! parser->lexer->first_token, ! next_token); ! } ! else ! start_of_id = -1; push_deferring_access_checks (dk_deferred); --- 8450,8457 ---- } /* Remember where the template-id starts. */ ! if (cp_parser_uncommitted_to_tentative_parse_p (parser)) ! start_of_id = cp_lexer_token_position (parser->lexer, false); push_deferring_access_checks (dk_deferred); *************** cp_parser_template_id (cp_parser *parser *** 7928,7941 **** return template; } ! /* If we find the sequence `[:' after a template-name, it's probably a digraph-typo for `< ::'. Substitute the tokens and check if we can parse correctly the argument list. */ ! next_token = cp_lexer_peek_nth_token (parser->lexer, 1); next_token_2 = cp_lexer_peek_nth_token (parser->lexer, 2); ! if (next_token->type == CPP_OPEN_SQUARE && next_token->flags & DIGRAPH ! && next_token_2->type == CPP_COLON && !(next_token_2->flags & PREV_WHITE)) { cp_parser_parse_tentatively (parser); --- 8467,8480 ---- return template; } ! /* If we find the sequence `[:' after a template-name, it's probably a digraph-typo for `< ::'. Substitute the tokens and check if we can parse correctly the argument list. */ ! next_token = cp_lexer_peek_token (parser->lexer); next_token_2 = cp_lexer_peek_nth_token (parser->lexer, 2); ! if (next_token->type == CPP_OPEN_SQUARE && next_token->flags & DIGRAPH ! && next_token_2->type == CPP_COLON && !(next_token_2->flags & PREV_WHITE)) { cp_parser_parse_tentatively (parser); *************** cp_parser_template_id (cp_parser *parser *** 7952,7972 **** and return simply an error. Maybe this is not a template-id after all. */ next_token_2->type = CPP_COLON; ! cp_parser_error (parser, "expected `<'"); pop_deferring_access_checks (); return error_mark_node; } /* Otherwise, emit an error about the invalid digraph, but continue parsing because we got our argument list. */ ! pedwarn ("`<::' cannot begin a template-argument list"); ! inform ("`<:' is an alternate spelling for `['. Insert whitespace " ! "between `<' and `::'"); if (!flag_permissive) { static bool hint; if (!hint) { ! inform ("(if you use `-fpermissive' G++ will accept your code)"); hint = true; } } --- 8491,8511 ---- and return simply an error. Maybe this is not a template-id after all. */ next_token_2->type = CPP_COLON; ! cp_parser_error (parser, "expected %<<%>"); pop_deferring_access_checks (); return error_mark_node; } /* Otherwise, emit an error about the invalid digraph, but continue parsing because we got our argument list. */ ! pedwarn ("%<<::%> cannot begin a template-argument list"); ! inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace " ! "between %<<%> and %<::%>"); if (!flag_permissive) { static bool hint; if (!hint) { ! inform ("(if you use -fpermissive G++ will accept your code)"); hint = true; } } *************** cp_parser_template_id (cp_parser *parser *** 7988,8009 **** template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments); else if (DECL_CLASS_TEMPLATE_P (template) || DECL_TEMPLATE_TEMPLATE_PARM_P (template)) ! template_id ! = finish_template_type (template, arguments, ! cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)); else { /* If it's not a class-template or a template-template, it should be a function-template. */ ! my_friendly_assert ((DECL_FUNCTION_TEMPLATE_P (template) ! || TREE_CODE (template) == OVERLOAD ! || BASELINK_P (template)), ! 20010716); ! template_id = lookup_template_function (template, arguments); } ! /* Retrieve any deferred checks. Do not pop this access checks yet so the memory will not be reclaimed during token replacing below. */ access_check = get_deferred_access_checks (); --- 8527,8547 ---- template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments); else if (DECL_CLASS_TEMPLATE_P (template) || DECL_TEMPLATE_TEMPLATE_PARM_P (template)) ! template_id ! = finish_template_type (template, arguments, ! cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)); else { /* If it's not a class-template or a template-template, it should be a function-template. */ ! gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template) ! || TREE_CODE (template) == OVERLOAD ! || BASELINK_P (template))); ! template_id = lookup_template_function (template, arguments); } ! /* Retrieve any deferred checks. Do not pop this access checks yet so the memory will not be reclaimed during token replacing below. */ access_check = get_deferred_access_checks (); *************** cp_parser_template_id (cp_parser *parser *** 8014,8035 **** the effort required to do the parse, nor will we issue duplicate error messages about problems during instantiation of the template. */ ! if (start_of_id >= 0) { ! cp_token *token; ! ! /* Find the token that corresponds to the start of the ! template-id. */ ! token = cp_lexer_advance_token (parser->lexer, ! parser->lexer->first_token, ! start_of_id); ! /* Reset the contents of the START_OF_ID token. */ token->type = CPP_TEMPLATE_ID; token->value = build_tree_list (access_check, template_id); token->keyword = RID_MAX; /* Purge all subsequent tokens. */ ! cp_lexer_purge_tokens_after (parser->lexer, token); } pop_deferring_access_checks (); --- 8552,8575 ---- the effort required to do the parse, nor will we issue duplicate error messages about problems during instantiation of the template. */ ! if (start_of_id) { ! cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id); ! /* Reset the contents of the START_OF_ID token. */ token->type = CPP_TEMPLATE_ID; token->value = build_tree_list (access_check, template_id); token->keyword = RID_MAX; + /* Purge all subsequent tokens. */ ! cp_lexer_purge_tokens_after (parser->lexer, start_of_id); ! ! /* ??? Can we actually assume that, if template_id == ! error_mark_node, we will have issued a diagnostic to the ! user, as opposed to simply marking the tentative parse as ! failed? */ ! if (cp_parser_error_occurred (parser) && template_id != error_mark_node) ! error ("parse error in template argument list"); } pop_deferring_access_checks (); *************** cp_parser_template_id (cp_parser *parser *** 8040,8046 **** template-name: identifier ! The standard should actually say: template-name: --- 8580,8586 ---- template-name: identifier ! The standard should actually say: template-name: *************** cp_parser_template_id (cp_parser *parser *** 8055,8061 **** a.operator K() the conversion-function-id is "operator K", and K is a type-id. ! It is impossible to call a templated conversion-function-id with an explicit argument list, since the only allowed template parameter is the type to which it is converting. --- 8595,8601 ---- a.operator K() the conversion-function-id is "operator K", and K is a type-id. ! It is impossible to call a templated conversion-function-id with an explicit argument list, since the only allowed template parameter is the type to which it is converting. *************** cp_parser_template_id (cp_parser *parser *** 8074,8081 **** names are looked up inside uninstantiated templates. */ static tree ! cp_parser_template_name (cp_parser* parser, ! bool template_keyword_p, bool check_dependency_p, bool is_declaration, bool *is_identifier) --- 8614,8621 ---- names are looked up inside uninstantiated templates. */ static tree ! cp_parser_template_name (cp_parser* parser, ! bool template_keyword_p, bool check_dependency_p, bool is_declaration, bool *is_identifier) *************** cp_parser_template_name (cp_parser* pars *** 8103,8109 **** /* Look for the identifier. */ else identifier = cp_parser_identifier (parser); ! /* If we didn't find an identifier, we don't have a template-id. */ if (identifier == error_mark_node) return error_mark_node; --- 8643,8649 ---- /* Look for the identifier. */ else identifier = cp_parser_identifier (parser); ! /* If we didn't find an identifier, we don't have a template-id. */ if (identifier == error_mark_node) return error_mark_node; *************** cp_parser_template_name (cp_parser* pars *** 8126,8137 **** /* In a declaration, in a dependent context, we pretend that the "template" keyword was present in order to improve error recovery. For example, given: ! template void f(T::X); ! we want to treat "X" as a template-id. */ ! if (is_declaration ! && !template_keyword_p && parser->scope && TYPE_P (parser->scope) && check_dependency_p && dependent_type_p (parser->scope) --- 8666,8677 ---- /* In a declaration, in a dependent context, we pretend that the "template" keyword was present in order to improve error recovery. For example, given: ! template void f(T::X); ! we want to treat "X" as a template-id. */ ! if (is_declaration ! && !template_keyword_p && parser->scope && TYPE_P (parser->scope) && check_dependency_p && dependent_type_p (parser->scope) *************** cp_parser_template_name (cp_parser* pars *** 8139,8164 **** need the template keyword before their name. */ && !constructor_name_p (identifier, parser->scope)) { ! ptrdiff_t start; ! cp_token* token; /* Explain what went wrong. */ ! error ("non-template `%D' used as template", identifier); ! inform ("use `%T::template %D' to indicate that it is a template", parser->scope, identifier); ! /* If parsing tentatively, find the location of the "<" ! token. */ ! if (cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser)) ! { ! cp_parser_simulate_error (parser); ! token = cp_lexer_peek_token (parser->lexer); ! token = cp_lexer_prev_token (parser->lexer, token); ! start = cp_lexer_token_difference (parser->lexer, ! parser->lexer->first_token, ! token); ! } ! else ! start = -1; /* Parse the template arguments so that we can issue error messages about them. */ cp_lexer_consume_token (parser->lexer); --- 8679,8693 ---- need the template keyword before their name. */ && !constructor_name_p (identifier, parser->scope)) { ! cp_token_position start = 0; ! /* Explain what went wrong. */ ! error ("non-template %qD used as template", identifier); ! inform ("use %<%T::template %D%> to indicate that it is a template", parser->scope, identifier); ! /* If parsing tentatively, find the location of the "<" token. */ ! if (cp_parser_simulate_error (parser)) ! start = cp_lexer_token_position (parser->lexer, true); /* Parse the template arguments so that we can issue error messages about them. */ cp_lexer_consume_token (parser->lexer); *************** cp_parser_template_name (cp_parser* pars *** 8173,8185 **** template argument list. That will prevent duplicate error messages from being issued about the missing "template" keyword. */ ! if (start >= 0) ! { ! token = cp_lexer_advance_token (parser->lexer, ! parser->lexer->first_token, ! start); ! cp_lexer_purge_tokens_after (parser->lexer, token); ! } if (is_identifier) *is_identifier = true; return identifier; --- 8702,8709 ---- template argument list. That will prevent duplicate error messages from being issued about the missing "template" keyword. */ ! if (start) ! cp_lexer_purge_tokens_after (parser->lexer, start); if (is_identifier) *is_identifier = true; return identifier; *************** cp_parser_template_name (cp_parser* pars *** 8191,8214 **** (and must) do name-lookup normally. */ if (template_keyword_p && (!parser->scope ! || (TYPE_P (parser->scope) && dependent_type_p (parser->scope)))) return identifier; } /* Look up the name. */ decl = cp_parser_lookup_name (parser, identifier, ! /*is_type=*/false, /*is_template=*/false, /*is_namespace=*/false, ! check_dependency_p); decl = maybe_get_template_decl_from_type_decl (decl); /* If DECL is a template, then the name was a template-name. */ if (TREE_CODE (decl) == TEMPLATE_DECL) ; ! else { /* The standard does not explicitly indicate whether a name that names a set of overloaded declarations, some of which are templates, is a template-name. However, such a name should --- 8715,8741 ---- (and must) do name-lookup normally. */ if (template_keyword_p && (!parser->scope ! || (TYPE_P (parser->scope) && dependent_type_p (parser->scope)))) return identifier; } /* Look up the name. */ decl = cp_parser_lookup_name (parser, identifier, ! none_type, /*is_template=*/false, /*is_namespace=*/false, ! check_dependency_p, ! /*ambiguous_p=*/NULL); decl = maybe_get_template_decl_from_type_decl (decl); /* If DECL is a template, then the name was a template-name. */ if (TREE_CODE (decl) == TEMPLATE_DECL) ; ! else { + tree fn = NULL_TREE; + /* The standard does not explicitly indicate whether a name that names a set of overloaded declarations, some of which are templates, is a template-name. However, such a name should *************** cp_parser_template_name (cp_parser* pars *** 8216,8231 **** template-id for the overloaded templates. */ fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl; if (TREE_CODE (fns) == OVERLOAD) { ! tree fn; ! ! for (fn = fns; fn; fn = OVL_NEXT (fn)) ! if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL) ! break; ! } ! else ! { ! /* Otherwise, the name does not name a template. */ cp_parser_error (parser, "expected template-name"); return error_mark_node; } --- 8743,8755 ---- template-id for the overloaded templates. */ fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl; if (TREE_CODE (fns) == OVERLOAD) + for (fn = fns; fn; fn = OVL_NEXT (fn)) + if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL) + break; + + if (!fn) { ! /* The name does not name a template. */ cp_parser_error (parser, "expected template-name"); return error_mark_node; } *************** cp_parser_template_argument_list (cp_par *** 8270,8282 **** if (n_args) /* Consume the comma. */ cp_lexer_consume_token (parser->lexer); ! /* Parse the template-argument. */ argument = cp_parser_template_argument (parser); if (n_args == alloced) { alloced *= 2; ! if (arg_ary == fixed_args) { arg_ary = xmalloc (sizeof (tree) * alloced); --- 8794,8806 ---- if (n_args) /* Consume the comma. */ cp_lexer_consume_token (parser->lexer); ! /* Parse the template-argument. */ argument = cp_parser_template_argument (parser); if (n_args == alloced) { alloced *= 2; ! if (arg_ary == fixed_args) { arg_ary = xmalloc (sizeof (tree) * alloced); *************** cp_parser_template_argument_list (cp_par *** 8293,8299 **** while (n_args--) TREE_VEC_ELT (vec, n_args) = arg_ary[n_args]; ! if (arg_ary != fixed_args) free (arg_ary); parser->in_template_argument_list_p = saved_in_template_argument_list_p; --- 8817,8823 ---- while (n_args--) TREE_VEC_ELT (vec, n_args) = arg_ary[n_args]; ! if (arg_ary != fixed_args) free (arg_ary); parser->in_template_argument_list_p = saved_in_template_argument_list_p; *************** cp_parser_template_argument_list (cp_par *** 8310,8316 **** The representation is that of an assignment-expression, type-id, or id-expression -- except that the qualified id-expression is evaluated, so that the value returned is either a DECL or an ! OVERLOAD. Although the standard says "assignment-expression", it forbids throw-expressions or assignments in the template argument. --- 8834,8840 ---- The representation is that of an assignment-expression, type-id, or id-expression -- except that the qualified id-expression is evaluated, so that the value returned is either a DECL or an ! OVERLOAD. Although the standard says "assignment-expression", it forbids throw-expressions or assignments in the template argument. *************** cp_parser_template_argument (cp_parser* *** 8328,8346 **** tree qualifying_class; /* There's really no way to know what we're looking at, so we just ! try each alternative in order. [temp.arg] In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of ! the corresponding template-parameter. Therefore, we try a type-id first. */ cp_parser_parse_tentatively (parser); argument = cp_parser_type_id (parser); /* If there was no error parsing the type-id but the next token is a '>>', ! we probably found a typo for '> >'. But there are type-id which are also valid expressions. For instance: struct X { int operator >> (int); }; --- 8852,8870 ---- tree qualifying_class; /* There's really no way to know what we're looking at, so we just ! try each alternative in order. [temp.arg] In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of ! the corresponding template-parameter. Therefore, we try a type-id first. */ cp_parser_parse_tentatively (parser); argument = cp_parser_type_id (parser); /* If there was no error parsing the type-id but the next token is a '>>', ! we probably found a typo for '> >'. But there are type-id which are also valid expressions. For instance: struct X { int operator >> (int); }; *************** cp_parser_template_argument (cp_parser* *** 8371,8377 **** /* We're still not sure what the argument will be. */ cp_parser_parse_tentatively (parser); /* Try a template. */ ! argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, &template_p, --- 8895,8901 ---- /* We're still not sure what the argument will be. */ cp_parser_parse_tentatively (parser); /* Try a template. */ ! argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, &template_p, *************** cp_parser_template_argument (cp_parser* *** 8388,8397 **** at this point in that case. */ if (TREE_CODE (argument) != TYPE_DECL) argument = cp_parser_lookup_name (parser, argument, ! /*is_type=*/false, /*is_template=*/template_p, /*is_namespace=*/false, ! /*check_dependency=*/true); if (TREE_CODE (argument) != TEMPLATE_DECL && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) cp_parser_error (parser, "expected template-name"); --- 8912,8922 ---- at this point in that case. */ if (TREE_CODE (argument) != TYPE_DECL) argument = cp_parser_lookup_name (parser, argument, ! none_type, /*is_template=*/template_p, /*is_namespace=*/false, ! /*check_dependency=*/true, ! /*ambiguous_p=*/NULL); if (TREE_CODE (argument) != TEMPLATE_DECL && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) cp_parser_error (parser, "expected template-name"); *************** cp_parser_template_argument (cp_parser* *** 8416,8421 **** --- 8941,8947 ---- { cp_parser_parse_tentatively (parser); argument = cp_parser_primary_expression (parser, + /*cast_p=*/false, &idk, &qualifying_class); if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX *************** cp_parser_template_argument (cp_parser* *** 8424,8429 **** --- 8950,8956 ---- if (cp_parser_parse_definitely (parser)) return argument; } + /* If the next token is "&", the argument must be the address of an object or function with external linkage. */ address_p = cp_lexer_next_token_is (parser->lexer, CPP_AND); *************** cp_parser_template_argument (cp_parser* *** 8439,8444 **** --- 8966,8972 ---- { cp_parser_parse_tentatively (parser); argument = cp_parser_primary_expression (parser, + /*cast_p=*/false, &idk, &qualifying_class); if (cp_parser_error_occurred (parser) *************** cp_parser_template_argument (cp_parser* *** 8446,8451 **** --- 8974,8985 ---- cp_parser_abort_tentative_parse (parser); else { + if (TREE_CODE (argument) == INDIRECT_REF) + { + gcc_assert (REFERENCE_REF_P (argument)); + argument = TREE_OPERAND (argument, 0); + } + if (qualifying_class) argument = finish_qualified_id_expr (qualifying_class, argument, *************** cp_parser_template_argument (cp_parser* *** 8465,8474 **** later. */ ; else if (address_p ! && (TREE_CODE (argument) == OFFSET_REF || TREE_CODE (argument) == SCOPE_REF)) /* A pointer-to-member. */ ; else cp_parser_simulate_error (parser); --- 8999,9010 ---- later. */ ; else if (address_p ! && (TREE_CODE (argument) == OFFSET_REF || TREE_CODE (argument) == SCOPE_REF)) /* A pointer-to-member. */ ; + else if (TREE_CODE (argument) == TEMPLATE_PARM_INDEX) + ; else cp_parser_simulate_error (parser); *************** cp_parser_template_argument (cp_parser* *** 8487,8499 **** cp_parser_error (parser, "invalid non-type template argument"); return error_mark_node; } /* If the argument wasn't successfully parsed as a type-id followed ! by '>>', the argument can only be a constant expression now. Otherwise, we try parsing the constant-expression tentatively, because the argument could really be a type-id. */ if (maybe_type_id) cp_parser_parse_tentatively (parser); ! argument = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, /*non_constant_p=*/NULL); argument = fold_non_dependent_expr (argument); --- 9023,9036 ---- cp_parser_error (parser, "invalid non-type template argument"); return error_mark_node; } + /* If the argument wasn't successfully parsed as a type-id followed ! by '>>', the argument can only be a constant expression now. Otherwise, we try parsing the constant-expression tentatively, because the argument could really be a type-id. */ if (maybe_type_id) cp_parser_parse_tentatively (parser); ! argument = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, /*non_constant_p=*/NULL); argument = fold_non_dependent_expr (argument); *************** cp_parser_template_argument (cp_parser* *** 8505,8511 **** return argument; /* We did our best to parse the argument as a non type-id, but that was the only alternative that matched (albeit with a '>' after ! it). We can assume it's just a typo from the user, and a diagnostic will then be issued. */ return cp_parser_type_id (parser); } --- 9042,9048 ---- return argument; /* We did our best to parse the argument as a non type-id, but that was the only alternative that matched (albeit with a '>' after ! it). We can assume it's just a typo from the user, and a diagnostic will then be issued. */ return cp_parser_type_id (parser); } *************** cp_parser_template_argument (cp_parser* *** 8513,8553 **** /* Parse an explicit-instantiation. explicit-instantiation: ! template declaration Although the standard says `declaration', what it really means is: explicit-instantiation: ! template decl-specifier-seq [opt] declarator [opt] ; Things like `template int S::i = 5, int S::j;' are not supposed to be allowed. A defect report has been filed about this ! issue. GNU Extension: ! explicit-instantiation: ! storage-class-specifier template decl-specifier-seq [opt] declarator [opt] ; ! function-specifier template decl-specifier-seq [opt] declarator [opt] ; */ static void cp_parser_explicit_instantiation (cp_parser* parser) { int declares_class_or_enum; ! tree decl_specifiers; ! tree attributes; tree extension_specifier = NULL_TREE; /* Look for an (optional) storage-class-specifier or function-specifier. */ if (cp_parser_allow_gnu_extensions_p (parser)) { ! extension_specifier = cp_parser_storage_class_specifier_opt (parser); if (!extension_specifier) ! extension_specifier = cp_parser_function_specifier_opt (parser); } /* Look for the `template' keyword. */ --- 9050,9091 ---- /* Parse an explicit-instantiation. explicit-instantiation: ! template declaration Although the standard says `declaration', what it really means is: explicit-instantiation: ! template decl-specifier-seq [opt] declarator [opt] ; Things like `template int S::i = 5, int S::j;' are not supposed to be allowed. A defect report has been filed about this ! issue. GNU Extension: ! explicit-instantiation: ! storage-class-specifier template decl-specifier-seq [opt] declarator [opt] ; ! function-specifier template decl-specifier-seq [opt] declarator [opt] ; */ static void cp_parser_explicit_instantiation (cp_parser* parser) { int declares_class_or_enum; ! cp_decl_specifier_seq decl_specifiers; tree extension_specifier = NULL_TREE; /* Look for an (optional) storage-class-specifier or function-specifier. */ if (cp_parser_allow_gnu_extensions_p (parser)) { ! extension_specifier = cp_parser_storage_class_specifier_opt (parser); if (!extension_specifier) ! extension_specifier ! = cp_parser_function_specifier_opt (parser, ! /*decl_specs=*/NULL); } /* Look for the `template' keyword. */ *************** cp_parser_explicit_instantiation (cp_par *** 8559,8569 **** control while processing explicit instantiation directives. */ push_deferring_access_checks (dk_no_check); /* Parse a decl-specifier-seq. */ ! decl_specifiers ! = cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_OPTIONAL, ! &attributes, ! &declares_class_or_enum); /* If there was exactly one decl-specifier, and it declared a class, and there's no declarator, then we have an explicit type instantiation. */ --- 9097,9106 ---- control while processing explicit instantiation directives. */ push_deferring_access_checks (dk_no_check); /* Parse a decl-specifier-seq. */ ! cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_OPTIONAL, ! &decl_specifiers, ! &declares_class_or_enum); /* If there was exactly one decl-specifier, and it declared a class, and there's no declarator, then we have an explicit type instantiation. */ *************** cp_parser_explicit_instantiation (cp_par *** 8571,8577 **** { tree type; ! type = check_tag_decl (decl_specifiers); /* Turn access control back on for names used during template instantiation. */ pop_deferring_access_checks (); --- 9108,9114 ---- { tree type; ! type = check_tag_decl (&decl_specifiers); /* Turn access control back on for names used during template instantiation. */ pop_deferring_access_checks (); *************** cp_parser_explicit_instantiation (cp_par *** 8580,8599 **** } else { ! tree declarator; tree decl; /* Parse the declarator. */ ! declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, /*member_p=*/false); ! cp_parser_check_for_definition_in_return_type (declarator, ! declares_class_or_enum); ! if (declarator != error_mark_node) { ! decl = grokdeclarator (declarator, decl_specifiers, NORMAL, 0, NULL); /* Turn access control back on for names used during template instantiation. */ --- 9117,9137 ---- } else { ! cp_declarator *declarator; tree decl; /* Parse the declarator. */ ! declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, /*member_p=*/false); ! if (declares_class_or_enum & 2) ! cp_parser_check_for_definition_in_return_type (declarator, ! decl_specifiers.type); ! if (declarator != cp_error_declarator) { ! decl = grokdeclarator (declarator, &decl_specifiers, NORMAL, 0, NULL); /* Turn access control back on for names used during template instantiation. */ *************** cp_parser_explicit_instantiation (cp_par *** 8617,8629 **** /* Parse an explicit-specialization. explicit-specialization: ! template < > declaration Although the standard says `declaration', what it really means is: explicit-specialization: template <> decl-specifier [opt] init-declarator [opt] ; ! template <> function-definition template <> explicit-specialization template <> template-declaration */ --- 9155,9167 ---- /* Parse an explicit-specialization. explicit-specialization: ! template < > declaration Although the standard says `declaration', what it really means is: explicit-specialization: template <> decl-specifier [opt] init-declarator [opt] ; ! template <> function-definition template <> explicit-specialization template <> template-declaration */ *************** cp_parser_explicit_specialization (cp_pa *** 8654,8660 **** } else /* Parse the dependent declaration. */ ! cp_parser_single_declaration (parser, /*member_p=*/false, /*friend_p=*/NULL); --- 9192,9198 ---- } else /* Parse the dependent declaration. */ ! cp_parser_single_declaration (parser, /*member_p=*/false, /*friend_p=*/NULL); *************** cp_parser_explicit_specialization (cp_pa *** 8678,8692 **** type-specifier: __complex__ ! Returns a representation of the type-specifier. If the ! type-specifier is a keyword (like `int' or `const', or ! `__complex__') then the corresponding IDENTIFIER_NODE is returned. ! For a class-specifier, enum-specifier, or elaborated-type-specifier ! a TREE_TYPE is returned; otherwise, a TYPE_DECL is returned. ! If IS_FRIEND is TRUE then this type-specifier is being declared a ! `friend'. If IS_DECLARATION is TRUE, then this type-specifier is ! appearing in a decl-specifier-seq. If DECLARES_CLASS_OR_ENUM is non-NULL, and the type-specifier is a class-specifier, enum-specifier, or elaborated-type-specifier, then --- 9216,9229 ---- type-specifier: __complex__ ! Returns a representation of the type-specifier. For a ! class-specifier, enum-specifier, or elaborated-type-specifier, a ! TREE_TYPE is returned; otherwise, a TYPE_DECL is returned. ! The parser flags FLAGS is used to control type-specifier parsing. ! ! If IS_DECLARATION is TRUE, then this type-specifier is appearing ! in a decl-specifier-seq. If DECLARES_CLASS_OR_ENUM is non-NULL, and the type-specifier is a class-specifier, enum-specifier, or elaborated-type-specifier, then *************** cp_parser_explicit_specialization (cp_pa *** 8699,8707 **** is set to FALSE. */ static tree ! cp_parser_type_specifier (cp_parser* parser, ! cp_parser_flags flags, ! bool is_friend, bool is_declaration, int* declares_class_or_enum, bool* is_cv_qualifier) --- 9236,9244 ---- is set to FALSE. */ static tree ! cp_parser_type_specifier (cp_parser* parser, ! cp_parser_flags flags, ! cp_decl_specifier_seq *decl_specs, bool is_declaration, int* declares_class_or_enum, bool* is_cv_qualifier) *************** cp_parser_type_specifier (cp_parser* par *** 8709,8714 **** --- 9246,9252 ---- tree type_spec = NULL_TREE; cp_token *token; enum rid keyword; + cp_decl_spec ds = ds_last; /* Assume this type-specifier does not declare a new type. */ if (declares_class_or_enum) *************** cp_parser_type_specifier (cp_parser* par *** 8724,8790 **** keyword = token->keyword; switch (keyword) { /* Any of these indicate either a class-specifier, or an elaborated-type-specifier. */ case RID_CLASS: case RID_STRUCT: case RID_UNION: - case RID_ENUM: /* Parse tentatively so that we can back up if we don't find a ! class-specifier or enum-specifier. */ cp_parser_parse_tentatively (parser); ! /* Look for the class-specifier or enum-specifier. */ ! if (keyword == RID_ENUM) ! type_spec = cp_parser_enum_specifier (parser); ! else ! type_spec = cp_parser_class_specifier (parser); ! /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) { if (declares_class_or_enum) *declares_class_or_enum = 2; return type_spec; } /* Fall through. */ case RID_TYPENAME: /* Look for an elaborated-type-specifier. */ ! type_spec = cp_parser_elaborated_type_specifier (parser, ! is_friend, ! is_declaration); ! /* We're declaring a class or enum -- unless we're using ! `typename'. */ ! if (declares_class_or_enum && keyword != RID_TYPENAME) ! *declares_class_or_enum = 1; return type_spec; case RID_CONST: case RID_VOLATILE: ! case RID_RESTRICT: ! type_spec = cp_parser_cv_qualifier_opt (parser); ! /* Even though we call a routine that looks for an optional ! qualifier, we know that there should be one. */ ! my_friendly_assert (type_spec != NULL, 20000328); ! /* This type-specifier was a cv-qualified. */ if (is_cv_qualifier) *is_cv_qualifier = true; ! return type_spec; case RID_COMPLEX: /* The `__complex__' keyword is a GNU extension. */ ! return cp_lexer_consume_token (parser->lexer)->value; default: break; } /* If we do not already have a type-specifier, assume we are looking at a simple-type-specifier. */ ! type_spec = cp_parser_simple_type_specifier (parser, flags, ! /*identifier_p=*/true); /* If we didn't find a type-specifier, and a type-specifier was not optional in this context, issue an error message. */ --- 9262,9380 ---- keyword = token->keyword; switch (keyword) { + case RID_ENUM: + /* 'enum' [identifier] '{' introduces an enum-specifier; + 'enum' introduces an elaborated-type-specifier. */ + if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE + || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME + && cp_lexer_peek_nth_token (parser->lexer, 3)->type + == CPP_OPEN_BRACE)) + { + if (parser->num_template_parameter_lists) + { + error ("template declaration of %qs", "enum"); + cp_parser_skip_to_end_of_block_or_statement (parser); + type_spec = error_mark_node; + } + else + type_spec = cp_parser_enum_specifier (parser); + + if (declares_class_or_enum) + *declares_class_or_enum = 2; + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, + type_spec, + /*user_defined_p=*/true); + return type_spec; + } + else + goto elaborated_type_specifier; + /* Any of these indicate either a class-specifier, or an elaborated-type-specifier. */ case RID_CLASS: case RID_STRUCT: case RID_UNION: /* Parse tentatively so that we can back up if we don't find a ! class-specifier. */ cp_parser_parse_tentatively (parser); ! /* Look for the class-specifier. */ ! type_spec = cp_parser_class_specifier (parser); /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) { if (declares_class_or_enum) *declares_class_or_enum = 2; + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, + type_spec, + /*user_defined_p=*/true); return type_spec; } /* Fall through. */ + elaborated_type_specifier: + /* We're declaring (not defining) a class or enum. */ + if (declares_class_or_enum) + *declares_class_or_enum = 1; + /* Fall through. */ case RID_TYPENAME: /* Look for an elaborated-type-specifier. */ ! type_spec ! = (cp_parser_elaborated_type_specifier ! (parser, ! decl_specs && decl_specs->specs[(int) ds_friend], ! is_declaration)); ! if (decl_specs) ! cp_parser_set_decl_spec_type (decl_specs, ! type_spec, ! /*user_defined_p=*/true); return type_spec; case RID_CONST: + ds = ds_const; + if (is_cv_qualifier) + *is_cv_qualifier = true; + break; + case RID_VOLATILE: ! ds = ds_volatile; if (is_cv_qualifier) *is_cv_qualifier = true; + break; ! case RID_RESTRICT: ! ds = ds_restrict; ! if (is_cv_qualifier) ! *is_cv_qualifier = true; ! break; case RID_COMPLEX: /* The `__complex__' keyword is a GNU extension. */ ! ds = ds_complex; ! break; default: break; } + /* Handle simple keywords. */ + if (ds != ds_last) + { + if (decl_specs) + { + ++decl_specs->specs[(int)ds]; + decl_specs->any_specifiers_p = true; + } + return cp_lexer_consume_token (parser->lexer)->value; + } + /* If we do not already have a type-specifier, assume we are looking at a simple-type-specifier. */ ! type_spec = cp_parser_simple_type_specifier (parser, ! decl_specs, ! flags); /* If we didn't find a type-specifier, and a type-specifier was not optional in this context, issue an error message. */ *************** cp_parser_type_specifier (cp_parser* par *** 8812,8818 **** unsigned float double ! void GNU Extension: --- 9402,9408 ---- unsigned float double ! void GNU Extension: *************** cp_parser_type_specifier (cp_parser* par *** 8820,8833 **** __typeof__ unary-expression __typeof__ ( type-id ) ! For the various keywords, the value returned is simply the ! TREE_IDENTIFIER representing the keyword if IDENTIFIER_P is true. ! For the first two productions, and if IDENTIFIER_P is false, the ! value returned is the indicated TYPE_DECL. */ static tree ! cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags, ! bool identifier_p) { tree type = NULL_TREE; cp_token *token; --- 9410,9422 ---- __typeof__ unary-expression __typeof__ ( type-id ) ! Returns the indicated TYPE_DECL. If DECL_SPECS is not NULL, it is ! appropriately updated. */ static tree ! cp_parser_simple_type_specifier (cp_parser* parser, ! cp_decl_specifier_seq *decl_specs, ! cp_parser_flags flags) { tree type = NULL_TREE; cp_token *token; *************** cp_parser_simple_type_specifier (cp_pars *** 8839,8844 **** --- 9428,9435 ---- switch (token->keyword) { case RID_CHAR: + if (decl_specs) + decl_specs->explicit_char_p = true; type = char_type_node; break; case RID_WCHAR: *************** cp_parser_simple_type_specifier (cp_pars *** 8848,8865 **** --- 9439,9466 ---- type = boolean_type_node; break; case RID_SHORT: + if (decl_specs) + ++decl_specs->specs[(int) ds_short]; type = short_integer_type_node; break; case RID_INT: + if (decl_specs) + decl_specs->explicit_int_p = true; type = integer_type_node; break; case RID_LONG: + if (decl_specs) + ++decl_specs->specs[(int) ds_long]; type = long_integer_type_node; break; case RID_SIGNED: + if (decl_specs) + ++decl_specs->specs[(int) ds_signed]; type = integer_type_node; break; case RID_UNSIGNED: + if (decl_specs) + ++decl_specs->specs[(int) ds_unsigned]; type = unsigned_type_node; break; case RID_FLOAT: *************** cp_parser_simple_type_specifier (cp_pars *** 8873,8891 **** break; case RID_TYPEOF: ! { ! tree operand; ! /* Consume the `typeof' token. */ ! cp_lexer_consume_token (parser->lexer); ! /* Parse the operand to `typeof'. */ ! operand = cp_parser_sizeof_operand (parser, RID_TYPEOF); ! /* If it is not already a TYPE, take its type. */ ! if (!TYPE_P (operand)) ! operand = finish_typeof (operand); ! return operand; ! } default: break; --- 9474,9492 ---- break; case RID_TYPEOF: ! /* Consume the `typeof' token. */ ! cp_lexer_consume_token (parser->lexer); ! /* Parse the operand to `typeof'. */ ! type = cp_parser_sizeof_operand (parser, RID_TYPEOF); ! /* If it is not already a TYPE, take its type. */ ! if (!TYPE_P (type)) ! type = finish_typeof (type); ! if (decl_specs) ! cp_parser_set_decl_spec_type (decl_specs, type, ! /*user_defined_p=*/true); ! return type; default: break; *************** cp_parser_simple_type_specifier (cp_pars *** 8896,8901 **** --- 9497,9514 ---- { tree id; + /* Record the type. */ + if (decl_specs + && (token->keyword != RID_SIGNED + && token->keyword != RID_UNSIGNED + && token->keyword != RID_SHORT + && token->keyword != RID_LONG)) + cp_parser_set_decl_spec_type (decl_specs, + type, + /*user_defined=*/false); + if (decl_specs) + decl_specs->any_specifiers_p = true; + /* Consume the token. */ id = cp_lexer_consume_token (parser->lexer)->value; *************** cp_parser_simple_type_specifier (cp_pars *** 8904,8914 **** that the type was a template. */ cp_parser_check_for_invalid_template_id (parser, type); ! return identifier_p ? id : TYPE_NAME (type); } /* The type-specifier must be a user-defined type. */ ! if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES)) { bool qualified_p; bool global_p; --- 9517,9527 ---- that the type was a template. */ cp_parser_check_for_invalid_template_id (parser, type); ! return TYPE_NAME (type); } /* The type-specifier must be a user-defined type. */ ! if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES)) { bool qualified_p; bool global_p; *************** cp_parser_simple_type_specifier (cp_pars *** 8933,8943 **** != NULL_TREE); /* If we have seen a nested-name-specifier, and the next token is `template', then we are using the template-id production. */ ! if (parser->scope && cp_parser_optional_template_keyword (parser)) { /* Look for the template-id. */ ! type = cp_parser_template_id (parser, /*template_keyword_p=*/true, /*check_dependency_p=*/true, /*is_declaration=*/false); --- 9546,9556 ---- != NULL_TREE); /* If we have seen a nested-name-specifier, and the next token is `template', then we are using the template-id production. */ ! if (parser->scope && cp_parser_optional_template_keyword (parser)) { /* Look for the template-id. */ ! type = cp_parser_template_id (parser, /*template_keyword_p=*/true, /*check_dependency_p=*/true, /*is_declaration=*/false); *************** cp_parser_simple_type_specifier (cp_pars *** 8953,8968 **** else type = cp_parser_type_name (parser); /* Keep track of all name-lookups performed in class scopes. */ ! if (type && !global_p && !qualified_p ! && TREE_CODE (type) == TYPE_DECL && TREE_CODE (DECL_NAME (type)) == IDENTIFIER_NODE) maybe_note_name_used_in_class (DECL_NAME (type), type); /* If it didn't work out, we don't have a TYPE. */ ! if ((flags & CP_PARSER_FLAGS_OPTIONAL) && !cp_parser_parse_definitely (parser)) type = NULL_TREE; } /* If we didn't get a type-name, issue an error message. */ --- 9566,9584 ---- else type = cp_parser_type_name (parser); /* Keep track of all name-lookups performed in class scopes. */ ! if (type && !global_p && !qualified_p ! && TREE_CODE (type) == TYPE_DECL && TREE_CODE (DECL_NAME (type)) == IDENTIFIER_NODE) maybe_note_name_used_in_class (DECL_NAME (type), type); /* If it didn't work out, we don't have a TYPE. */ ! if ((flags & CP_PARSER_FLAGS_OPTIONAL) && !cp_parser_parse_definitely (parser)) type = NULL_TREE; + if (type && decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + /*user_defined=*/true); } /* If we didn't get a type-name, issue an error message. */ *************** cp_parser_simple_type_specifier (cp_pars *** 8986,9000 **** type-name: class-name enum-name ! typedef-name enum-name: identifier typedef-name: ! identifier ! Returns a TYPE_DECL for the the type. */ static tree cp_parser_type_name (cp_parser* parser) --- 9602,9616 ---- type-name: class-name enum-name ! typedef-name enum-name: identifier typedef-name: ! identifier ! Returns a TYPE_DECL for the type. */ static tree cp_parser_type_name (cp_parser* parser) *************** cp_parser_type_name (cp_parser* parser) *** 9005,9014 **** /* We can't know yet whether it is a class-name or not. */ cp_parser_parse_tentatively (parser); /* Try a class-name. */ ! type_decl = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! /*type_p=*/false, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/false); --- 9621,9630 ---- /* We can't know yet whether it is a class-name or not. */ cp_parser_parse_tentatively (parser); /* Try a class-name. */ ! type_decl = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! none_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/false); *************** cp_parser_type_name (cp_parser* parser) *** 9019,9032 **** identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) return error_mark_node; ! /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier); /* Issue an error if we did not find a type-name. */ if (TREE_CODE (type_decl) != TYPE_DECL) { if (!cp_parser_simulate_error (parser)) ! cp_parser_name_lookup_error (parser, identifier, type_decl, "is not a type"); type_decl = error_mark_node; } --- 9635,9648 ---- identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) return error_mark_node; ! /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier); /* Issue an error if we did not find a type-name. */ if (TREE_CODE (type_decl) != TYPE_DECL) { if (!cp_parser_simulate_error (parser)) ! cp_parser_name_lookup_error (parser, identifier, type_decl, "is not a type"); type_decl = error_mark_node; } *************** cp_parser_type_name (cp_parser* parser) *** 9038,9044 **** && !parser->scope) maybe_note_name_used_in_class (identifier, type_decl); } ! return type_decl; } --- 9654,9660 ---- && !parser->scope) maybe_note_name_used_in_class (identifier, type_decl); } ! return type_decl; } *************** cp_parser_type_name (cp_parser* parser) *** 9051,9064 **** class-key :: [opt] nested-name-specifier [opt] template [opt] template-id enum :: [opt] nested-name-specifier [opt] identifier typename :: [opt] nested-name-specifier identifier ! typename :: [opt] nested-name-specifier template [opt] ! template-id GNU extension: elaborated-type-specifier: class-key attributes :: [opt] nested-name-specifier [opt] identifier ! class-key attributes :: [opt] nested-name-specifier [opt] template [opt] template-id enum attributes :: [opt] nested-name-specifier [opt] identifier --- 9667,9680 ---- class-key :: [opt] nested-name-specifier [opt] template [opt] template-id enum :: [opt] nested-name-specifier [opt] identifier typename :: [opt] nested-name-specifier identifier ! typename :: [opt] nested-name-specifier template [opt] ! template-id GNU extension: elaborated-type-specifier: class-key attributes :: [opt] nested-name-specifier [opt] identifier ! class-key attributes :: [opt] nested-name-specifier [opt] template [opt] template-id enum attributes :: [opt] nested-name-specifier [opt] identifier *************** cp_parser_type_name (cp_parser* parser) *** 9070,9077 **** Returns the TYPE specified. */ static tree ! cp_parser_elaborated_type_specifier (cp_parser* parser, ! bool is_friend, bool is_declaration) { enum tag_types tag_type; --- 9686,9693 ---- Returns the TYPE specified. */ static tree ! cp_parser_elaborated_type_specifier (cp_parser* parser, ! bool is_friend, bool is_declaration) { enum tag_types tag_type; *************** cp_parser_elaborated_type_specifier (cp_ *** 9099,9105 **** tag_type = typename_type; /* The `typename' keyword is only allowed in templates. */ if (!processing_template_decl) ! pedwarn ("using `typename' outside of template"); } /* Otherwise it must be a class-key. */ else --- 9715,9721 ---- tag_type = typename_type; /* The `typename' keyword is only allowed in templates. */ if (!processing_template_decl) ! pedwarn ("using % outside of template"); } /* Otherwise it must be a class-key. */ else *************** cp_parser_elaborated_type_specifier (cp_ *** 9112,9118 **** } /* Look for the `::' operator. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the nested-name-specifier. */ if (tag_type == typename_type) --- 9728,9734 ---- } /* Look for the `::' operator. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the nested-name-specifier. */ if (tag_type == typename_type) *************** cp_parser_elaborated_type_specifier (cp_ *** 9121,9127 **** /*typename_keyword_p=*/true, /*check_dependency_p=*/true, /*type_p=*/true, ! is_declaration) == error_mark_node) return error_mark_node; } --- 9737,9743 ---- /*typename_keyword_p=*/true, /*check_dependency_p=*/true, /*type_p=*/true, ! is_declaration) == error_mark_node) return error_mark_node; } *************** cp_parser_elaborated_type_specifier (cp_ *** 9160,9167 **** else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && tag_type == typename_type) type = make_typename_type (parser->scope, decl, /*complain=*/1); ! else type = TREE_TYPE (decl); } --- 9776,9784 ---- else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && tag_type == typename_type) type = make_typename_type (parser->scope, decl, + typename_type, /*complain=*/1); ! else type = TREE_TYPE (decl); } *************** cp_parser_elaborated_type_specifier (cp_ *** 9177,9198 **** } /* For a `typename', we needn't call xref_tag. */ ! if (tag_type == typename_type) ! return make_typename_type (parser->scope, identifier, ! /*complain=*/1); /* Look up a qualified name in the usual way. */ if (parser->scope) { tree decl; ! /* In an elaborated-type-specifier, names are assumed to name ! types, so we set IS_TYPE to TRUE when calling ! cp_parser_lookup_name. */ ! decl = cp_parser_lookup_name (parser, identifier, ! /*is_type=*/true, /*is_template=*/false, /*is_namespace=*/false, ! /*check_dependency=*/true); /* If we are parsing friend declaration, DECL may be a TEMPLATE_DECL tree node here. However, we need to check --- 9794,9814 ---- } /* For a `typename', we needn't call xref_tag. */ ! if (tag_type == typename_type ! && TREE_CODE (parser->scope) != NAMESPACE_DECL) ! return cp_parser_make_typename_type (parser, parser->scope, ! identifier); /* Look up a qualified name in the usual way. */ if (parser->scope) { tree decl; ! decl = cp_parser_lookup_name (parser, identifier, ! tag_type, /*is_template=*/false, /*is_namespace=*/false, ! /*check_dependency=*/true, ! /*ambiguous_p=*/NULL); /* If we are parsing friend declaration, DECL may be a TEMPLATE_DECL tree node here. However, we need to check *************** cp_parser_elaborated_type_specifier (cp_ *** 9215,9239 **** processing_template_decl does not work here since it is always 1 for the above two cases. */ ! decl = (cp_parser_maybe_treat_template_as_class (decl, /*tag_name_p=*/is_friend && parser->num_template_parameter_lists)); if (TREE_CODE (decl) != TYPE_DECL) { ! error ("expected type-name"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE) ! check_elaborated_type_specifier (tag_type, decl, (parser->num_template_parameter_lists || DECL_SELF_REFERENCE_P (decl))); type = TREE_TYPE (decl); } ! else { /* An elaborated-type-specifier sometimes introduces a new type and sometimes names an existing type. Normally, the rule is that it --- 9831,9857 ---- processing_template_decl does not work here since it is always 1 for the above two cases. */ ! decl = (cp_parser_maybe_treat_template_as_class (decl, /*tag_name_p=*/is_friend && parser->num_template_parameter_lists)); if (TREE_CODE (decl) != TYPE_DECL) { ! cp_parser_diagnose_invalid_type_name (parser, ! parser->scope, ! identifier); return error_mark_node; } if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE) ! check_elaborated_type_specifier (tag_type, decl, (parser->num_template_parameter_lists || DECL_SELF_REFERENCE_P (decl))); type = TREE_TYPE (decl); } ! else { /* An elaborated-type-specifier sometimes introduces a new type and sometimes names an existing type. Normally, the rule is that it *************** cp_parser_elaborated_type_specifier (cp_ *** 9245,9251 **** the `struct S' in the body of `f' is the same `struct S' as in the global scope; the existing definition is used. However, if ! there were no global declaration, this would introduce a new local class named `S'. An exception to this rule applies to the following code: --- 9863,9869 ---- the `struct S' in the body of `f' is the same `struct S' as in the global scope; the existing definition is used. However, if ! there were no global declaration, this would introduce a new local class named `S'. An exception to this rule applies to the following code: *************** cp_parser_elaborated_type_specifier (cp_ *** 9258,9264 **** This exception only applies if the elaborated-type-specifier forms the complete declaration: ! [class.name] A declaration consisting solely of `class-key identifier ;' is either a redeclaration of the name in the current scope or a --- 9876,9882 ---- This exception only applies if the elaborated-type-specifier forms the complete declaration: ! [class.name] A declaration consisting solely of `class-key identifier ;' is either a redeclaration of the name in the current scope or a *************** cp_parser_elaborated_type_specifier (cp_ *** 9272,9292 **** struct S { friend struct T; }; ! `T' is not a new type in the scope of `S'. Also, `new struct S' or `sizeof (struct S)' never results in the definition of a new type; a new type can only be declared in a declaration context. */ /* Warn about attributes. They are ignored. */ if (attributes) warning ("type attributes are honored only at type definition"); ! type = xref_tag (tag_type, identifier, ! (is_friend ! || !is_declaration ! || cp_lexer_next_token_is_not (parser->lexer, ! CPP_SEMICOLON)), parser->num_template_parameter_lists); } } --- 9890,9918 ---- struct S { friend struct T; }; ! `T' is not a new type in the scope of `S'. Also, `new struct S' or `sizeof (struct S)' never results in the definition of a new type; a new type can only be declared in a declaration context. */ + tag_scope ts; + if (is_friend) + /* Friends have special name lookup rules. */ + ts = ts_within_enclosing_non_class; + else if (is_declaration + && cp_lexer_next_token_is (parser->lexer, + CPP_SEMICOLON)) + /* This is a `class-key identifier ;' */ + ts = ts_current; + else + ts = ts_global; + /* Warn about attributes. They are ignored. */ if (attributes) warning ("type attributes are honored only at type definition"); ! type = xref_tag (tag_type, identifier, ts, parser->num_template_parameter_lists); } } *************** cp_parser_elaborated_type_specifier (cp_ *** 9305,9351 **** enum-specifier: enum identifier [opt] { enumerator-list [opt] } Returns an ENUM_TYPE representing the enumeration. */ static tree cp_parser_enum_specifier (cp_parser* parser) { ! cp_token *token; ! tree identifier = NULL_TREE; tree type; ! /* Look for the `enum' keyword. */ ! if (!cp_parser_require_keyword (parser, RID_ENUM, "`enum'")) ! return error_mark_node; ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* See if it is an identifier. */ ! if (token->type == CPP_NAME) identifier = cp_parser_identifier (parser); ! ! /* Look for the `{'. */ ! if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) ! return error_mark_node; ! ! /* At this point, we're going ahead with the enum-specifier, even ! if some other problem occurs. */ ! cp_parser_commit_to_tentative_parse (parser); /* Issue an error message if type-definitions are forbidden here. */ cp_parser_check_type_definition (parser); ! /* Create the new type. */ ! type = start_enum (identifier ? identifier : make_anon_name ()); ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* If it's not a `}', then there are some enumerators. */ ! if (token->type != CPP_CLOSE_BRACE) cp_parser_enumerator_list (parser, type); ! /* Look for the `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); /* Finish up the enumeration. */ finish_enum (type); --- 9931,9986 ---- enum-specifier: enum identifier [opt] { enumerator-list [opt] } + GNU Extensions: + enum identifier [opt] { enumerator-list [opt] } attributes + Returns an ENUM_TYPE representing the enumeration. */ static tree cp_parser_enum_specifier (cp_parser* parser) { ! tree identifier; tree type; ! /* Caller guarantees that the current token is 'enum', an identifier ! possibly follows, and the token after that is an opening brace. ! If we don't have an identifier, fabricate an anonymous name for ! the enumeration being defined. */ ! cp_lexer_consume_token (parser->lexer); ! if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) identifier = cp_parser_identifier (parser); ! else ! identifier = make_anon_name (); /* Issue an error message if type-definitions are forbidden here. */ cp_parser_check_type_definition (parser); ! /* Create the new type. We do this before consuming the opening brace ! so the enum will be recorded as being on the line of its tag (or the ! 'enum' keyword, if there is no tag). */ ! type = start_enum (identifier); ! /* Consume the opening brace. */ ! cp_lexer_consume_token (parser->lexer); ! ! /* If the next token is not '}', then there are some enumerators. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) cp_parser_enumerator_list (parser, type); ! ! /* Consume the final '}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + /* Look for trailing attributes to apply to this enumeration, and + apply them if appropriate. */ + if (cp_parser_allow_gnu_extensions_p (parser)) + { + tree trailing_attr = cp_parser_attributes_opt (parser); + cplus_decl_attributes (&type, + trailing_attr, + (int) ATTR_FLAG_TYPE_IN_PLACE); + } + /* Finish up the enumeration. */ finish_enum (type); *************** cp_parser_enum_specifier (cp_parser* par *** 9353,9359 **** } /* Parse an enumerator-list. The enumerators all have the indicated ! TYPE. enumerator-list: enumerator-definition --- 9988,9994 ---- } /* Parse an enumerator-list. The enumerators all have the indicated ! TYPE. enumerator-list: enumerator-definition *************** cp_parser_enumerator_list (cp_parser* pa *** 9364,9378 **** { while (true) { - cp_token *token; - /* Parse an enumerator-definition. */ cp_parser_enumerator_definition (parser, type); ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* If it's not a `,', then we've reached the end of the ! list. */ ! if (token->type != CPP_COMMA) break; /* Otherwise, consume the `,' and keep going. */ cp_lexer_consume_token (parser->lexer); --- 9999,10010 ---- { while (true) { /* Parse an enumerator-definition. */ cp_parser_enumerator_definition (parser, type); ! ! /* If the next token is not a ',', we've reached the end of ! the list. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) break; /* Otherwise, consume the `,' and keep going. */ cp_lexer_consume_token (parser->lexer); *************** cp_parser_enumerator_list (cp_parser* pa *** 9392,9405 **** enumerator-definition: enumerator enumerator = constant-expression ! enumerator: identifier */ static void cp_parser_enumerator_definition (cp_parser* parser, tree type) { - cp_token *token; tree identifier; tree value; --- 10024,10036 ---- enumerator-definition: enumerator enumerator = constant-expression ! enumerator: identifier */ static void cp_parser_enumerator_definition (cp_parser* parser, tree type) { tree identifier; tree value; *************** cp_parser_enumerator_definition (cp_pars *** 9407,9422 **** identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) return; ! ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* If it's an `=', then there's an explicit value. */ ! if (token->type == CPP_EQ) { /* Consume the `=' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the value. */ ! value = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, NULL); } --- 10038,10051 ---- identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) return; ! ! /* If the next token is an '=', then there is an explicit value. */ ! if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { /* Consume the `=' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the value. */ ! value = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, NULL); } *************** cp_parser_namespace_name (cp_parser* par *** 9452,9474 **** [basic.lookup.udir] When looking up a namespace-name in a using-directive or alias ! definition, only namespace names are considered. And: [basic.lookup.qual] During the lookup of a name preceding the :: scope resolution ! operator, object, function, and enumerator names are ignored. (Note that cp_parser_class_or_namespace_name only calls this function if the token after the name is the scope resolution operator.) */ namespace_decl = cp_parser_lookup_name (parser, identifier, ! /*is_type=*/false, /*is_template=*/false, /*is_namespace=*/true, ! /*check_dependency=*/true); /* If it's not a namespace, issue an error. */ if (namespace_decl == error_mark_node || TREE_CODE (namespace_decl) != NAMESPACE_DECL) --- 10081,10104 ---- [basic.lookup.udir] When looking up a namespace-name in a using-directive or alias ! definition, only namespace names are considered. And: [basic.lookup.qual] During the lookup of a name preceding the :: scope resolution ! operator, object, function, and enumerator names are ignored. (Note that cp_parser_class_or_namespace_name only calls this function if the token after the name is the scope resolution operator.) */ namespace_decl = cp_parser_lookup_name (parser, identifier, ! none_type, /*is_template=*/false, /*is_namespace=*/true, ! /*check_dependency=*/true, ! /*ambiguous_p=*/NULL); /* If it's not a namespace, issue an error. */ if (namespace_decl == error_mark_node || TREE_CODE (namespace_decl) != NAMESPACE_DECL) *************** cp_parser_namespace_name (cp_parser* par *** 9476,9482 **** cp_parser_error (parser, "expected namespace-name"); namespace_decl = error_mark_node; } ! return namespace_decl; } --- 10106,10112 ---- cp_parser_error (parser, "expected namespace-name"); namespace_decl = error_mark_node; } ! return namespace_decl; } *************** cp_parser_namespace_name (cp_parser* par *** 9484,9490 **** namespace-definition: named-namespace-definition ! unnamed-namespace-definition named-namespace-definition: original-namespace-definition --- 10114,10120 ---- namespace-definition: named-namespace-definition ! unnamed-namespace-definition named-namespace-definition: original-namespace-definition *************** cp_parser_namespace_name (cp_parser* par *** 9492,9501 **** original-namespace-definition: namespace identifier { namespace-body } ! extension-namespace-definition: namespace original-namespace-name { namespace-body } ! unnamed-namespace-definition: namespace { namespace-body } */ --- 10122,10131 ---- original-namespace-definition: namespace identifier { namespace-body } ! extension-namespace-definition: namespace original-namespace-name { namespace-body } ! unnamed-namespace-definition: namespace { namespace-body } */ *************** cp_parser_namespace_alias_definition (cp *** 9559,9565 **** /* Look for the `=' token. */ cp_parser_require (parser, CPP_EQ, "`='"); /* Look for the qualified-namespace-specifier. */ ! namespace_specifier = cp_parser_qualified_namespace_specifier (parser); /* Look for the `;' token. */ cp_parser_require (parser, CPP_SEMICOLON, "`;'"); --- 10189,10195 ---- /* Look for the `=' token. */ cp_parser_require (parser, CPP_EQ, "`='"); /* Look for the qualified-namespace-specifier. */ ! namespace_specifier = cp_parser_qualified_namespace_specifier (parser); /* Look for the `;' token. */ cp_parser_require (parser, CPP_SEMICOLON, "`;'"); *************** static tree *** 9580,9586 **** cp_parser_qualified_namespace_specifier (cp_parser* parser) { /* Look for the optional `::'. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the optional nested-name-specifier. */ --- 10210,10216 ---- cp_parser_qualified_namespace_specifier (cp_parser* parser) { /* Look for the optional `::'. */ ! cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the optional nested-name-specifier. */ *************** cp_parser_using_declaration (cp_parser* *** 9607,9618 **** bool global_scope_p; tree decl; tree identifier; - tree scope; tree qscope; /* Look for the `using' keyword. */ cp_parser_require_keyword (parser, RID_USING, "`using'"); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* See if it's `typename'. */ --- 10237,10247 ---- bool global_scope_p; tree decl; tree identifier; tree qscope; /* Look for the `using' keyword. */ cp_parser_require_keyword (parser, RID_USING, "`using'"); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* See if it's `typename'. */ *************** cp_parser_using_declaration (cp_parser* *** 9625,9639 **** } /* Look for the optional global scope qualification. */ ! global_scope_p = (cp_parser_global_scope_opt (parser, ! /*current_scope_valid_p=*/false) != NULL_TREE); /* If we saw `typename', or didn't see `::', then there must be a nested-name-specifier present. */ if (typename_p || !global_scope_p) ! qscope = cp_parser_nested_name_specifier (parser, typename_p, /*check_dependency_p=*/true, /*type_p=*/false, /*is_declaration=*/true); --- 10254,10268 ---- } /* Look for the optional global scope qualification. */ ! global_scope_p = (cp_parser_global_scope_opt (parser, ! /*current_scope_valid_p=*/false) != NULL_TREE); /* If we saw `typename', or didn't see `::', then there must be a nested-name-specifier present. */ if (typename_p || !global_scope_p) ! qscope = cp_parser_nested_name_specifier (parser, typename_p, /*check_dependency_p=*/true, /*type_p=*/false, /*is_declaration=*/true); *************** cp_parser_using_declaration (cp_parser* *** 9649,9655 **** qscope = global_namespace; /* Parse the unqualified-id. */ ! identifier = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*declarator_p=*/true); --- 10278,10284 ---- qscope = global_namespace; /* Parse the unqualified-id. */ ! identifier = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*declarator_p=*/true); *************** cp_parser_using_declaration (cp_parser* *** 9666,9678 **** error ("a template-id may not appear in a using-declaration"); else { ! scope = current_scope (); ! if (scope && TYPE_P (scope)) { /* Create the USING_DECL. */ ! decl = do_class_using_decl (build_nt (SCOPE_REF, ! parser->scope, ! identifier)); /* Add it to the list of members in this class. */ finish_member_declaration (decl); } --- 10295,10304 ---- error ("a template-id may not appear in a using-declaration"); else { ! if (at_class_scope_p ()) { /* Create the USING_DECL. */ ! decl = do_class_using_decl (parser->scope, identifier); /* Add it to the list of members in this class. */ finish_member_declaration (decl); } *************** cp_parser_using_declaration (cp_parser* *** 9681,9687 **** decl = cp_parser_lookup_name_simple (parser, identifier); if (decl == error_mark_node) cp_parser_name_lookup_error (parser, identifier, decl, NULL); ! else if (scope) do_local_using_decl (decl, qscope, identifier); else do_toplevel_using_decl (decl, qscope, identifier); --- 10307,10313 ---- decl = cp_parser_lookup_name_simple (parser, identifier); if (decl == error_mark_node) cp_parser_name_lookup_error (parser, identifier, decl, NULL); ! else if (!at_namespace_scope_p ()) do_local_using_decl (decl, qscope, identifier); else do_toplevel_using_decl (decl, qscope, identifier); *************** cp_parser_using_declaration (cp_parser* *** 9692,9699 **** cp_parser_require (parser, CPP_SEMICOLON, "`;'"); } ! /* Parse a using-directive. ! using-directive: using namespace :: [opt] nested-name-specifier [opt] namespace-name ; */ --- 10318,10325 ---- cp_parser_require (parser, CPP_SEMICOLON, "`;'"); } ! /* Parse a using-directive. ! using-directive: using namespace :: [opt] nested-name-specifier [opt] namespace-name ; */ *************** cp_parser_using_directive (cp_parser* pa *** 9729,9735 **** /* Parse an asm-definition. asm-definition: ! asm ( string-literal ) ; GNU Extension: --- 10355,10361 ---- /* Parse an asm-definition. asm-definition: ! asm ( string-literal ) ; GNU Extension: *************** cp_parser_using_directive (cp_parser* pa *** 9738,9751 **** asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ; asm volatile [opt] ( string-literal : asm-operand-list [opt] : asm-operand-list [opt] ) ; ! asm volatile [opt] ( string-literal : asm-operand-list [opt] ! : asm-operand-list [opt] : asm-operand-list [opt] ) ; */ static void cp_parser_asm_definition (cp_parser* parser) { - cp_token *token; tree string; tree outputs = NULL_TREE; tree inputs = NULL_TREE; --- 10364,10376 ---- asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ; asm volatile [opt] ( string-literal : asm-operand-list [opt] : asm-operand-list [opt] ) ; ! asm volatile [opt] ( string-literal : asm-operand-list [opt] ! : asm-operand-list [opt] : asm-operand-list [opt] ) ; */ static void cp_parser_asm_definition (cp_parser* parser) { tree string; tree outputs = NULL_TREE; tree inputs = NULL_TREE; *************** cp_parser_asm_definition (cp_parser* par *** 9766,9779 **** cp_lexer_consume_token (parser->lexer); } /* Look for the opening `('. */ ! cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); ! /* Look for the string. */ ! token = cp_parser_require (parser, CPP_STRING, "asm body"); ! if (!token) return; ! string = token->value; /* If we're allowing GNU extensions, check for the extended assembly ! syntax. Unfortunately, the `:' tokens need not be separated by a space in C, and so, for compatibility, we tolerate that here too. Doing that means that we have to treat the `::' operator as two `:' tokens. */ --- 10391,10409 ---- cp_lexer_consume_token (parser->lexer); } /* Look for the opening `('. */ ! if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) return; ! /* Look for the string. */ ! string = cp_parser_string_literal (parser, false, false); ! if (string == error_mark_node) ! { ! cp_parser_skip_to_closing_parenthesis (parser, true, false, ! /*consume_paren=*/true); ! return; ! } ! /* If we're allowing GNU extensions, check for the extended assembly ! syntax. Unfortunately, the `:' tokens need not be separated by a space in C, and so, for compatibility, we tolerate that here too. Doing that means that we have to treat the `::' operator as two `:' tokens. */ *************** cp_parser_asm_definition (cp_parser* par *** 9794,9800 **** /* Consume the `:'. */ cp_lexer_consume_token (parser->lexer); /* Parse the output-operands. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) --- 10424,10430 ---- /* Consume the `:'. */ cp_lexer_consume_token (parser->lexer); /* Parse the output-operands. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) *************** cp_parser_asm_definition (cp_parser* par *** 9815,9821 **** /* Consume the `:' or `::'. */ cp_lexer_consume_token (parser->lexer); /* Parse the output-operands. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) --- 10445,10451 ---- /* Consume the `:' or `::'. */ cp_lexer_consume_token (parser->lexer); /* Parse the output-operands. */ ! if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) *************** cp_parser_asm_definition (cp_parser* par *** 9826,9832 **** clobbers_p = true; /* Look for clobbers. */ ! if (clobbers_p || cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { /* Consume the `:' or `::'. */ --- 10456,10462 ---- clobbers_p = true; /* Look for clobbers. */ ! if (clobbers_p || cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { /* Consume the `:' or `::'. */ *************** cp_parser_asm_definition (cp_parser* par *** 9843,9858 **** /*consume_paren=*/true); cp_parser_require (parser, CPP_SEMICOLON, "`;'"); ! /* Create the ASM_STMT. */ if (at_function_scope_p ()) { ! asm_stmt = ! finish_asm_stmt (volatile_p ! ? ridpointers[(int) RID_VOLATILE] : NULL_TREE, ! string, outputs, inputs, clobbers); ! /* If the extended syntax was not used, mark the ASM_STMT. */ if (!extended_p) ! ASM_INPUT_P (asm_stmt) = 1; } else assemble_asm (string); --- 10473,10492 ---- /*consume_paren=*/true); cp_parser_require (parser, CPP_SEMICOLON, "`;'"); ! /* Create the ASM_EXPR. */ if (at_function_scope_p ()) { ! asm_stmt = finish_asm_stmt (volatile_p, string, outputs, ! inputs, clobbers); ! /* If the extended syntax was not used, mark the ASM_EXPR. */ if (!extended_p) ! { ! tree temp = asm_stmt; ! if (TREE_CODE (temp) == CLEANUP_POINT_EXPR) ! temp = TREE_OPERAND (temp, 0); ! ! ASM_INPUT_P (temp) = 1; ! } } else assemble_asm (string); *************** cp_parser_asm_definition (cp_parser* par *** 9872,9884 **** function-definition: decl-specifier-seq [opt] declarator ctor-initializer [opt] ! function-body ! decl-specifier-seq [opt] declarator function-try-block GNU Extension: function-definition: ! __extension__ function-definition The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. Returns a representation of the entity declared. If MEMBER_P is TRUE, --- 10506,10518 ---- function-definition: decl-specifier-seq [opt] declarator ctor-initializer [opt] ! function-body ! decl-specifier-seq [opt] declarator function-try-block GNU Extension: function-definition: ! __extension__ function-definition The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. Returns a representation of the entity declared. If MEMBER_P is TRUE, *************** cp_parser_asm_definition (cp_parser* par *** 9895,9910 **** is FALSE. */ static tree ! cp_parser_init_declarator (cp_parser* parser, ! tree decl_specifiers, ! tree prefix_attributes, bool function_definition_allowed_p, bool member_p, int declares_class_or_enum, bool* function_definition_p) { cp_token *token; ! tree declarator; tree attributes; tree asm_specification; tree initializer; --- 10529,10544 ---- is FALSE. */ static tree ! cp_parser_init_declarator (cp_parser* parser, ! cp_decl_specifier_seq *decl_specifiers, bool function_definition_allowed_p, bool member_p, int declares_class_or_enum, bool* function_definition_p) { cp_token *token; ! cp_declarator *declarator; ! tree prefix_attributes; tree attributes; tree asm_specification; tree initializer; *************** cp_parser_init_declarator (cp_parser* pa *** 9915,9921 **** bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; ! bool pop_p = false; /* Assume that this is not the declarator for a function definition. */ --- 10549,10559 ---- bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; ! tree pushed_scope = NULL; ! ! /* Gather the attributes that were provided with the ! decl-specifiers. */ ! prefix_attributes = decl_specifiers->attributes; /* Assume that this is not the declarator for a function definition. */ *************** cp_parser_init_declarator (cp_parser* pa *** 9923,9934 **** *function_definition_p = false; /* Defer access checks while parsing the declarator; we cannot know ! what names are accessible until we know what is being declared. */ resume_deferring_access_checks (); /* Parse the declarator. */ ! declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, --- 10561,10572 ---- *function_definition_p = false; /* Defer access checks while parsing the declarator; we cannot know ! what names are accessible until we know what is being declared. */ resume_deferring_access_checks (); /* Parse the declarator. */ ! declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, *************** cp_parser_init_declarator (cp_parser* pa *** 9938,9948 **** /* If the DECLARATOR was erroneous, there's no need to go further. */ ! if (declarator == error_mark_node) return error_mark_node; ! cp_parser_check_for_definition_in_return_type (declarator, ! declares_class_or_enum); /* Figure out what scope the entity declared by the DECLARATOR is located in. `grokdeclarator' sometimes changes the scope, so --- 10576,10587 ---- /* If the DECLARATOR was erroneous, there's no need to go further. */ ! if (declarator == cp_error_declarator) return error_mark_node; ! if (declares_class_or_enum & 2) ! cp_parser_check_for_definition_in_return_type (declarator, ! decl_specifiers->type); /* Figure out what scope the entity declared by the DECLARATOR is located in. `grokdeclarator' sometimes changes the scope, so *************** cp_parser_init_declarator (cp_parser* pa *** 9996,10002 **** declarator, prefix_attributes); else ! decl = (cp_parser_function_definition_from_specifiers_and_declarator (parser, decl_specifiers, prefix_attributes, declarator)); --- 10635,10641 ---- declarator, prefix_attributes); else ! decl = (cp_parser_function_definition_from_specifiers_and_declarator (parser, decl_specifiers, prefix_attributes, declarator)); *************** cp_parser_init_declarator (cp_parser* pa *** 10007,10034 **** /* [dcl.dcl] Only in function declarations for constructors, destructors, and ! type conversions can the decl-specifier-seq be omitted. We explicitly postpone this check past the point where we handle function-definitions because we tolerate function-definitions that are missing their return types in some modes. */ ! if (!decl_specifiers && ctor_dtor_or_conv_p <= 0) { ! cp_parser_error (parser, "expected constructor, destructor, or type conversion"); return error_mark_node; } /* An `=' or an `(' indicates an initializer. */ ! is_initialized = (token->type == CPP_EQ || token->type == CPP_OPEN_PAREN); /* If the init-declarator isn't initialized and isn't followed by a `,' or `;', it's not a valid init-declarator. */ ! if (!is_initialized && token->type != CPP_COMMA && token->type != CPP_SEMICOLON) { ! cp_parser_error (parser, "expected init-declarator"); return error_mark_node; } --- 10646,10673 ---- /* [dcl.dcl] Only in function declarations for constructors, destructors, and ! type conversions can the decl-specifier-seq be omitted. We explicitly postpone this check past the point where we handle function-definitions because we tolerate function-definitions that are missing their return types in some modes. */ ! if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0) { ! cp_parser_error (parser, "expected constructor, destructor, or type conversion"); return error_mark_node; } /* An `=' or an `(' indicates an initializer. */ ! is_initialized = (token->type == CPP_EQ || token->type == CPP_OPEN_PAREN); /* If the init-declarator isn't initialized and isn't followed by a `,' or `;', it's not a valid init-declarator. */ ! if (!is_initialized && token->type != CPP_COMMA && token->type != CPP_SEMICOLON) { ! cp_parser_error (parser, "expected initializer"); return error_mark_node; } *************** cp_parser_init_declarator (cp_parser* pa *** 10041,10051 **** sure this was intended to be a declarator. Then continue declaring the variable(s), as int, to try to cut down on further errors. */ ! if (decl_specifiers != NULL ! && TREE_VALUE (decl_specifiers) == error_mark_node) { cp_parser_error (parser, "invalid type in declaration"); ! TREE_VALUE (decl_specifiers) = integer_type_node; } /* Check to see whether or not this declaration is a friend. */ --- 10680,10690 ---- sure this was intended to be a declarator. Then continue declaring the variable(s), as int, to try to cut down on further errors. */ ! if (decl_specifiers->any_specifiers_p ! && decl_specifiers->type == error_mark_node) { cp_parser_error (parser, "invalid type in declaration"); ! decl_specifiers->type = integer_type_node; } /* Check to see whether or not this declaration is a friend. */ *************** cp_parser_init_declarator (cp_parser* pa *** 10062,10084 **** { if (parser->in_unbraced_linkage_specification_p) { ! decl_specifiers = tree_cons (error_mark_node, ! get_identifier ("extern"), ! decl_specifiers); have_extern_spec = false; } decl = start_decl (declarator, decl_specifiers, ! is_initialized, attributes, prefix_attributes); } ! ! /* Enter the SCOPE. That way unqualified names appearing in the ! initializer will be looked up in SCOPE. */ ! if (scope) ! pop_p = push_scope (scope); /* Perform deferred access control checks, now that we know in which SCOPE the declared entity resides. */ ! if (!member_p && decl) { tree saved_current_function_decl = NULL_TREE; --- 10701,10721 ---- { if (parser->in_unbraced_linkage_specification_p) { ! decl_specifiers->storage_class = sc_extern; have_extern_spec = false; } decl = start_decl (declarator, decl_specifiers, ! is_initialized, attributes, prefix_attributes, ! &pushed_scope); } ! else if (scope) ! /* Enter the SCOPE. That way unqualified names appearing in the ! initializer will be looked up in SCOPE. */ ! pushed_scope = push_scope (scope); /* Perform deferred access control checks, now that we know in which SCOPE the declared entity resides. */ ! if (!member_p && decl) { tree saved_current_function_decl = NULL_TREE; *************** cp_parser_init_declarator (cp_parser* pa *** 10090,10096 **** saved_current_function_decl = current_function_decl; current_function_decl = decl; } ! /* Perform the access control checks for the declarator and the the decl-specifiers. */ perform_deferred_access_checks (); --- 10727,10733 ---- saved_current_function_decl = current_function_decl; current_function_decl = decl; } ! /* Perform the access control checks for the declarator and the the decl-specifiers. */ perform_deferred_access_checks (); *************** cp_parser_init_declarator (cp_parser* pa *** 10102,10108 **** /* Parse the initializer. */ if (is_initialized) ! initializer = cp_parser_initializer (parser, &is_parenthesized_init, &is_non_constant_init); else --- 10739,10745 ---- /* Parse the initializer. */ if (is_initialized) ! initializer = cp_parser_initializer (parser, &is_parenthesized_init, &is_non_constant_init); else *************** cp_parser_init_declarator (cp_parser* pa *** 10120,10159 **** if (cp_parser_attributes_opt (parser)) warning ("attributes after parenthesized initializer ignored"); - /* Leave the SCOPE, now that we have processed the initializer. It - is important to do this before calling cp_finish_decl because it - makes decisions about whether to create DECL_STMTs or not based - on the current scope. */ - if (pop_p) - pop_scope (scope); - /* For an in-class declaration, use `grokfield' to create the declaration. */ if (member_p) { decl = grokfield (declarator, decl_specifiers, initializer, /*asmspec=*/NULL_TREE, /*attributes=*/NULL_TREE); if (decl && TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); } ! /* Finish processing the declaration. But, skip friend declarations. */ ! if (!friend_p && decl) ! cp_finish_decl (decl, ! initializer, ! asm_specification, ! /* If the initializer is in parentheses, then this is ! a direct-initialization, which means that an ! `explicit' constructor is OK. Otherwise, an ! `explicit' constructor cannot be used. */ ! ((is_parenthesized_init || !is_initialized) ? 0 : LOOKUP_ONLYCONVERTING)); /* Remember whether or not variables were initialized by constant-expressions. */ ! if (decl && TREE_CODE (decl) == VAR_DECL && is_initialized && !is_non_constant_init) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; --- 10757,10798 ---- if (cp_parser_attributes_opt (parser)) warning ("attributes after parenthesized initializer ignored"); /* For an in-class declaration, use `grokfield' to create the declaration. */ if (member_p) { + if (pushed_scope) + { + pop_scope (pushed_scope); + pushed_scope = false; + } decl = grokfield (declarator, decl_specifiers, initializer, /*asmspec=*/NULL_TREE, /*attributes=*/NULL_TREE); if (decl && TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); } ! /* Finish processing the declaration. But, skip friend declarations. */ ! if (!friend_p && decl && decl != error_mark_node) ! { ! cp_finish_decl (decl, ! initializer, ! asm_specification, ! /* If the initializer is in parentheses, then this is ! a direct-initialization, which means that an ! `explicit' constructor is OK. Otherwise, an ! `explicit' constructor cannot be used. */ ! ((is_parenthesized_init || !is_initialized) ? 0 : LOOKUP_ONLYCONVERTING)); + } + if (!friend_p && pushed_scope) + pop_scope (pushed_scope); /* Remember whether or not variables were initialized by constant-expressions. */ ! if (decl && TREE_CODE (decl) == VAR_DECL && is_initialized && !is_non_constant_init) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; *************** cp_parser_init_declarator (cp_parser* pa *** 10161,10170 **** } /* Parse a declarator. ! declarator: direct-declarator ! ptr-operator declarator abstract-declarator: ptr-operator abstract-declarator [opt] --- 10800,10809 ---- } /* Parse a declarator. ! declarator: direct-declarator ! ptr-operator declarator abstract-declarator: ptr-operator abstract-declarator [opt] *************** cp_parser_init_declarator (cp_parser* pa *** 10174,10235 **** declarator: attributes [opt] direct-declarator ! attributes [opt] ptr-operator declarator abstract-declarator: attributes [opt] ptr-operator abstract-declarator [opt] attributes [opt] direct-abstract-declarator - - Returns a representation of the declarator. If the declarator has - the form `* declarator', then an INDIRECT_REF is returned, whose - only operand is the sub-declarator. Analogously, `& declarator' is - represented as an ADDR_EXPR. For `X::* declarator', a SCOPE_REF is - used. The first operand is the TYPE for `X'. The second operand - is an INDIRECT_REF whose operand is the sub-declarator. - - Otherwise, the representation is as for a direct-declarator. - - (It would be better to define a structure type to represent - declarators, rather than abusing `tree' nodes to represent - declarators. That would be much clearer and save some memory. - There is no reason for declarators to be garbage-collected, for - example; they are created during parser and no longer needed after - `grokdeclarator' has been called.) - - For a ptr-operator that has the optional cv-qualifier-seq, - cv-qualifiers will be stored in the TREE_TYPE of the INDIRECT_REF - node. If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to detect constructor, destructor or conversion operators. It is set to -1 if the declarator is a name, and +1 if it is a function. Otherwise it is set to zero. Usually you just want to test for >0, but internally the negative value is used. ! (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have a decl-specifier-seq unless it declares a constructor, destructor, or conversion. It might seem that we could check this condition in semantic analysis, rather than parsing, but that makes it difficult to handle something like `f()'. We want to notice that there are no decl-specifiers, and therefore realize that this is an ! expression, not a declaration.) ! If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff ! the declarator is a direct-declarator of the form "(...)". MEMBER_P is true iff this declarator is a member-declarator. */ ! static tree ! cp_parser_declarator (cp_parser* parser, ! cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, bool* parenthesized_p, bool member_p) { cp_token *token; ! tree declarator; enum tree_code code; ! tree cv_qualifier_seq; tree class_type; tree attributes = NULL_TREE; --- 10813,10854 ---- declarator: attributes [opt] direct-declarator ! attributes [opt] ptr-operator declarator abstract-declarator: attributes [opt] ptr-operator abstract-declarator [opt] attributes [opt] direct-abstract-declarator If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to detect constructor, destructor or conversion operators. It is set to -1 if the declarator is a name, and +1 if it is a function. Otherwise it is set to zero. Usually you just want to test for >0, but internally the negative value is used. ! (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have a decl-specifier-seq unless it declares a constructor, destructor, or conversion. It might seem that we could check this condition in semantic analysis, rather than parsing, but that makes it difficult to handle something like `f()'. We want to notice that there are no decl-specifiers, and therefore realize that this is an ! expression, not a declaration.) ! If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff ! the declarator is a direct-declarator of the form "(...)". MEMBER_P is true iff this declarator is a member-declarator. */ ! static cp_declarator * ! cp_parser_declarator (cp_parser* parser, ! cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, bool* parenthesized_p, bool member_p) { cp_token *token; ! cp_declarator *declarator; enum tree_code code; ! cp_cv_quals cv_quals; tree class_type; tree attributes = NULL_TREE; *************** cp_parser_declarator (cp_parser* parser, *** 10240,10255 **** if (cp_parser_allow_gnu_extensions_p (parser)) attributes = cp_parser_attributes_opt (parser); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! /* Check for the ptr-operator production. */ cp_parser_parse_tentatively (parser); /* Parse the ptr-operator. */ ! code = cp_parser_ptr_operator (parser, ! &class_type, ! &cv_qualifier_seq); /* If that worked, then we have a ptr-operator. */ if (cp_parser_parse_definitely (parser)) { --- 10859,10874 ---- if (cp_parser_allow_gnu_extensions_p (parser)) attributes = cp_parser_attributes_opt (parser); ! /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); ! /* Check for the ptr-operator production. */ cp_parser_parse_tentatively (parser); /* Parse the ptr-operator. */ ! code = cp_parser_ptr_operator (parser, ! &class_type, ! &cv_quals); /* If that worked, then we have a ptr-operator. */ if (cp_parser_parse_definitely (parser)) { *************** cp_parser_declarator (cp_parser* parser, *** 10272,10289 **** case where the dependent declarator is absent. */ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED && !cp_parser_parse_definitely (parser)) ! declarator = NULL_TREE; ! /* Build the representation of the ptr-operator. */ - if (code == INDIRECT_REF) - declarator = make_pointer_declarator (cv_qualifier_seq, - declarator); - else - declarator = make_reference_declarator (cv_qualifier_seq, - declarator); - /* Handle the pointer-to-member case. */ if (class_type) ! declarator = build_nt (SCOPE_REF, class_type, declarator); } /* Everything else is a direct-declarator. */ else --- 10891,10907 ---- case where the dependent declarator is absent. */ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED && !cp_parser_parse_definitely (parser)) ! declarator = NULL; ! /* Build the representation of the ptr-operator. */ if (class_type) ! declarator = make_ptrmem_declarator (cv_quals, ! class_type, ! declarator); ! else if (code == INDIRECT_REF) ! declarator = make_pointer_declarator (cv_quals, declarator); ! else ! declarator = make_reference_declarator (cv_quals, declarator); } /* Everything else is a direct-declarator. */ else *************** cp_parser_declarator (cp_parser* parser, *** 10296,10304 **** member_p); } ! if (attributes && declarator != error_mark_node) ! declarator = tree_cons (attributes, declarator, NULL_TREE); ! return declarator; } --- 10914,10922 ---- member_p); } ! if (attributes && declarator != cp_error_declarator) ! declarator->attributes = attributes; ! return declarator; } *************** cp_parser_declarator (cp_parser* parser, *** 10307,10320 **** direct-declarator: declarator-id direct-declarator ( parameter-declaration-clause ) ! cv-qualifier-seq [opt] exception-specification [opt] direct-declarator [ constant-expression [opt] ] ! ( declarator ) direct-abstract-declarator: direct-abstract-declarator [opt] ! ( parameter-declaration-clause ) cv-qualifier-seq [opt] exception-specification [opt] direct-abstract-declarator [opt] [ constant-expression [opt] ] --- 10925,10938 ---- direct-declarator: declarator-id direct-declarator ( parameter-declaration-clause ) ! cv-qualifier-seq [opt] exception-specification [opt] direct-declarator [ constant-expression [opt] ] ! ( declarator ) direct-abstract-declarator: direct-abstract-declarator [opt] ! ( parameter-declaration-clause ) cv-qualifier-seq [opt] exception-specification [opt] direct-abstract-declarator [opt] [ constant-expression [opt] ] *************** cp_parser_declarator (cp_parser* parser, *** 10326,10356 **** we are parsing a direct-declarator. It is CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case of ambiguity we prefer an abstract declarator, as per ! [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P is as for ! cp_parser_declarator. ! ! For the declarator-id production, the representation is as for an ! id-expression, except that a qualified name is represented as a ! SCOPE_REF. A function-declarator is represented as a CALL_EXPR; ! see the documentation of the FUNCTION_DECLARATOR_* macros for ! information about how to find the various declarator components. ! An array-declarator is represented as an ARRAY_REF. The ! direct-declarator is the first operand; the constant-expression ! indicating the size of the array is the second operand. */ ! static tree cp_parser_direct_declarator (cp_parser* parser, cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, bool member_p) { cp_token *token; ! tree declarator = NULL_TREE; tree scope = NULL_TREE; bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_in_declarator_p = parser->in_declarator_p; bool first = true; ! bool pop_p = false; while (true) { --- 10944,10965 ---- we are parsing a direct-declarator. It is CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case of ambiguity we prefer an abstract declarator, as per ! [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P and MEMBER_P are as for ! cp_parser_declarator. */ ! static cp_declarator * cp_parser_direct_declarator (cp_parser* parser, cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, bool member_p) { cp_token *token; ! cp_declarator *declarator = NULL; tree scope = NULL_TREE; bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_in_declarator_p = parser->in_declarator_p; bool first = true; ! tree pushed_scope = NULL_TREE; while (true) { *************** cp_parser_direct_declarator (cp_parser* *** 10368,10374 **** template parameter `(T)' is a parameter-declaration-clause, and not a parenthesized named declarator. ! We first try and parse a parameter-declaration-clause, and then try a nested declarator (if FIRST is true). --- 10977,10983 ---- template parameter `(T)' is a parameter-declaration-clause, and not a parenthesized named declarator. ! We first try and parse a parameter-declaration-clause, and then try a nested declarator (if FIRST is true). *************** cp_parser_direct_declarator (cp_parser* *** 10391,10406 **** int i (int (3)); The former is a function-declaration; the latter is a ! variable initialization. Thus again, we try a parameter-declaration-clause, and if that fails, we back out and return. */ if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { ! tree params; unsigned saved_num_template_parameter_lists; ! /* In a member-declarator, the only valid interpretation of a parenthesis is the start of a parameter-declaration-clause. (It is invalid to --- 11000,11015 ---- int i (int (3)); The former is a function-declaration; the latter is a ! variable initialization. Thus again, we try a parameter-declaration-clause, and if that fails, we back out and return. */ if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { ! cp_parameter_declarator *params; unsigned saved_num_template_parameter_lists; ! /* In a member-declarator, the only valid interpretation of a parenthesis is the start of a parameter-declaration-clause. (It is invalid to *************** cp_parser_direct_declarator (cp_parser* *** 10419,10425 **** parser->default_arg_ok_p = false; parser->in_declarator_p = true; } ! /* Inside the function parameter list, surrounding template-parameter-lists do not apply. */ saved_num_template_parameter_lists --- 11028,11034 ---- parser->default_arg_ok_p = false; parser->in_declarator_p = true; } ! /* Inside the function parameter list, surrounding template-parameter-lists do not apply. */ saved_num_template_parameter_lists *************** cp_parser_direct_declarator (cp_parser* *** 10436,10442 **** exception-specification. */ if (member_p || cp_parser_parse_definitely (parser)) { ! tree cv_qualifiers; tree exception_specification; if (ctor_dtor_or_conv_p) --- 11045,11051 ---- exception-specification. */ if (member_p || cp_parser_parse_definitely (parser)) { ! cp_cv_quals cv_quals; tree exception_specification; if (ctor_dtor_or_conv_p) *************** cp_parser_direct_declarator (cp_parser* *** 10446,10471 **** cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the cv-qualifier-seq. */ ! cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser); /* And the exception-specification. */ ! exception_specification = cp_parser_exception_specification_opt (parser); /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, ! cv_qualifiers, exception_specification); /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ parser->default_arg_ok_p = false; ! /* Repeat the main loop. */ continue; } } ! /* If this is the first, we can try a parenthesized declarator. */ if (first) --- 11055,11080 ---- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the cv-qualifier-seq. */ ! cv_quals = cp_parser_cv_qualifier_seq_opt (parser); /* And the exception-specification. */ ! exception_specification = cp_parser_exception_specification_opt (parser); /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, ! cv_quals, exception_specification); /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ parser->default_arg_ok_p = false; ! /* Repeat the main loop. */ continue; } } ! /* If this is the first, we can try a parenthesized declarator. */ if (first) *************** cp_parser_direct_declarator (cp_parser* *** 10474,10486 **** parser->default_arg_ok_p = saved_default_arg_ok_p; parser->in_declarator_p = saved_in_declarator_p; ! /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); /* Parse the nested declarator. */ saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; parser->in_type_id_in_expr_p = true; ! declarator = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, member_p); --- 11083,11095 ---- parser->default_arg_ok_p = saved_default_arg_ok_p; parser->in_declarator_p = saved_in_declarator_p; ! /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); /* Parse the nested declarator. */ saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; parser->in_type_id_in_expr_p = true; ! declarator = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, member_p); *************** cp_parser_direct_declarator (cp_parser* *** 10488,10497 **** first = false; /* Expect a `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) ! declarator = error_mark_node; ! if (declarator == error_mark_node) break; ! goto handle_declarator; } /* Otherwise, we must be done. */ --- 11097,11106 ---- first = false; /* Expect a `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) ! declarator = cp_error_declarator; ! if (declarator == cp_error_declarator) break; ! goto handle_declarator; } /* Otherwise, we must be done. */ *************** cp_parser_direct_declarator (cp_parser* *** 10506,10512 **** if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = 0; ! first = false; parser->default_arg_ok_p = false; parser->in_declarator_p = true; --- 11115,11121 ---- if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = 0; ! first = false; parser->default_arg_ok_p = false; parser->in_declarator_p = true; *************** cp_parser_direct_declarator (cp_parser* *** 10520,10634 **** { bool non_constant_p; ! bounds = cp_parser_constant_expression (parser, /*allow_non_constant=*/true, &non_constant_p); if (!non_constant_p) bounds = fold_non_dependent_expr (bounds); } else bounds = NULL_TREE; /* Look for the closing `]'. */ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'")) { ! declarator = error_mark_node; break; } ! declarator = build_nt (ARRAY_REF, declarator, bounds); } else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) { /* Parse a declarator-id */ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) cp_parser_parse_tentatively (parser); ! declarator = cp_parser_declarator_id (parser); if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) { if (!cp_parser_parse_definitely (parser)) ! declarator = error_mark_node; ! else if (TREE_CODE (declarator) != IDENTIFIER_NODE) { cp_parser_error (parser, "expected unqualified-id"); ! declarator = error_mark_node; } } ! ! if (declarator == error_mark_node) ! break; ! ! if (TREE_CODE (declarator) == SCOPE_REF ! && !current_scope ()) { ! tree scope = TREE_OPERAND (declarator, 0); /* In the declaration of a member of a template class outside of the class itself, the SCOPE will sometimes be a TYPENAME_TYPE. For example, given: ! template int S::R::i = 3; ! the SCOPE will be a TYPENAME_TYPE for `S::R'. In this context, we must resolve S::R to an ordinary type, rather than a typename type. ! The reason we normally avoid resolving TYPENAME_TYPEs is that a specialization of `S' might render `S::R' not a type. However, if `S' is specialized, then this `i' will not be used, so there is no harm in resolving the types here. */ ! if (TREE_CODE (scope) == TYPENAME_TYPE) ! { ! tree type; ! ! /* Resolve the TYPENAME_TYPE. */ ! type = resolve_typename_type (scope, ! /*only_current_p=*/false); ! /* If that failed, the declarator is invalid. */ ! if (type == error_mark_node) ! error ("`%T::%D' is not a type", ! TYPE_CONTEXT (scope), ! TYPE_IDENTIFIER (scope)); ! /* Build a new DECLARATOR. */ ! declarator = build_nt (SCOPE_REF, ! type, ! TREE_OPERAND (declarator, 1)); ! } } ! ! /* Check to see whether the declarator-id names a constructor, ! destructor, or conversion. */ ! if (declarator && ctor_dtor_or_conv_p ! && ((TREE_CODE (declarator) == SCOPE_REF ! && CLASS_TYPE_P (TREE_OPERAND (declarator, 0))) ! || (TREE_CODE (declarator) != SCOPE_REF ! && at_class_scope_p ()))) { - tree unqualified_name; tree class_type; ! /* Get the unqualified part of the name. */ ! if (TREE_CODE (declarator) == SCOPE_REF) ! { ! class_type = TREE_OPERAND (declarator, 0); ! unqualified_name = TREE_OPERAND (declarator, 1); ! } else { ! class_type = current_class_type; ! unqualified_name = declarator; ! } ! /* See if it names ctor, dtor or conv. */ ! if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR ! || IDENTIFIER_TYPENAME_P (unqualified_name) ! || constructor_name_p (unqualified_name, class_type) ! || (TREE_CODE (unqualified_name) == TYPE_DECL ! && same_type_p (TREE_TYPE (unqualified_name), ! class_type))) ! *ctor_dtor_or_conv_p = -1; } handle_declarator:; --- 11129,11265 ---- { bool non_constant_p; ! bounds = cp_parser_constant_expression (parser, /*allow_non_constant=*/true, &non_constant_p); if (!non_constant_p) bounds = fold_non_dependent_expr (bounds); + /* Normally, the array bound must be an integral constant + expression. However, as an extension, we allow VLAs + in function scopes. */ + else if (!at_function_scope_p ()) + { + error ("array bound is not an integer constant"); + bounds = error_mark_node; + } } else bounds = NULL_TREE; /* Look for the closing `]'. */ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'")) { ! declarator = cp_error_declarator; break; } ! declarator = make_array_declarator (declarator, bounds); } else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) { + tree qualifying_scope; + tree unqualified_name; + /* Parse a declarator-id */ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) cp_parser_parse_tentatively (parser); ! unqualified_name = cp_parser_declarator_id (parser); ! qualifying_scope = parser->scope; if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) { if (!cp_parser_parse_definitely (parser)) ! unqualified_name = error_mark_node; ! else if (qualifying_scope ! || (TREE_CODE (unqualified_name) ! != IDENTIFIER_NODE)) { cp_parser_error (parser, "expected unqualified-id"); ! unqualified_name = error_mark_node; } } ! ! if (unqualified_name == error_mark_node) { ! declarator = cp_error_declarator; ! break; ! } + if (qualifying_scope && at_namespace_scope_p () + && TREE_CODE (qualifying_scope) == TYPENAME_TYPE) + { /* In the declaration of a member of a template class outside of the class itself, the SCOPE will sometimes be a TYPENAME_TYPE. For example, given: ! template int S::R::i = 3; ! the SCOPE will be a TYPENAME_TYPE for `S::R'. In this context, we must resolve S::R to an ordinary type, rather than a typename type. ! The reason we normally avoid resolving TYPENAME_TYPEs is that a specialization of `S' might render `S::R' not a type. However, if `S' is specialized, then this `i' will not be used, so there is no harm in resolving the types here. */ ! tree type; ! ! /* Resolve the TYPENAME_TYPE. */ ! type = resolve_typename_type (qualifying_scope, ! /*only_current_p=*/false); ! /* If that failed, the declarator is invalid. */ ! if (type == error_mark_node) ! error ("%<%T::%D%> is not a type", ! TYPE_CONTEXT (qualifying_scope), ! TYPE_IDENTIFIER (qualifying_scope)); ! qualifying_scope = type; } ! ! declarator = make_id_declarator (qualifying_scope, ! unqualified_name); ! if (unqualified_name) { tree class_type; ! if (qualifying_scope ! && CLASS_TYPE_P (qualifying_scope)) ! class_type = qualifying_scope; else + class_type = current_class_type; + + if (class_type) { ! if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR) ! declarator->u.id.sfk = sfk_destructor; ! else if (IDENTIFIER_TYPENAME_P (unqualified_name)) ! declarator->u.id.sfk = sfk_conversion; ! else if (/* There's no way to declare a constructor ! for an anonymous type, even if the type ! got a name for linkage purposes. */ ! !TYPE_WAS_ANONYMOUS (class_type) ! && (constructor_name_p (unqualified_name, ! class_type) ! || (TREE_CODE (unqualified_name) == TYPE_DECL ! && (same_type_p ! (TREE_TYPE (unqualified_name), ! class_type))))) ! declarator->u.id.sfk = sfk_constructor; ! if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none) ! *ctor_dtor_or_conv_p = -1; ! if (qualifying_scope ! && TREE_CODE (unqualified_name) == TYPE_DECL ! && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name))) ! { ! error ("invalid use of constructor as a template"); ! inform ("use %<%T::%D%> instead of %<%T::%T%> to name " ! "the constructor in a qualified name", ! class_type, ! DECL_NAME (TYPE_TI_TEMPLATE (class_type)), ! class_type, class_type); ! } ! } } handle_declarator:; *************** cp_parser_direct_declarator (cp_parser* *** 10636,10647 **** if (scope) /* Any names that appear after the declarator-id for a member are looked up in the containing scope. */ ! pop_p = push_scope (scope); parser->in_declarator_p = true; if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) ! || (declarator ! && (TREE_CODE (declarator) == SCOPE_REF ! || TREE_CODE (declarator) == IDENTIFIER_NODE))) /* Default args are only allowed on function declarations. */ parser->default_arg_ok_p = saved_default_arg_ok_p; --- 11267,11276 ---- if (scope) /* Any names that appear after the declarator-id for a member are looked up in the containing scope. */ ! pushed_scope = push_scope (scope); parser->in_declarator_p = true; if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) ! || (declarator && declarator->kind == cdk_id)) /* Default args are only allowed on function declarations. */ parser->default_arg_ok_p = saved_default_arg_ok_p; *************** cp_parser_direct_declarator (cp_parser* *** 10661,10676 **** cp_parser_error (parser, "expected declarator"); /* If we entered a scope, we must exit it now. */ ! if (pop_p) ! pop_scope (scope); parser->default_arg_ok_p = saved_default_arg_ok_p; parser->in_declarator_p = saved_in_declarator_p; ! return declarator; } ! /* Parse a ptr-operator. ptr-operator: * cv-qualifier-seq [opt] --- 11290,11305 ---- cp_parser_error (parser, "expected declarator"); /* If we entered a scope, we must exit it now. */ ! if (pushed_scope) ! pop_scope (pushed_scope); parser->default_arg_ok_p = saved_default_arg_ok_p; parser->in_declarator_p = saved_in_declarator_p; ! return declarator; } ! /* Parse a ptr-operator. ptr-operator: * cv-qualifier-seq [opt] *************** cp_parser_direct_declarator (cp_parser* *** 10682,10698 **** ptr-operator: & cv-qualifier-seq [opt] ! Returns INDIRECT_REF if a pointer, or pointer-to-member, was ! used. Returns ADDR_EXPR if a reference was used. In the ! case of a pointer-to-member, *TYPE is filled in with the ! TYPE containing the member. *CV_QUALIFIER_SEQ is filled in ! with the cv-qualifier-seq, or NULL_TREE, if there are no ! cv-qualifiers. Returns ERROR_MARK if an error occurred. */ ! static enum tree_code ! cp_parser_ptr_operator (cp_parser* parser, ! tree* type, ! tree* cv_qualifier_seq) { enum tree_code code = ERROR_MARK; cp_token *token; --- 11311,11327 ---- ptr-operator: & cv-qualifier-seq [opt] ! Returns INDIRECT_REF if a pointer, or pointer-to-member, was used. ! Returns ADDR_EXPR if a reference was used. In the case of a ! pointer-to-member, *TYPE is filled in with the TYPE containing the ! member. *CV_QUALS is filled in with the cv-qualifier-seq, or ! TYPE_UNQUALIFIED, if there are no cv-qualifiers. Returns ! ERROR_MARK if an error occurred. */ ! static enum tree_code ! cp_parser_ptr_operator (cp_parser* parser, ! tree* type, ! cp_cv_quals *cv_quals) { enum tree_code code = ERROR_MARK; cp_token *token; *************** cp_parser_ptr_operator (cp_parser* parse *** 10700,10706 **** /* Assume that it's not a pointer-to-member. */ *type = NULL_TREE; /* And that there are no cv-qualifiers. */ ! *cv_qualifier_seq = NULL_TREE; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); --- 11329,11335 ---- /* Assume that it's not a pointer-to-member. */ *type = NULL_TREE; /* And that there are no cv-qualifiers. */ ! *cv_quals = TYPE_UNQUALIFIED; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); *************** cp_parser_ptr_operator (cp_parser* parse *** 10717,10725 **** `&', if we are allowing GNU extensions. (The only qualifier that can legally appear after `&' is `restrict', but that is enforced during semantic analysis. */ ! if (code == INDIRECT_REF || cp_parser_allow_gnu_extensions_p (parser)) ! *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser); } else { --- 11346,11354 ---- `&', if we are allowing GNU extensions. (The only qualifier that can legally appear after `&' is `restrict', but that is enforced during semantic analysis. */ ! if (code == INDIRECT_REF || cp_parser_allow_gnu_extensions_p (parser)) ! *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); } else { *************** cp_parser_ptr_operator (cp_parser* parse *** 10749,10755 **** /* Indicate that the `*' operator was used. */ code = INDIRECT_REF; /* Look for the optional cv-qualifier-seq. */ ! *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser); } /* If that didn't work we don't have a ptr-operator. */ if (!cp_parser_parse_definitely (parser)) --- 11378,11384 ---- /* Indicate that the `*' operator was used. */ code = INDIRECT_REF; /* Look for the optional cv-qualifier-seq. */ ! *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); } /* If that didn't work we don't have a ptr-operator. */ if (!cp_parser_parse_definitely (parser)) *************** cp_parser_ptr_operator (cp_parser* parse *** 10762,10839 **** /* Parse an (optional) cv-qualifier-seq. cv-qualifier-seq: ! cv-qualifier cv-qualifier-seq [opt] ! ! Returns a TREE_LIST. The TREE_VALUE of each node is the ! representation of a cv-qualifier. */ ! ! static tree ! cp_parser_cv_qualifier_seq_opt (cp_parser* parser) ! { ! tree cv_qualifiers = NULL_TREE; ! ! while (true) ! { ! tree cv_qualifier; ! ! /* Look for the next cv-qualifier. */ ! cv_qualifier = cp_parser_cv_qualifier_opt (parser); ! /* If we didn't find one, we're done. */ ! if (!cv_qualifier) ! break; ! ! /* Add this cv-qualifier to the list. */ ! cv_qualifiers ! = tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers); ! } ! ! /* We built up the list in reverse order. */ ! return nreverse (cv_qualifiers); ! } ! ! /* Parse an (optional) cv-qualifier. cv-qualifier: const ! volatile GNU Extension: cv-qualifier: ! __restrict__ */ ! static tree ! cp_parser_cv_qualifier_opt (cp_parser* parser) { ! cp_token *token; ! tree cv_qualifier = NULL_TREE; ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* See if it's a cv-qualifier. */ ! switch (token->keyword) { ! case RID_CONST: ! case RID_VOLATILE: ! case RID_RESTRICT: ! /* Save the value of the token. */ ! cv_qualifier = token->value; ! /* Consume the token. */ ! cp_lexer_consume_token (parser->lexer); ! break; ! default: ! break; } ! return cv_qualifier; } /* Parse a declarator-id. declarator-id: id-expression ! :: [opt] nested-name-specifier [opt] type-name In the `id-expression' case, the value returned is as for cp_parser_id_expression if the id-expression was an unqualified-id. --- 11391,11464 ---- /* Parse an (optional) cv-qualifier-seq. cv-qualifier-seq: ! cv-qualifier cv-qualifier-seq [opt] cv-qualifier: const ! volatile GNU Extension: cv-qualifier: ! __restrict__ ! Returns a bitmask representing the cv-qualifiers. */ ! ! static cp_cv_quals ! cp_parser_cv_qualifier_seq_opt (cp_parser* parser) { ! cp_cv_quals cv_quals = TYPE_UNQUALIFIED; ! while (true) { ! cp_token *token; ! cp_cv_quals cv_qualifier; ! /* Peek at the next token. */ ! token = cp_lexer_peek_token (parser->lexer); ! /* See if it's a cv-qualifier. */ ! switch (token->keyword) ! { ! case RID_CONST: ! cv_qualifier = TYPE_QUAL_CONST; ! break; ! ! case RID_VOLATILE: ! cv_qualifier = TYPE_QUAL_VOLATILE; ! break; ! ! case RID_RESTRICT: ! cv_qualifier = TYPE_QUAL_RESTRICT; ! break; ! ! default: ! cv_qualifier = TYPE_UNQUALIFIED; ! break; ! } ! ! if (!cv_qualifier) ! break; ! ! if (cv_quals & cv_qualifier) ! { ! error ("duplicate cv-qualifier"); ! cp_lexer_purge_token (parser->lexer); ! } ! else ! { ! cp_lexer_consume_token (parser->lexer); ! cv_quals |= cv_qualifier; ! } } ! return cv_quals; } /* Parse a declarator-id. declarator-id: id-expression ! :: [opt] nested-name-specifier [opt] type-name In the `id-expression' case, the value returned is as for cp_parser_id_expression if the id-expression was an unqualified-id. *************** cp_parser_cv_qualifier_opt (cp_parser* p *** 10845,10852 **** static tree cp_parser_declarator_id (cp_parser* parser) { - tree id_expression; - /* The expression must be an id-expression. Assume that qualified names are the names of types so that: --- 11470,11475 ---- *************** cp_parser_declarator_id (cp_parser* pars *** 10861,10880 **** int S::R::i = 3; will work, too. */ ! id_expression = cp_parser_id_expression (parser, ! /*template_keyword_p=*/false, ! /*check_dependency_p=*/false, ! /*template_p=*/NULL, ! /*declarator_p=*/true); ! /* If the name was qualified, create a SCOPE_REF to represent ! that. */ ! if (parser->scope) ! { ! id_expression = build_nt (SCOPE_REF, parser->scope, id_expression); ! parser->scope = NULL_TREE; ! } ! ! return id_expression; } /* Parse a type-id. --- 11484,11494 ---- int S::R::i = 3; will work, too. */ ! return cp_parser_id_expression (parser, ! /*template_keyword_p=*/false, ! /*check_dependency_p=*/false, ! /*template_p=*/NULL, ! /*declarator_p=*/true); } /* Parse a type-id. *************** cp_parser_declarator_id (cp_parser* pars *** 10887,10914 **** static tree cp_parser_type_id (cp_parser* parser) { ! tree type_specifier_seq; ! tree abstract_declarator; /* Parse the type-specifier-seq. */ ! type_specifier_seq ! = cp_parser_type_specifier_seq (parser); ! if (type_specifier_seq == error_mark_node) return error_mark_node; /* There might or might not be an abstract declarator. */ cp_parser_parse_tentatively (parser); /* Look for the declarator. */ ! abstract_declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL, /*parenthesized_p=*/NULL, /*member_p=*/false); /* Check to see if there really was a declarator. */ if (!cp_parser_parse_definitely (parser)) ! abstract_declarator = NULL_TREE; ! return groktypename (build_tree_list (type_specifier_seq, ! abstract_declarator)); } /* Parse a type-specifier-seq. --- 11501,11527 ---- static tree cp_parser_type_id (cp_parser* parser) { ! cp_decl_specifier_seq type_specifier_seq; ! cp_declarator *abstract_declarator; /* Parse the type-specifier-seq. */ ! cp_parser_type_specifier_seq (parser, /*is_condition=*/false, ! &type_specifier_seq); ! if (type_specifier_seq.type == error_mark_node) return error_mark_node; /* There might or might not be an abstract declarator. */ cp_parser_parse_tentatively (parser); /* Look for the declarator. */ ! abstract_declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL, /*parenthesized_p=*/NULL, /*member_p=*/false); /* Check to see if there really was a declarator. */ if (!cp_parser_parse_definitely (parser)) ! abstract_declarator = NULL; ! return groktypename (&type_specifier_seq, abstract_declarator); } /* Parse a type-specifier-seq. *************** cp_parser_type_id (cp_parser* parser) *** 10921,10976 **** type-specifier-seq: attributes type-specifier-seq [opt] ! Returns a TREE_LIST. Either the TREE_VALUE of each node is a ! type-specifier, or the TREE_PURPOSE is a list of attributes. */ ! static tree ! cp_parser_type_specifier_seq (cp_parser* parser) { bool seen_type_specifier = false; ! tree type_specifier_seq = NULL_TREE; /* Parse the type-specifiers and attributes. */ while (true) { tree type_specifier; /* Check for attributes first. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) { ! type_specifier_seq = tree_cons (cp_parser_attributes_opt (parser), ! NULL_TREE, ! type_specifier_seq); continue; } - /* After the first type-specifier, others are optional. */ - if (seen_type_specifier) - cp_parser_parse_tentatively (parser); /* Look for the type-specifier. */ ! type_specifier = cp_parser_type_specifier (parser, ! CP_PARSER_FLAGS_NONE, ! /*is_friend=*/false, /*is_declaration=*/false, NULL, ! NULL); ! /* If the first type-specifier could not be found, this is not a ! type-specifier-seq at all. */ ! if (!seen_type_specifier && type_specifier == error_mark_node) ! return error_mark_node; ! /* If subsequent type-specifiers could not be found, the ! type-specifier-seq is complete. */ ! else if (seen_type_specifier && !cp_parser_parse_definitely (parser)) ! break; - /* Add the new type-specifier to the list. */ - type_specifier_seq - = tree_cons (NULL_TREE, type_specifier, type_specifier_seq); seen_type_specifier = true; } ! /* We built up the list in reverse order. */ ! return nreverse (type_specifier_seq); } /* Parse a parameter-declaration-clause. --- 11534,11614 ---- type-specifier-seq: attributes type-specifier-seq [opt] ! If IS_CONDITION is true, we are at the start of a "condition", ! e.g., we've just seen "if (". ! Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */ ! ! static void ! cp_parser_type_specifier_seq (cp_parser* parser, ! bool is_condition, ! cp_decl_specifier_seq *type_specifier_seq) { bool seen_type_specifier = false; ! cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL; ! ! /* Clear the TYPE_SPECIFIER_SEQ. */ ! clear_decl_specs (type_specifier_seq); /* Parse the type-specifiers and attributes. */ while (true) { tree type_specifier; + bool is_cv_qualifier; /* Check for attributes first. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) { ! type_specifier_seq->attributes = ! chainon (type_specifier_seq->attributes, ! cp_parser_attributes_opt (parser)); continue; } /* Look for the type-specifier. */ ! type_specifier = cp_parser_type_specifier (parser, ! flags, ! type_specifier_seq, /*is_declaration=*/false, NULL, ! &is_cv_qualifier); ! if (!type_specifier) ! { ! /* If the first type-specifier could not be found, this is not a ! type-specifier-seq at all. */ ! if (!seen_type_specifier) ! { ! cp_parser_error (parser, "expected type-specifier"); ! type_specifier_seq->type = error_mark_node; ! return; ! } ! /* If subsequent type-specifiers could not be found, the ! type-specifier-seq is complete. */ ! break; ! } seen_type_specifier = true; + /* The standard says that a condition can be: + + type-specifier-seq declarator = assignment-expression + + However, given: + + struct S {}; + if (int S = ...) + + we should treat the "S" as a declarator, not as a + type-specifier. The standard doesn't say that explicitly for + type-specifier-seq, but it does say that for + decl-specifier-seq in an ordinary declaration. Perhaps it + would be clearer just to allow a decl-specifier-seq here, and + then add a semantic restriction that if any decl-specifiers + that are not type-specifiers appear, the program is invalid. */ + if (is_condition && !is_cv_qualifier) + flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; } ! return; } /* Parse a parameter-declaration-clause. *************** cp_parser_type_specifier_seq (cp_parser* *** 10979,10997 **** parameter-declaration-list [opt] ... [opt] parameter-declaration-list , ... ! Returns a representation for the parameter declarations. Each node ! is a TREE_LIST. (See cp_parser_parameter_declaration for the exact ! representation.) If the parameter-declaration-clause ends with an ! ellipsis, PARMLIST_ELLIPSIS_P will hold of the first node in the ! list. A return value of NULL_TREE indicates a ! parameter-declaration-clause consisting only of an ellipsis. */ ! static tree cp_parser_parameter_declaration_clause (cp_parser* parser) { ! tree parameters; cp_token *token; bool ellipsis_p; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); --- 11617,11633 ---- parameter-declaration-list [opt] ... [opt] parameter-declaration-list , ... ! Returns a representation for the parameter declarations. A return ! value of NULL indicates a parameter-declaration-clause consisting ! only of an ellipsis. */ ! static cp_parameter_declarator * cp_parser_parameter_declaration_clause (cp_parser* parser) { ! cp_parameter_declarator *parameters; cp_token *token; bool ellipsis_p; + bool is_error; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); *************** cp_parser_parameter_declaration_clause ( *** 11000,11006 **** { /* Consume the `...' token. */ cp_lexer_consume_token (parser->lexer); ! return NULL_TREE; } else if (token->type == CPP_CLOSE_PAREN) /* There are no parameters. */ --- 11636,11642 ---- { /* Consume the `...' token. */ cp_lexer_consume_token (parser->lexer); ! return NULL; } else if (token->type == CPP_CLOSE_PAREN) /* There are no parameters. */ *************** cp_parser_parameter_declaration_clause ( *** 11008,11036 **** #ifndef NO_IMPLICIT_EXTERN_C if (in_system_header && current_class_type == NULL && current_lang_name == lang_name_c) ! return NULL_TREE; else #endif ! return void_list_node; } /* Check for `(void)', too, which is a special case. */ else if (token->keyword == RID_VOID ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_CLOSE_PAREN)) { /* Consume the `void' token. */ cp_lexer_consume_token (parser->lexer); /* There are no parameters. */ ! return void_list_node; } ! /* Parse the parameter-declaration-list. */ ! parameters = cp_parser_parameter_declaration_list (parser); /* If a parse error occurred while parsing the parameter-declaration-list, then the entire parameter-declaration-clause is erroneous. */ ! if (parameters == error_mark_node) ! return error_mark_node; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); --- 11644,11672 ---- #ifndef NO_IMPLICIT_EXTERN_C if (in_system_header && current_class_type == NULL && current_lang_name == lang_name_c) ! return NULL; else #endif ! return no_parameters; } /* Check for `(void)', too, which is a special case. */ else if (token->keyword == RID_VOID ! && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_CLOSE_PAREN)) { /* Consume the `void' token. */ cp_lexer_consume_token (parser->lexer); /* There are no parameters. */ ! return no_parameters; } ! /* Parse the parameter-declaration-list. */ ! parameters = cp_parser_parameter_declaration_list (parser, &is_error); /* If a parse error occurred while parsing the parameter-declaration-list, then the entire parameter-declaration-clause is erroneous. */ ! if (is_error) ! return NULL; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); *************** cp_parser_parameter_declaration_clause ( *** 11040,11049 **** /* Consume the `,'. */ cp_lexer_consume_token (parser->lexer); /* Expect an ellipsis. */ ! ellipsis_p = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL); } ! /* It might also be `...' if the optional trailing `,' was omitted. */ else if (token->type == CPP_ELLIPSIS) { --- 11676,11685 ---- /* Consume the `,'. */ cp_lexer_consume_token (parser->lexer); /* Expect an ellipsis. */ ! ellipsis_p = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL); } ! /* It might also be `...' if the optional trailing `,' was omitted. */ else if (token->type == CPP_ELLIPSIS) { *************** cp_parser_parameter_declaration_clause ( *** 11056,11062 **** ellipsis_p = false; /* Finish the parameter list. */ ! return finish_parmlist (parameters, ellipsis_p); } /* Parse a parameter-declaration-list. --- 11692,11701 ---- ellipsis_p = false; /* Finish the parameter list. */ ! if (parameters && ellipsis_p) ! parameters->ellipsis_p = true; ! ! return parameters; } /* Parse a parameter-declaration-list. *************** cp_parser_parameter_declaration_clause ( *** 11067,11100 **** Returns a representation of the parameter-declaration-list, as for cp_parser_parameter_declaration_clause. However, the ! `void_list_node' is never appended to the list. */ ! static tree ! cp_parser_parameter_declaration_list (cp_parser* parser) { ! tree parameters = NULL_TREE; /* Look for more parameters. */ while (true) { ! tree parameter; bool parenthesized_p; /* Parse the parameter. */ ! parameter ! = cp_parser_parameter_declaration (parser, /*template_parm_p=*/false, &parenthesized_p); /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ ! if (parameter == error_mark_node) { ! parameters = error_mark_node; break; } /* Add the new parameter to the list. */ ! TREE_CHAIN (parameter) = parameters; ! parameters = parameter; /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) --- 11706,11745 ---- Returns a representation of the parameter-declaration-list, as for cp_parser_parameter_declaration_clause. However, the ! `void_list_node' is never appended to the list. Upon return, ! *IS_ERROR will be true iff an error occurred. */ ! static cp_parameter_declarator * ! cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { ! cp_parameter_declarator *parameters = NULL; ! cp_parameter_declarator **tail = ¶meters; ! ! /* Assume all will go well. */ ! *is_error = false; /* Look for more parameters. */ while (true) { ! cp_parameter_declarator *parameter; bool parenthesized_p; /* Parse the parameter. */ ! parameter ! = cp_parser_parameter_declaration (parser, /*template_parm_p=*/false, &parenthesized_p); /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ ! if (!parameter) { ! *is_error = true; ! parameters = NULL; break; } /* Add the new parameter to the list. */ ! *tail = parameter; ! tail = ¶meter->next; /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) *************** cp_parser_parameter_declaration_list (cp *** 11116,11125 **** /* When parsing something like: int i(float f, double d) ! we can tell after seeing the declaration for "f" that we are not looking at an initialization of a variable "i", ! but rather at the declaration of a function "i". Due to the fact that the parsing of template arguments (as specified to a template-id) requires backtracking we --- 11761,11770 ---- /* When parsing something like: int i(float f, double d) ! we can tell after seeing the declaration for "f" that we are not looking at an initialization of a variable "i", ! but rather at the declaration of a function "i". Due to the fact that the parsing of template arguments (as specified to a template-id) requires backtracking we *************** cp_parser_parameter_declaration_list (cp *** 11127,11134 **** list. */ if (!parser->in_template_argument_list_p && !parser->in_type_id_in_expr_p ! && cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser) /* However, a parameter-declaration of the form "foat(f)" (which is a valid declaration of a parameter "f") can also be interpreted as an --- 11772,11778 ---- list. */ if (!parser->in_template_argument_list_p && !parser->in_type_id_in_expr_p ! && cp_parser_uncommitted_to_tentative_parse_p (parser) /* However, a parameter-declaration of the form "foat(f)" (which is a valid declaration of a parameter "f") can also be interpreted as an *************** cp_parser_parameter_declaration_list (cp *** 11138,11147 **** } else { ! cp_parser_error (parser, "expected `,' or `...'"); ! if (!cp_parser_parsing_tentatively (parser) ! || cp_parser_committed_to_tentative_parse (parser)) ! cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/false); --- 11782,11790 ---- } else { ! cp_parser_error (parser, "expected %<,%> or %<...%>"); ! if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) ! cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/false); *************** cp_parser_parameter_declaration_list (cp *** 11149,11156 **** } } ! /* We built up the list in reverse order; straighten it out now. */ ! return nreverse (parameters); } /* Parse a parameter declaration. --- 11792,11798 ---- } } ! return parameters; } /* Parse a parameter declaration. *************** cp_parser_parameter_declaration_list (cp *** 11166,11192 **** token encountered during the parsing of the assignment-expression is not interpreted as a greater-than operator.) ! Returns a TREE_LIST representing the parameter-declaration. The ! TREE_PURPOSE is the default argument expression, or NULL_TREE if ! there is no default argument. The TREE_VALUE is a representation ! of the decl-specifier-seq and declarator. In particular, the ! TREE_VALUE will be a TREE_LIST whose TREE_PURPOSE represents the ! decl-specifier-seq and whose TREE_VALUE represents the declarator. ! If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff ! the declarator is of the form "(p)". */ ! static tree ! cp_parser_parameter_declaration (cp_parser *parser, bool template_parm_p, bool *parenthesized_p) { int declares_class_or_enum; bool greater_than_is_operator_p; ! tree decl_specifiers; ! tree attributes; ! tree declarator; tree default_argument; - tree parameter; cp_token *token; const char *saved_message; --- 11808,11827 ---- token encountered during the parsing of the assignment-expression is not interpreted as a greater-than operator.) ! Returns a representation of the parameter, or NULL if an error ! occurs. If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to ! true iff the declarator is of the form "(p)". */ ! static cp_parameter_declarator * ! cp_parser_parameter_declaration (cp_parser *parser, bool template_parm_p, bool *parenthesized_p) { int declares_class_or_enum; bool greater_than_is_operator_p; ! cp_decl_specifier_seq decl_specifiers; ! cp_declarator *declarator; tree default_argument; cp_token *token; const char *saved_message; *************** cp_parser_parameter_declaration (cp_pars *** 11202,11235 **** /* Type definitions may not appear in parameter types. */ saved_message = parser->type_definition_forbidden_message; ! parser->type_definition_forbidden_message = "types may not be defined in parameter types"; /* Parse the declaration-specifiers. */ ! decl_specifiers ! = cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_NONE, ! &attributes, ! &declares_class_or_enum); /* If an error occurred, there's no reason to attempt to parse the rest of the declaration. */ if (cp_parser_error_occurred (parser)) { parser->type_definition_forbidden_message = saved_message; ! return error_mark_node; } /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If the next token is a `)', `,', `=', `>', or `...', then there is no declarator. */ ! if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA || token->type == CPP_EQ || token->type == CPP_ELLIPSIS || token->type == CPP_GREATER) { ! declarator = NULL_TREE; if (parenthesized_p) *parenthesized_p = false; } --- 11837,11869 ---- /* Type definitions may not appear in parameter types. */ saved_message = parser->type_definition_forbidden_message; ! parser->type_definition_forbidden_message = "types may not be defined in parameter types"; /* Parse the declaration-specifiers. */ ! cp_parser_decl_specifier_seq (parser, ! CP_PARSER_FLAGS_NONE, ! &decl_specifiers, ! &declares_class_or_enum); /* If an error occurred, there's no reason to attempt to parse the rest of the declaration. */ if (cp_parser_error_occurred (parser)) { parser->type_definition_forbidden_message = saved_message; ! return NULL; } /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If the next token is a `)', `,', `=', `>', or `...', then there is no declarator. */ ! if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA || token->type == CPP_EQ || token->type == CPP_ELLIPSIS || token->type == CPP_GREATER) { ! declarator = NULL; if (parenthesized_p) *parenthesized_p = false; } *************** cp_parser_parameter_declaration (cp_pars *** 11238,11244 **** { bool saved_default_arg_ok_p = parser->default_arg_ok_p; parser->default_arg_ok_p = false; ! /* After seeing a decl-specifier-seq, if the next token is not a "(", there is no possibility that the code is a valid expression. Therefore, if parsing tentatively, we commit at --- 11872,11878 ---- { bool saved_default_arg_ok_p = parser->default_arg_ok_p; parser->default_arg_ok_p = false; ! /* After seeing a decl-specifier-seq, if the next token is not a "(", there is no possibility that the code is a valid expression. Therefore, if parsing tentatively, we commit at *************** cp_parser_parameter_declaration (cp_pars *** 11252,11259 **** function-type (taking a "char" as a parameter) or a cast of some object of type "char" to "int". */ && !parser->in_type_id_in_expr_p ! && cp_parser_parsing_tentatively (parser) ! && !cp_parser_committed_to_tentative_parse (parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) cp_parser_commit_to_tentative_parse (parser); /* Parse the declarator. */ --- 11886,11892 ---- function-type (taking a "char" as a parameter) or a cast of some object of type "char" to "int". */ && !parser->in_type_id_in_expr_p ! && cp_parser_uncommitted_to_tentative_parse_p (parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) cp_parser_commit_to_tentative_parse (parser); /* Parse the declarator. */ *************** cp_parser_parameter_declaration (cp_pars *** 11264,11270 **** /*member_p=*/false); parser->default_arg_ok_p = saved_default_arg_ok_p; /* After the declarator, allow more attributes. */ ! attributes = chainon (attributes, cp_parser_attributes_opt (parser)); } /* The restriction on defining new types applies only to the type --- 11897,11905 ---- /*member_p=*/false); parser->default_arg_ok_p = saved_default_arg_ok_p; /* After the declarator, allow more attributes. */ ! decl_specifiers.attributes ! = chainon (decl_specifiers.attributes, ! cp_parser_attributes_opt (parser)); } /* The restriction on defining new types applies only to the type *************** cp_parser_parameter_declaration (cp_pars *** 11280,11301 **** /* If we are defining a class, then the tokens that make up the default argument must be saved and processed later. */ ! if (!template_parm_p && at_class_scope_p () && TYPE_BEING_DEFINED (current_class_type)) { unsigned depth = 0; ! ! /* Create a DEFAULT_ARG to represented the unparsed default ! argument. */ ! default_argument = make_node (DEFAULT_ARG); ! DEFARG_TOKENS (default_argument) = cp_token_cache_new (); /* Add tokens until we have processed the entire default ! argument. */ while (true) { bool done = false; - cp_token *token; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); --- 11915,11933 ---- /* If we are defining a class, then the tokens that make up the default argument must be saved and processed later. */ ! if (!template_parm_p && at_class_scope_p () && TYPE_BEING_DEFINED (current_class_type)) { unsigned depth = 0; ! cp_token *first_token; ! cp_token *token; /* Add tokens until we have processed the entire default ! argument. We add the range [first_token, token). */ ! first_token = cp_lexer_peek_token (parser->lexer); while (true) { bool done = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); *************** cp_parser_parameter_declaration (cp_pars *** 11345,11351 **** case CPP_NAME: case CPP_SCOPE: /* In these cases, we should look for template-ids. ! For example, if the default argument is `X()', we need to do name lookup to figure out whether or not `X' is a template; if so, the `,' does not end the default argument. --- 11977,11983 ---- case CPP_NAME: case CPP_SCOPE: /* In these cases, we should look for template-ids. ! For example, if the default argument is `X()', we need to do name lookup to figure out whether or not `X' is a template; if so, the `,' does not end the default argument. *************** cp_parser_parameter_declaration (cp_pars *** 11360,11371 **** /* If we've reached the end, stop. */ if (done) break; ! /* Add the token to the token block. */ token = cp_lexer_consume_token (parser->lexer); - cp_token_cache_push_token (DEFARG_TOKENS (default_argument), - token); } } /* Outside of a class definition, we can just parse the assignment-expression. */ --- 11992,12007 ---- /* If we've reached the end, stop. */ if (done) break; ! /* Add the token to the token block. */ token = cp_lexer_consume_token (parser->lexer); } + + /* Create a DEFAULT_ARG to represented the unparsed default + argument. */ + default_argument = make_node (DEFAULT_ARG); + DEFARG_TOKENS (default_argument) + = cp_token_cache_new (first_token, token); } /* Outside of a class definition, we can just parse the assignment-expression. */ *************** cp_parser_parameter_declaration (cp_pars *** 11375,11395 **** /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is set correctly. */ ! saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = greater_than_is_operator_p; /* Local variable names (and the `this' keyword) may not appear in a default argument. */ ! saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; parser->local_variables_forbidden_p = true; /* Parse the assignment-expression. */ ! default_argument = cp_parser_assignment_expression (parser); /* Restore saved state. */ ! parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; ! parser->local_variables_forbidden_p ! = saved_local_variables_forbidden_p; } if (!parser->default_arg_ok_p) { --- 12011,12032 ---- /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is set correctly. */ ! saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = greater_than_is_operator_p; /* Local variable names (and the `this' keyword) may not appear in a default argument. */ ! saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; parser->local_variables_forbidden_p = true; /* Parse the assignment-expression. */ ! default_argument ! = cp_parser_assignment_expression (parser, /*cast_p=*/false); /* Restore saved state. */ ! parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; ! parser->local_variables_forbidden_p ! = saved_local_variables_forbidden_p; } if (!parser->default_arg_ok_p) { *************** cp_parser_parameter_declaration (cp_pars *** 11404,11418 **** } else default_argument = NULL_TREE; - - /* Create the representation of the parameter. */ - if (attributes) - decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers); - parameter = build_tree_list (default_argument, - build_tree_list (decl_specifiers, - declarator)); ! return parameter; } /* Parse a function-body. --- 12041,12050 ---- } else default_argument = NULL_TREE; ! return make_parameter_declarator (&decl_specifiers, ! declarator, ! default_argument); } /* Parse a function-body. *************** cp_parser_parameter_declaration (cp_pars *** 11423,11429 **** static void cp_parser_function_body (cp_parser *parser) { ! cp_parser_compound_statement (parser, false); } /* Parse a ctor-initializer-opt followed by a function-body. Return --- 12055,12061 ---- static void cp_parser_function_body (cp_parser *parser) { ! cp_parser_compound_statement (parser, NULL, false); } /* Parse a ctor-initializer-opt followed by a function-body. Return *************** cp_parser_ctor_initializer_opt_and_funct *** 11451,11460 **** initializer: = initializer-clause ! ( expression-list ) Returns a expression representing the initializer. If no ! initializer is present, NULL_TREE is returned. *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )' production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is --- 12083,12092 ---- initializer: = initializer-clause ! ( expression-list ) Returns a expression representing the initializer. If no ! initializer is present, NULL_TREE is returned. *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )' production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is *************** cp_parser_initializer (cp_parser* parser *** 11487,11492 **** --- 12119,12125 ---- } else if (token->type == CPP_OPEN_PAREN) init = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, non_constant_p); else { *************** cp_parser_initializer (cp_parser* parser *** 11498,11514 **** return init; } ! /* Parse an initializer-clause. initializer-clause: assignment-expression { initializer-list , [opt] } { } ! Returns an expression representing the initializer. If the `assignment-expression' production is used the value ! returned is simply a representation for the expression. Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be the elements of the initializer-list (or NULL_TREE, if the last --- 12131,12147 ---- return init; } ! /* Parse an initializer-clause. initializer-clause: assignment-expression { initializer-list , [opt] } { } ! Returns an expression representing the initializer. If the `assignment-expression' production is used the value ! returned is simply a representation for the expression. Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be the elements of the initializer-list (or NULL_TREE, if the last *************** cp_parser_initializer (cp_parser* parser *** 11520,11568 **** static tree cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) { ! tree initializer = NULL_TREE; /* If it is not a `{', then we are looking at an assignment-expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) { ! /* Speed up common initializers (simply a literal). */ ! cp_token* token = cp_lexer_peek_token (parser->lexer); ! cp_token* token2 = cp_lexer_peek_nth_token (parser->lexer, 2); ! ! if (token2->type == CPP_COMMA) ! switch (token->type) ! { ! case CPP_CHAR: ! case CPP_WCHAR: ! case CPP_NUMBER: ! token = cp_lexer_consume_token (parser->lexer); ! initializer = token->value; ! break; ! ! case CPP_STRING: ! case CPP_WSTRING: ! token = cp_lexer_consume_token (parser->lexer); ! if (TREE_CHAIN (token->value)) ! initializer = TREE_CHAIN (token->value); ! else ! initializer = token->value; ! break; ! ! default: ! break; ! } ! ! /* Otherwise, fall back to the generic assignment expression. */ ! if (!initializer) ! { ! initializer ! = cp_parser_constant_expression (parser, ! /*allow_non_constant_p=*/true, ! non_constant_p); ! if (!*non_constant_p) ! initializer = fold_non_dependent_expr (initializer); ! } } else { --- 12153,12173 ---- static tree cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) { ! tree initializer; ! ! /* Assume the expression is constant. */ ! *non_constant_p = false; /* If it is not a `{', then we are looking at an assignment-expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) { ! initializer ! = cp_parser_constant_expression (parser, ! /*allow_non_constant_p=*/true, ! non_constant_p); ! if (!*non_constant_p) ! initializer = fold_non_dependent_expr (initializer); } else { *************** cp_parser_initializer_clause (cp_parser* *** 11570,11579 **** cp_lexer_consume_token (parser->lexer); /* Create a CONSTRUCTOR to represent the braced-initializer. */ initializer = make_node (CONSTRUCTOR); - /* Mark it with TREE_HAS_CONSTRUCTOR. This should not be - necessary, but check_initializer depends upon it, for - now. */ - TREE_HAS_CONSTRUCTOR (initializer) = 1; /* If it's not a `}', then there is a non-trivial initializer. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) { --- 12175,12180 ---- *************** cp_parser_initializer_clause (cp_parser* *** 11598,11604 **** initializer-list , initializer-clause GNU Extension: ! initializer-list: identifier : initializer-clause initializer-list, identifier : initializer-clause --- 12199,12205 ---- initializer-list , initializer-clause GNU Extension: ! initializer-list: identifier : initializer-clause initializer-list, identifier : initializer-clause *************** cp_parser_initializer_list (cp_parser* p *** 11640,11646 **** identifier = NULL_TREE; /* Parse the initializer. */ ! initializer = cp_parser_initializer_clause (parser, &clause_non_constant_p); /* If any clause is non-constant, so is the entire initializer. */ if (clause_non_constant_p) --- 12241,12247 ---- identifier = NULL_TREE; /* Parse the initializer. */ ! initializer = cp_parser_initializer_clause (parser, &clause_non_constant_p); /* If any clause is non-constant, so is the entire initializer. */ if (clause_non_constant_p) *************** cp_parser_initializer_list (cp_parser* p *** 11682,11700 **** to indicate that names looked up in dependent types should be assumed to be types. TEMPLATE_KEYWORD_P is true iff the `template' keyword has been used to indicate that the name that appears next ! is a template. TYPE_P is true iff the next name should be treated ! as class-name, even if it is declared to be some other kind of name ! as well. If CHECK_DEPENDENCY_P is FALSE, names are looked up in ! dependent scopes. If CLASS_HEAD_P is TRUE, this class is the class ! being defined in a class-head. Returns the TYPE_DECL representing the class. */ static tree ! cp_parser_class_name (cp_parser *parser, ! bool typename_keyword_p, ! bool template_keyword_p, ! bool type_p, bool check_dependency_p, bool class_head_p, bool is_declaration) --- 12283,12300 ---- to indicate that names looked up in dependent types should be assumed to be types. TEMPLATE_KEYWORD_P is true iff the `template' keyword has been used to indicate that the name that appears next ! is a template. TAG_TYPE indicates the explicit tag given before ! the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are ! looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class ! is the class being defined in a class-head. Returns the TYPE_DECL representing the class. */ static tree ! cp_parser_class_name (cp_parser *parser, ! bool typename_keyword_p, ! bool template_keyword_p, ! enum tag_types tag_type, bool check_dependency_p, bool class_head_p, bool is_declaration) *************** cp_parser_class_name (cp_parser *parser, *** 11711,11730 **** cp_parser_error (parser, "expected class-name"); return error_mark_node; } ! /* PARSER->SCOPE can be cleared when parsing the template-arguments to a template-id, so we save it here. */ scope = parser->scope; if (scope == error_mark_node) return error_mark_node; ! /* Any name names a type if we're following the `typename' keyword in a qualified name where the enclosing scope is type-dependent. */ typename_p = (typename_keyword_p && scope && TYPE_P (scope) && dependent_type_p (scope)); /* Handle the common case (an identifier, but not a template-id) efficiently. */ ! if (token->type == CPP_NAME && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) { tree identifier; --- 12311,12330 ---- cp_parser_error (parser, "expected class-name"); return error_mark_node; } ! /* PARSER->SCOPE can be cleared when parsing the template-arguments to a template-id, so we save it here. */ scope = parser->scope; if (scope == error_mark_node) return error_mark_node; ! /* Any name names a type if we're following the `typename' keyword in a qualified name where the enclosing scope is type-dependent. */ typename_p = (typename_keyword_p && scope && TYPE_P (scope) && dependent_type_p (scope)); /* Handle the common case (an identifier, but not a template-id) efficiently. */ ! if (token->type == CPP_NAME && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) { tree identifier; *************** cp_parser_class_name (cp_parser *parser, *** 11750,11762 **** resolution operator, object, function, and enumerator names are ignored. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) ! type_p = true; /* Look up the name. */ ! decl = cp_parser_lookup_name (parser, identifier, ! type_p, /*is_template=*/false, /*is_namespace=*/false, ! check_dependency_p); } } else --- 12350,12363 ---- resolution operator, object, function, and enumerator names are ignored. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) ! tag_type = typename_type; /* Look up the name. */ ! decl = cp_parser_lookup_name (parser, identifier, ! tag_type, /*is_template=*/false, /*is_namespace=*/false, ! check_dependency_p, ! /*ambiguous_p=*/NULL); } } else *************** cp_parser_class_name (cp_parser *parser, *** 11774,11801 **** /* If this is a typename, create a TYPENAME_TYPE. */ if (typename_p && decl != error_mark_node) { ! decl = make_typename_type (scope, decl, /*complain=*/1); if (decl != error_mark_node) decl = TYPE_NAME (decl); } /* Check to see that it is really the name of a class. */ ! if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) /* Situations like this: template struct A { ! typename T::template X::I i; }; are problematic. Is `T::template X' a class-name? The standard does not seem to be definitive, but there is no other valid interpretation of the following `::'. Therefore, those names are considered class-names. */ ! decl = TYPE_NAME (make_typename_type (scope, decl, tf_error)); else if (decl == error_mark_node || TREE_CODE (decl) != TYPE_DECL || !IS_AGGR_TYPE (TREE_TYPE (decl))) { cp_parser_error (parser, "expected class-name"); --- 12375,12403 ---- /* If this is a typename, create a TYPENAME_TYPE. */ if (typename_p && decl != error_mark_node) { ! decl = make_typename_type (scope, decl, typename_type, /*complain=*/1); if (decl != error_mark_node) decl = TYPE_NAME (decl); } /* Check to see that it is really the name of a class. */ ! if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) /* Situations like this: template struct A { ! typename T::template X::I i; }; are problematic. Is `T::template X' a class-name? The standard does not seem to be definitive, but there is no other valid interpretation of the following `::'. Therefore, those names are considered class-names. */ ! decl = TYPE_NAME (make_typename_type (scope, decl, tag_type, tf_error)); else if (decl == error_mark_node || TREE_CODE (decl) != TYPE_DECL + || TREE_TYPE (decl) == error_mark_node || !IS_AGGR_TYPE (TREE_TYPE (decl))) { cp_parser_error (parser, "expected class-name"); *************** cp_parser_class_specifier (cp_parser* pa *** 11817,11827 **** { cp_token *token; tree type; ! tree attributes; int has_trailing_semicolon; bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; ! bool pop_p = false; tree scope = NULL_TREE; push_deferring_access_checks (dk_no_deferred); --- 12419,12429 ---- { cp_token *token; tree type; ! tree attributes = NULL_TREE; int has_trailing_semicolon; bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; ! tree old_scope = NULL_TREE; tree scope = NULL_TREE; push_deferring_access_checks (dk_no_deferred); *************** cp_parser_class_specifier (cp_parser* pa *** 11852,11874 **** ++parser->num_classes_being_defined; /* Inside the class, surrounding template-parameter-lists do not apply. */ ! saved_num_template_parameter_lists ! = parser->num_template_parameter_lists; parser->num_template_parameter_lists = 0; /* Start the class. */ if (nested_name_specifier_p) { scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); ! pop_p = push_scope (scope); } type = begin_class_definition (type); if (type == error_mark_node) /* If the type is erroneous, skip the entire body of the class. */ cp_parser_skip_to_closing_brace (parser); else /* Parse the member-specification. */ cp_parser_member_specification_opt (parser); /* Look for the trailing `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); /* We get better error messages by noticing a common problem: a --- 12454,12478 ---- ++parser->num_classes_being_defined; /* Inside the class, surrounding template-parameter-lists do not apply. */ ! saved_num_template_parameter_lists ! = parser->num_template_parameter_lists; parser->num_template_parameter_lists = 0; /* Start the class. */ if (nested_name_specifier_p) { scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); ! old_scope = push_inner_scope (scope); } type = begin_class_definition (type); + if (type == error_mark_node) /* If the type is erroneous, skip the entire body of the class. */ cp_parser_skip_to_closing_brace (parser); else /* Parse the member-specification. */ cp_parser_member_specification_opt (parser); + /* Look for the trailing `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); /* We get better error messages by noticing a common problem: a *************** cp_parser_class_specifier (cp_parser* pa *** 11883,11890 **** } if (type != error_mark_node) type = finish_struct (type, attributes); ! if (pop_p) ! pop_scope (scope); /* If this class is not itself within the scope of another class, then we need to parse the bodies of all of the queued function definitions. Note that the queued functions defined in a class --- 12487,12494 ---- } if (type != error_mark_node) type = finish_struct (type, attributes); ! if (nested_name_specifier_p) ! pop_inner_scope (old_scope, scope); /* If this class is not itself within the scope of another class, then we need to parse the bodies of all of the queued function definitions. Note that the queued functions defined in a class *************** cp_parser_class_specifier (cp_parser* pa *** 11905,11921 **** struct A::B { void f() { } }; there is no need to delay the parsing of `A::B::f'. */ ! if (--parser->num_classes_being_defined == 0) { tree queue_entry; tree fn; /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. This two-phased approach handles cases like: ! ! struct S { ! void f() { g(); } void g(int i = 3); }; --- 12509,12527 ---- struct A::B { void f() { } }; there is no need to delay the parsing of `A::B::f'. */ ! if (--parser->num_classes_being_defined == 0) { tree queue_entry; tree fn; + tree class_type = NULL_TREE; + tree pushed_scope = NULL_TREE; /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. This two-phased approach handles cases like: ! ! struct S { ! void f() { g(); } void g(int i = 3); }; *************** cp_parser_class_specifier (cp_parser* pa *** 11927,11940 **** = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues))) { fn = TREE_VALUE (queue_entry); - /* Make sure that any template parameters are in scope. */ - maybe_begin_member_template_processing (fn); /* If there are default arguments that have not yet been processed, take care of them now. */ cp_parser_late_parsing_default_args (parser, fn); /* Remove any template parameters from the symbol table. */ maybe_end_member_template_processing (); } /* Now parse the body of the functions. */ for (TREE_VALUE (parser->unparsed_functions_queues) = nreverse (TREE_VALUE (parser->unparsed_functions_queues)); --- 12533,12556 ---- = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues))) { fn = TREE_VALUE (queue_entry); /* If there are default arguments that have not yet been processed, take care of them now. */ + if (class_type != TREE_PURPOSE (queue_entry)) + { + if (pushed_scope) + pop_scope (pushed_scope); + class_type = TREE_PURPOSE (queue_entry); + pushed_scope = push_scope (class_type); + } + /* Make sure that any template parameters are in scope. */ + maybe_begin_member_template_processing (fn); + /* Parse the default argument expressions. */ cp_parser_late_parsing_default_args (parser, fn); /* Remove any template parameters from the symbol table. */ maybe_end_member_template_processing (); } + if (pushed_scope) + pop_scope (pushed_scope); /* Now parse the body of the functions. */ for (TREE_VALUE (parser->unparsed_functions_queues) = nreverse (TREE_VALUE (parser->unparsed_functions_queues)); *************** cp_parser_class_specifier (cp_parser* pa *** 11952,11958 **** cp_parser_late_parsing_for_member (parser, fn); function_depth--; } - } /* Put back any saved access checks. */ --- 12568,12573 ---- *************** cp_parser_class_specifier (cp_parser* pa *** 11970,11998 **** class-head: class-key identifier [opt] base-clause [opt] class-key nested-name-specifier identifier base-clause [opt] ! class-key nested-name-specifier [opt] template-id ! base-clause [opt] GNU Extensions: class-key attributes identifier [opt] base-clause [opt] class-key attributes nested-name-specifier identifier base-clause [opt] ! class-key attributes nested-name-specifier [opt] template-id ! base-clause [opt] Returns the TYPE of the indicated class. Sets *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions involving a nested-name-specifier was used, and FALSE otherwise. Returns NULL_TREE if the class-head is syntactically valid, but semantically invalid in a way that means we should skip the entire body of the class. */ static tree ! cp_parser_class_head (cp_parser* parser, bool* nested_name_specifier_p, tree *attributes_p) { - cp_token *token; tree nested_name_specifier; enum tag_types class_key; tree id = NULL_TREE; --- 12585,12614 ---- class-head: class-key identifier [opt] base-clause [opt] class-key nested-name-specifier identifier base-clause [opt] ! class-key nested-name-specifier [opt] template-id ! base-clause [opt] GNU Extensions: class-key attributes identifier [opt] base-clause [opt] class-key attributes nested-name-specifier identifier base-clause [opt] ! class-key attributes nested-name-specifier [opt] template-id ! base-clause [opt] Returns the TYPE of the indicated class. Sets *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions involving a nested-name-specifier was used, and FALSE otherwise. + Returns error_mark_node if this is not a class-head. + Returns NULL_TREE if the class-head is syntactically valid, but semantically invalid in a way that means we should skip the entire body of the class. */ static tree ! cp_parser_class_head (cp_parser* parser, bool* nested_name_specifier_p, tree *attributes_p) { tree nested_name_specifier; enum tag_types class_key; tree id = NULL_TREE; *************** cp_parser_class_head (cp_parser* parser, *** 12002,12009 **** bool qualified_p = false; bool invalid_nested_name_p = false; bool invalid_explicit_specialization_p = false; ! bool pop_p = false; unsigned num_templates; /* Assume no nested-name-specifier will be present. */ *nested_name_specifier_p = false; --- 12618,12626 ---- bool qualified_p = false; bool invalid_nested_name_p = false; bool invalid_explicit_specialization_p = false; ! tree pushed_scope = NULL_TREE; unsigned num_templates; + tree bases; /* Assume no nested-name-specifier will be present. */ *nested_name_specifier_p = false; *************** cp_parser_class_head (cp_parser* parser, *** 12022,12028 **** /* If the next token is `::', that is invalid -- but sometimes people do try to write: ! struct ::S {}; Handle this gracefully by accepting the extra qualifier, and then issuing an error about it later if this really is a --- 12639,12645 ---- /* If the next token is `::', that is invalid -- but sometimes people do try to write: ! struct ::S {}; Handle this gracefully by accepting the extra qualifier, and then issuing an error about it later if this really is a *************** cp_parser_class_head (cp_parser* parser, *** 12035,12041 **** /* Determine the name of the class. Begin by looking for an optional nested-name-specifier. */ ! nested_name_specifier = cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/false, --- 12652,12658 ---- /* Determine the name of the class. Begin by looking for an optional nested-name-specifier. */ ! nested_name_specifier = cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/false, *************** cp_parser_class_head (cp_parser* parser, *** 12048,12063 **** /* Although the grammar says `identifier', it really means `class-name' or `template-name'. You are only allowed to define a class that has already been declared with this ! syntax. The proposed resolution for Core Issue 180 says that whever you see `class T::X' you should treat `X' as a type-name. ! It is OK to define an inaccessible class; for example: ! class A { class B; }; class A::B {}; ! We do not know if we will see a class-name, or a template-name. We look for a class-name first, in case the class-name is a template-id; if we looked for the --- 12665,12680 ---- /* Although the grammar says `identifier', it really means `class-name' or `template-name'. You are only allowed to define a class that has already been declared with this ! syntax. The proposed resolution for Core Issue 180 says that whever you see `class T::X' you should treat `X' as a type-name. ! It is OK to define an inaccessible class; for example: ! class A { class B; }; class A::B {}; ! We do not know if we will see a class-name, or a template-name. We look for a class-name first, in case the class-name is a template-id; if we looked for the *************** cp_parser_class_head (cp_parser* parser, *** 12066,12072 **** type = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! /*type_p=*/true, /*check_dependency_p=*/false, /*class_head_p=*/true, /*is_declaration=*/false); --- 12683,12689 ---- type = cp_parser_class_name (parser, /*typename_keyword_p=*/false, /*template_keyword_p=*/false, ! class_type, /*check_dependency_p=*/false, /*class_head_p=*/true, /*is_declaration=*/false); *************** cp_parser_class_head (cp_parser* parser, *** 12084,12099 **** nested_name_specifier = NULL_TREE; /* Otherwise, count the number of templates used in TYPE and its containing scopes. */ ! else { tree scope; ! for (scope = TREE_TYPE (type); scope && TREE_CODE (scope) != NAMESPACE_DECL; ! scope = (TYPE_P (scope) ? TYPE_CONTEXT (scope) ! : DECL_CONTEXT (scope))) ! if (TYPE_P (scope) && CLASS_TYPE_P (scope) && CLASSTYPE_TEMPLATE_INFO (scope) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)) --- 12701,12716 ---- nested_name_specifier = NULL_TREE; /* Otherwise, count the number of templates used in TYPE and its containing scopes. */ ! else { tree scope; ! for (scope = TREE_TYPE (type); scope && TREE_CODE (scope) != NAMESPACE_DECL; ! scope = (TYPE_P (scope) ? TYPE_CONTEXT (scope) ! : DECL_CONTEXT (scope))) ! if (TYPE_P (scope) && CLASS_TYPE_P (scope) && CLASSTYPE_TEMPLATE_INFO (scope) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)) *************** cp_parser_class_head (cp_parser* parser, *** 12108,12114 **** an identifier, or nothing at all. */ cp_parser_parse_tentatively (parser); /* Check for a template-id. */ ! id = cp_parser_template_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*is_declaration=*/true); --- 12725,12731 ---- an identifier, or nothing at all. */ cp_parser_parse_tentatively (parser); /* Check for a template-id. */ ! id = cp_parser_template_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*is_declaration=*/true); *************** cp_parser_class_head (cp_parser* parser, *** 12138,12144 **** xref_tag, since that has irreversible side-effects. */ if (!cp_parser_next_token_starts_class_definition_p (parser)) { ! cp_parser_error (parser, "expected `{' or `:'"); return error_mark_node; } --- 12755,12761 ---- xref_tag, since that has irreversible side-effects. */ if (!cp_parser_next_token_starts_class_definition_p (parser)) { ! cp_parser_error (parser, "expected %<{%> or %<:%>"); return error_mark_node; } *************** cp_parser_class_head (cp_parser* parser, *** 12155,12170 **** else if (nested_name_specifier) { tree scope; /* Figure out in what scope the declaration is being placed. */ scope = current_scope (); - if (!scope) - scope = current_namespace; /* If that scope does not contain the scope in which the class was originally declared, the program is invalid. */ if (scope && !is_ancestor (scope, nested_name_specifier)) { ! error ("declaration of `%D' in `%D' which does not " ! "enclose `%D'", type, scope, nested_name_specifier); type = NULL_TREE; goto done; } --- 12772,12794 ---- else if (nested_name_specifier) { tree scope; + + /* Reject typedef-names in class heads. */ + if (!DECL_IMPLICIT_TYPEDEF_P (type)) + { + error ("invalid class name in declaration of %qD", type); + type = NULL_TREE; + goto done; + } + /* Figure out in what scope the declaration is being placed. */ scope = current_scope (); /* If that scope does not contain the scope in which the class was originally declared, the program is invalid. */ if (scope && !is_ancestor (scope, nested_name_specifier)) { ! error ("declaration of %qD in %qD which does not enclose %qD", ! type, scope, nested_name_specifier); type = NULL_TREE; goto done; } *************** cp_parser_class_head (cp_parser* parser, *** 12183,12193 **** } /* An explicit-specialization must be preceded by "template <>". If it is not, try to recover gracefully. */ ! if (at_namespace_scope_p () && parser->num_template_parameter_lists == 0 && template_id_p) { ! error ("an explicit specialization must be preceded by 'template <>'"); invalid_explicit_specialization_p = true; /* Take the same action that would have been taken by cp_parser_explicit_specialization. */ --- 12807,12817 ---- } /* An explicit-specialization must be preceded by "template <>". If it is not, try to recover gracefully. */ ! if (at_namespace_scope_p () && parser->num_template_parameter_lists == 0 && template_id_p) { ! error ("an explicit specialization must be preceded by %