X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=2737bbecca8614065299d43af8b73c4cffc31535;hb=3e5d979595c5dd72ad98fdffb3deae78547b939b;hp=f17019cc8ee90e17bdcfa5522c8822ef9e8298e6;hpb=f35468307d96ed321763d3d7a2819feb9683fc52;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f17019cc8ee..2737bbecca8 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -56,8 +56,6 @@ static void emit_associated_thunks PARAMS ((tree)); static void genrtl_try_block PARAMS ((tree)); static void genrtl_eh_spec_block PARAMS ((tree)); static void genrtl_handler PARAMS ((tree)); -static void genrtl_ctor_stmt PARAMS ((tree)); -static void genrtl_subobject PARAMS ((tree)); static void genrtl_named_return_value PARAMS ((void)); static void cp_expand_stmt PARAMS ((tree)); static void genrtl_start_function PARAMS ((tree)); @@ -66,19 +64,19 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *)); /* Finish processing the COND, the SUBSTMT condition for STMT. */ -#define FINISH_COND(cond, stmt, substmt) \ +#define FINISH_COND(COND, STMT, SUBSTMT) \ do { \ - if (last_tree != stmt) \ + if (last_tree != (STMT)) \ { \ - RECHAIN_STMTS (stmt, substmt); \ - if (!processing_template_decl) \ - { \ - cond = build_tree_list (substmt, cond); \ - substmt = cond; \ - } \ + RECHAIN_STMTS (STMT, SUBSTMT); \ + if (!processing_template_decl) \ + { \ + (COND) = build_tree_list (SUBSTMT, COND); \ + (SUBSTMT) = (COND); \ + } \ } \ else \ - substmt = cond; \ + (SUBSTMT) = (COND); \ } while (0) /* Returns non-zero if the current statement is a full expression, @@ -99,7 +97,7 @@ stmt_tree current_stmt_tree () { return (cfun - ? &cfun->language->x_stmt_tree + ? &cfun->language->base.x_stmt_tree : &scope_chain->x_stmt_tree); } @@ -111,7 +109,7 @@ int anon_aggr_type_p (node) tree node; { - return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr); + return ANON_AGGR_TYPE_P (node); } /* Finish a scope. */ @@ -205,6 +203,7 @@ finish_expr_stmt (expr) tree expr; { tree r = NULL_TREE; + tree expr_type = NULL_TREE;; if (expr != NULL_TREE) { @@ -215,6 +214,9 @@ finish_expr_stmt (expr) || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) expr = default_conversion (expr); + /* Remember the type of the expression. */ + expr_type = TREE_TYPE (expr); + if (stmts_are_full_exprs_p ()) expr = convert_to_void (expr, "statement"); @@ -225,7 +227,7 @@ finish_expr_stmt (expr) /* This was an expression-statement, so we save the type of the expression. */ - last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE; + last_expr_type = expr_type; return r; } @@ -264,7 +266,6 @@ finish_then_clause (if_stmt) tree if_stmt; { RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt)); - last_tree = if_stmt; return if_stmt; } @@ -290,21 +291,8 @@ finish_else_clause (if_stmt) void finish_if_stmt () { - do_poplevel (); finish_stmt (); -} - -void -clear_out_block () -{ - /* If COND wasn't a declaration, clear out the - block we made for it and start a new one here so the - optimization in expand_end_loop will work. */ - if (getdecls () == NULL_TREE) - { - do_poplevel (); - do_pushlevel (); - } + do_poplevel (); } /* Begin a while-statement. Returns a newly created WHILE_STMT if @@ -329,8 +317,26 @@ finish_while_stmt_cond (cond, while_stmt) tree while_stmt; { cond = maybe_convert_cond (cond); - FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt)); - clear_out_block (); + if (getdecls () == NULL_TREE) + /* It was a simple condition; install it. */ + WHILE_COND (while_stmt) = cond; + else + { + /* If there was a declaration in the condition, we can't leave it + there; transform + while (A x = 42) { } + to + while (true) { A x = 42; if (!x) break; } */ + tree if_stmt; + WHILE_COND (while_stmt) = boolean_true_node; + + if_stmt = begin_if_stmt (); + cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0); + finish_if_stmt_cond (cond, if_stmt); + finish_break_stmt (); + finish_then_clause (if_stmt); + finish_if_stmt (); + } } /* Finish a while-statement, which may be given by WHILE_STMT. */ @@ -415,12 +421,12 @@ begin_for_stmt () r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0; - add_stmt (r); if (NEW_FOR_SCOPE_P (r)) { do_pushlevel (); note_level_for_for (); } + add_stmt (r); return r; } @@ -446,8 +452,26 @@ finish_for_cond (cond, for_stmt) tree for_stmt; { cond = maybe_convert_cond (cond); - FINISH_COND (cond, for_stmt, FOR_COND (for_stmt)); - clear_out_block (); + if (getdecls () == NULL_TREE) + /* It was a simple condition; install it. */ + FOR_COND (for_stmt) = cond; + else + { + /* If there was a declaration in the condition, we can't leave it + there; transform + for (; A x = 42;) { } + to + for (;;) { A x = 42; if (!x) break; } */ + tree if_stmt; + FOR_COND (for_stmt) = NULL_TREE; + + if_stmt = begin_if_stmt (); + cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0); + finish_if_stmt_cond (cond, if_stmt); + finish_break_stmt (); + finish_then_clause (if_stmt); + finish_if_stmt (); + } } /* Finish the increment-EXPRESSION in a for-statement, which may be @@ -500,9 +524,9 @@ tree begin_switch_stmt () { tree r; - r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE); - add_stmt (r); do_pushlevel (); + r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE); + add_stmt (r); return r; } @@ -513,9 +537,9 @@ finish_switch_cond (cond, switch_stmt) tree cond; tree switch_stmt; { + tree orig_type = NULL; if (!processing_template_decl) { - tree type; tree index; /* Convert the condition to an integer or enumeration type. */ @@ -525,23 +549,27 @@ finish_switch_cond (cond, switch_stmt) error ("switch quantity not an integer"); cond = error_mark_node; } + orig_type = TREE_TYPE (cond); if (cond != error_mark_node) { cond = default_conversion (cond); cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond)); } - type = TREE_TYPE (cond); - index = get_unwidened (cond, NULL_TREE); - /* We can't strip a conversion from a signed type to an unsigned, - because if we did, int_fits_type_p would do the wrong thing - when checking case values for being in range, - and it's too hard to do the right thing. */ - if (TREE_UNSIGNED (TREE_TYPE (cond)) - == TREE_UNSIGNED (TREE_TYPE (index))) - cond = index; + if (cond != error_mark_node) + { + index = get_unwidened (cond, NULL_TREE); + /* We can't strip a conversion from a signed type to an unsigned, + because if we did, int_fits_type_p would do the wrong thing + when checking case values for being in range, + and it's too hard to do the right thing. */ + if (TREE_UNSIGNED (TREE_TYPE (cond)) + == TREE_UNSIGNED (TREE_TYPE (index))) + cond = index; + } } FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt)); + SWITCH_TYPE (switch_stmt) = orig_type; push_switch (switch_stmt); } @@ -554,8 +582,8 @@ finish_switch_stmt (switch_stmt) { RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt)); pop_switch (); - do_poplevel (); finish_stmt (); + do_poplevel (); } /* Generate the RTL for T, which is a TRY_BLOCK. */ @@ -773,21 +801,6 @@ finish_handler (handler) RECHAIN_STMTS (handler, HANDLER_BODY (handler)); } -/* Generate the RTL for T, which is a CTOR_STMT. */ - -static void -genrtl_ctor_stmt (t) - tree t; -{ - if (CTOR_BEGIN_P (t)) - begin_protect_partials (); - else - /* After this point, any exceptions will cause the - destructor to be executed, so we no longer need to worry - about destroying the various subobjects ourselves. */ - end_protect_partials (); -} - /* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the compound-statement does not define a scope. Returns a new COMPOUND_STMT if appropriate. */ @@ -872,9 +885,6 @@ finish_asm_stmt (cv_qualifier, string, output_operands, tree r; tree t; - if (TREE_CHAIN (string)) - string = combine_strings (string); - if (cv_qualifier != NULL_TREE && cv_qualifier != ridpointers[(int) RID_VOLATILE]) { @@ -940,7 +950,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands, DECL_RTL for the OPERAND -- which we don't have at this point. */ if (!allows_reg && DECL_P (operand)) - mark_addressable (operand); + cxx_mark_addressable (operand); } } @@ -972,35 +982,25 @@ finish_label_decl (name) add_decl_stmt (decl); } -/* Generate the RTL for a SUBOBJECT. */ - -static void -genrtl_subobject (cleanup) - tree cleanup; -{ - add_partial_entry (cleanup); -} - -/* We're in a constructor, and have just constructed a a subobject of - *THIS. CLEANUP is code to run if an exception is thrown before the - end of the current function is reached. */ +/* When DECL goes out of scope, make sure that CLEANUP is executed. */ void -finish_subobject (cleanup) +finish_decl_cleanup (decl, cleanup) + tree decl; tree cleanup; { - tree r = build_stmt (SUBOBJECT, cleanup); - add_stmt (r); + add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); } -/* When DECL goes out of scope, make sure that CLEANUP is executed. */ +/* If the current scope exits with an exception, run CLEANUP. */ -void -finish_decl_cleanup (decl, cleanup) - tree decl; +void +finish_eh_cleanup (cleanup) tree cleanup; { - add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); + tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup); + CLEANUP_EH_ONLY (r) = 1; + add_stmt (r); } /* Generate the RTL for a RETURN_INIT. */ @@ -1085,6 +1085,15 @@ finish_named_return_value (return_id, init) DECL_UNINLINABLE (current_function_decl) = 1; } +/* Begin processing a mem-initializer-list. */ + +void +begin_mem_initializers () +{ + if (! DECL_CONSTRUCTOR_P (current_function_decl)) + error ("only constructors take base initializers"); +} + /* The INIT_LIST is a list of mem-initializers, in the order they were written by the user. The TREE_VALUE of each node is a list of initializers for a particular subobject. The TREE_PURPOSE is a @@ -1141,90 +1150,11 @@ finish_mem_initializers (init_list) } } - setup_vtbl_ptr (member_init_list, base_init_list); -} - -/* Do the initialization work necessary at the beginning of a constructor - or destructor. This means processing member initializers and setting - vtable pointers. - - ??? The call to keep_next_level at the end applies to all functions, but - should probably go somewhere else. */ - -void -setup_vtbl_ptr (member_init_list, base_init_list) - tree member_init_list; - tree base_init_list; -{ - my_friendly_assert (doing_semantic_analysis_p (), 19990919); - my_friendly_assert (!vtbls_set_up_p, 20011220); - if (processing_template_decl) add_stmt (build_min_nt (CTOR_INITIALIZER, member_init_list, base_init_list)); - else if (DECL_CONSTRUCTOR_P (current_function_decl)) - { - tree ctor_stmt; - - /* Mark the beginning of the constructor. */ - ctor_stmt = build_stmt (CTOR_STMT); - CTOR_BEGIN_P (ctor_stmt) = 1; - add_stmt (ctor_stmt); - - /* And actually initialize the base-classes and members. */ - emit_base_init (member_init_list, base_init_list); - } - else if (DECL_DESTRUCTOR_P (current_function_decl)) - { - tree if_stmt; - tree compound_stmt; - - /* If the dtor is empty, and we know there is not any possible - way we could use any vtable entries, before they are possibly - set by a base class dtor, we don't have to setup the vtables, - as we know that any base class dtor will set up any vtables - it needs. We avoid MI, because one base class dtor can do a - virtual dispatch to an overridden function that would need to - have a non-related vtable set up, we cannot avoid setting up - vtables in that case. We could change this to see if there - is just one vtable. - - ??? In the destructor for a class, the vtables are set - appropriately for that class. There will be no non-related - vtables. jason 2001-12-11. */ - 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); - current_vcalls_possible_p = &IF_COND (if_stmt); - - compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); - - /* Make all virtual function table pointers in non-virtual base - classes point to CURRENT_CLASS_TYPE's virtual function - tables. */ - initialize_vtbl_ptrs (current_class_ptr); - - finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); - finish_then_clause (if_stmt); - finish_if_stmt (); - - /* And insert cleanups for our bases and members so that they - will be properly destroyed if we throw. */ - push_base_cleanups (); - } - - /* Always keep the BLOCK node associated with the outermost pair of - curly braces of a function. These are needed for correct - operation of dwarfout.c. */ - keep_next_level (1); - - /* The virtual function tables are set up now. */ - vtbls_set_up_p = 1; + else + emit_base_init (member_init_list, base_init_list); } /* Returns the stack of SCOPE_STMTs for the current function. */ @@ -1232,7 +1162,7 @@ setup_vtbl_ptr (member_init_list, base_init_list) tree * current_scope_stmt_stack () { - return &cfun->language->x_scope_stmt_stack; + return &cfun->language->base.x_scope_stmt_stack; } /* Finish a parenthesized expression EXPR. */ @@ -1242,7 +1172,7 @@ finish_parenthesized_expr (expr) tree expr; { if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr)))) - /* This inhibits warnings in truthvalue_conversion. */ + /* This inhibits warnings in c_common_truthvalue_conversion. */ C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); if (TREE_CODE (expr) == OFFSET_REF) @@ -1284,7 +1214,7 @@ begin_global_stmt_expr () keep_next_level (1); - return (last_tree != NULL_TREE) ? last_tree : expand_start_stmt_expr(); + return last_tree ? last_tree : expand_start_stmt_expr(/*has_scope=*/1); } /* Finish the STMT_EXPR last begun with begin_global_stmt_expr. */ @@ -1334,32 +1264,86 @@ finish_stmt_expr (rtl_expr) return result; } -/* Finish a call to FN with ARGS. Returns a representation of the - call. */ +/* Generate an expression for `FN (ARGS)'. + + If DISALLOW_VIRTUAL is true, the call to FN will be not generated + as a virtual call, even if FN is virtual. (This flag is set when + encountering an expression where the function name is explicitly + qualified. For example a call to `X::f' never generates a virtual + call.) + + Returns code for the call. */ tree -finish_call_expr (fn, args, koenig) - tree fn; - tree args; - int koenig; +finish_call_expr (tree fn, tree args, bool disallow_virtual) { - tree result; + if (fn == error_mark_node || args == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + return build_nt (CALL_EXPR, fn, args, NULL_TREE); + + /* ARGS should be a list of arguments. */ + my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST, + 20020712); - if (koenig) + if (BASELINK_P (fn)) { - if (TREE_CODE (fn) == BIT_NOT_EXPR) - fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0)); - else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR) - fn = do_identifier (fn, 2, args); - } - result = build_x_function_call (fn, args, current_class_ref); + tree object; + + /* A call to a member function. From [over.call.func]: + + If the keyword this is in scope and refers to the class of + that member function, or a derived class thereof, then the + function call is transformed into a qualified function call + using (*this) as the postfix-expression to the left of the + . operator.... [Otherwise] a contrived object of type T + becomes the implied object argument. + + This paragraph is unclear about this situation: + + struct A { void f(); }; + struct B : public A {}; + struct C : public A { void g() { B::f(); }}; + + In particular, for `B::f', this paragraph does not make clear + whether "the class of that member function" refers to `A' or + to `B'. We believe it refers to `B'. */ + if (current_class_type + && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), + current_class_type) + && current_class_ref) + object = current_class_ref; + else + { + tree representative_fn; - if (TREE_CODE (result) == CALL_EXPR - && (! TREE_TYPE (result) - || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE)) - result = require_complete_type (result); + representative_fn = BASELINK_FUNCTIONS (fn); + if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR) + representative_fn = TREE_OPERAND (representative_fn, 0); + representative_fn = get_first_fn (representative_fn); + object = build_dummy_object (DECL_CONTEXT (representative_fn)); + } - return result; + return build_new_method_call (object, fn, args, NULL_TREE, + (disallow_virtual + ? LOOKUP_NONVIRTUAL : 0)); + } + else if (is_overloaded_fn (fn)) + /* A call to a namespace-scope function. */ + return build_new_function_call (fn, args); + else if (CLASS_TYPE_P (TREE_TYPE (fn))) + { + /* If the "function" is really an object of class type, it might + have an overloaded `operator ()'. */ + tree result; + result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE); + if (result) + return result; + } + + /* A call where the function is unknown. */ + return build_function_call (fn, args); } /* Finish a call to a postfix increment or decrement or EXPR. (Which @@ -1419,14 +1403,6 @@ finish_object_call_expr (fn, object, args) tree object; tree args; { -#if 0 - /* This is a future direction of this code, but because - build_x_function_call cannot always undo what is done in - build_component_ref entirely yet, we cannot do this. */ - - tree real_fn = build_component_ref (object, fn, NULL_TREE, 1); - return finish_call_expr (real_fn, args); -#else if (DECL_DECLARES_TYPE_P (fn)) { if (processing_template_decl) @@ -1445,9 +1421,11 @@ finish_object_call_expr (fn, object, args) return error_mark_node; } } - - return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); -#endif + + if (name_p (fn)) + return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); + else + return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); } /* Finish a qualified member function call using OBJECT and ARGS as @@ -1488,22 +1466,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor) return cp_convert (void_type_node, object); } -/* Finish a call to a globally qualified member function FN using - ARGS. Returns an expression for the call. */ - -tree -finish_qualified_call_expr (fn, args) - tree fn; - tree args; -{ - if (processing_template_decl) - return build_min_nt (CALL_EXPR, fn, args, NULL_TREE); - else - return build_member_call (TREE_OPERAND (fn, 0), - TREE_OPERAND (fn, 1), - args); -} - /* Finish an expression of the form CODE EXPR. */ tree @@ -1538,6 +1500,20 @@ finish_id_expr (expr) return expr; } +/* Return the declaration for the function-name variable indicated by + ID. */ + +tree +finish_fname (tree id) +{ + tree decl; + + decl = fname_decl (C_RID_CODE (id), id); + if (processing_template_decl) + decl = build_min_nt (LOOKUP_EXPR, DECL_NAME (decl)); + return decl; +} + static tree current_type_lookups; /* Perform deferred access control for types used in the type of a @@ -1577,32 +1553,13 @@ decl_type_access_control (decl) added to type_lookups after typed_declspecs saved the copy that ended up in current_type_lookups. */ type_lookups = current_type_lookups; - - current_type_lookups = NULL_TREE; } -/* Record the lookups, if we're doing deferred access control. */ - void save_type_access_control (lookups) tree lookups; { - if (type_lookups != error_mark_node) - { - my_friendly_assert (!current_type_lookups, 20010301); - current_type_lookups = lookups; - } - else - my_friendly_assert (!lookups || lookups == error_mark_node, 20010301); -} - -/* Set things up so that the next deferred access control will succeed. - This is needed for friend declarations see grokdeclarator for details. */ - -void -skip_type_access_control () -{ - type_lookups = NULL_TREE; + current_type_lookups = lookups; } /* Reset the deferred access control. */ @@ -1614,20 +1571,17 @@ reset_type_access_control () current_type_lookups = NULL_TREE; } -/* Begin a function definition declared with DECL_SPECS and - DECLARATOR. Returns non-zero if the function-declaration is - legal. */ +/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES, + and DECLARATOR. Returns non-zero if the function-declaration is + valid. */ int -begin_function_definition (decl_specs, declarator) +begin_function_definition (decl_specs, attributes, declarator) tree decl_specs; + tree attributes; tree declarator; { - tree specs; - tree attrs; - - split_specs_attrs (decl_specs, &specs, &attrs); - if (!start_function (specs, declarator, attrs, SF_DEFAULT)) + if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT)) return 0; deferred_type_access_control (); @@ -1722,6 +1676,25 @@ finish_template_template_parm (aggr, identifier) return finish_template_type_parm (aggr, tmpl); } +/* ARGUMENT is the default-argument value for a template template + parameter. If ARGUMENT is invalid, issue error messages and return + the ERROR_MARK_NODE. Otherwise, ARGUMENT itself is returned. */ + +tree +check_template_template_default_arg (tree argument) +{ + if (TREE_CODE (argument) != TEMPLATE_DECL + && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM + && TREE_CODE (argument) != TYPE_DECL + && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) + { + error ("invalid default template argument"); + return error_mark_node; + } + + return argument; +} + /* Finish a parameter list, indicated by PARMS. If ELLIPSIS is non-zero, the parameter list was terminated by a `...'. */ @@ -1748,6 +1721,9 @@ tree begin_class_definition (t) tree t; { + if (t == error_mark_node) + return error_mark_node; + /* Check the bases are accessible. */ decl_type_access_control (TYPE_NAME (t)); reset_type_access_control (); @@ -1923,7 +1899,7 @@ finish_member_declaration (decl) struct S { enum E { }; int E } s; s.E = 3; - is legal. In addition, the FIELD_DECLs must be maintained in + is valid. In addition, the FIELD_DECLs must be maintained in declaration order so that class layout works as expected. However, we don't need that order until class layout, so we save a little time by putting FIELD_DECLs on in reverse order @@ -1957,6 +1933,9 @@ finish_class_definition (t, attributes, semi, pop_scope_p) int semi; int pop_scope_p; { + if (t == error_mark_node) + return error_mark_node; + /* finish_struct nukes this anyway; if finish_exception does too, then it can go. */ if (semi) @@ -1964,8 +1943,8 @@ finish_class_definition (t, attributes, semi, pop_scope_p) /* If we got any attributes in class_head, xref_tag will stick them in TREE_TYPE of the type. Grab them now. */ - attributes = chainon (TREE_TYPE (t), attributes); - TREE_TYPE (t) = NULL_TREE; + attributes = chainon (TYPE_ATTRIBUTES (t), attributes); + TYPE_ATTRIBUTES (t) = NULL_TREE; if (TREE_CODE (t) == ENUMERAL_TYPE) ; @@ -1980,8 +1959,6 @@ finish_class_definition (t, attributes, semi, pop_scope_p) check_for_missing_semicolon (t); if (pop_scope_p) pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t))); - if (current_function_decl) - type_lookups = error_mark_node; if (current_scope () == current_function_decl) do_pending_defargs (); @@ -1998,16 +1975,6 @@ begin_inline_definitions () do_pending_inlines (); } -/* Finish processing the inline function definitions cached during the - processing of a class definition. */ - -void -finish_inline_definitions () -{ - if (current_class_type == NULL_TREE) - clear_inline_text_obstack (); -} - /* Finish processing the declaration of a member class template TYPES whose template parameters are given by PARMS. */ @@ -2116,7 +2083,12 @@ finish_base_specifier (access_specifier, base_class) { tree result; - if (! is_aggr_type (base_class, 1)) + if (base_class == error_mark_node) + { + error ("invalid base-class specification"); + result = NULL_TREE; + } + else if (! is_aggr_type (base_class, 1)) result = NULL_TREE; else { @@ -2144,11 +2116,9 @@ check_multiple_declarators () contain at most one declarator. We don't just use PROCESSING_TEMPLATE_DECL for the first - condition since that would disallow the perfectly legal code, + condition since that would disallow the perfectly valid code, like `template struct S { int i, j; };'. */ - tree scope = current_scope (); - - if (scope && TREE_CODE (scope) == FUNCTION_DECL) + if (at_function_scope_p ()) /* It's OK to write `template void f() { int i, j;}'. */ return; @@ -2190,7 +2160,7 @@ finish_sizeof (t) if (processing_template_decl) return build_min_nt (SIZEOF_EXPR, t); - return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t); + return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t); } /* Implement the __alignof keyword: Return the minimum required @@ -2203,7 +2173,7 @@ finish_alignof (t) if (processing_template_decl) return build_min_nt (ALIGNOF_EXPR, t); - return TYPE_P (t) ? c_alignof (t) : c_alignof_expr (t); + return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t); } /* Generate RTL for the statement T, and its substatements, and any @@ -2215,14 +2185,6 @@ cp_expand_stmt (t) { switch (TREE_CODE (t)) { - case CLEANUP_STMT: - genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t)); - break; - - case CTOR_STMT: - genrtl_ctor_stmt (t); - break; - case TRY_BLOCK: genrtl_try_block (t); break; @@ -2235,10 +2197,6 @@ cp_expand_stmt (t) genrtl_handler (t); break; - case SUBOBJECT: - genrtl_subobject (SUBOBJECT_CLEANUP (t)); - break; - case RETURN_INIT: genrtl_named_return_value (); break; @@ -2247,7 +2205,7 @@ cp_expand_stmt (t) break; default: - my_friendly_abort (19990810); + abort (); break; } } @@ -2293,7 +2251,7 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data) { /* Replace the first argument with the address of the third argument to the AGGR_INIT_EXPR. */ - mark_addressable (slot); + cxx_mark_addressable (slot); args = tree_cons (NULL_TREE, build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (slot)), @@ -2393,6 +2351,7 @@ expand_body (fn) { int saved_lineno; const char *saved_input_filename; + tree saved_function; /* When the parser calls us after finishing the body of a template function, we don't really want to expand the body. When we're @@ -2470,8 +2429,15 @@ expand_body (fn) if (DECL_EXTERNAL (fn)) return; - /* Emit any thunks that should be emitted at the same time as FN. */ - emit_associated_thunks (fn); + /* Save the current file name and line number. When we expand the + body of the function, we'll set LINENO and INPUT_FILENAME so that + error-mesages come out in the right places. */ + saved_lineno = lineno; + saved_input_filename = input_filename; + saved_function = current_function_decl; + lineno = DECL_SOURCE_LINE (fn); + input_filename = DECL_SOURCE_FILE (fn); + current_function_decl = fn; timevar_push (TV_INTEGRATION); @@ -2481,14 +2447,6 @@ expand_body (fn) timevar_pop (TV_INTEGRATION); timevar_push (TV_EXPAND); - /* Save the current file name and line number. When we expand the - body of the function, we'll set LINENO and INPUT_FILENAME so that - error-mesages come out in the right places. */ - saved_lineno = lineno; - saved_input_filename = input_filename; - lineno = DECL_SOURCE_LINE (fn); - input_filename = DECL_SOURCE_FILE (fn); - genrtl_start_function (fn); current_function_is_thunk = DECL_THUNK_P (fn); @@ -2520,11 +2478,15 @@ expand_body (fn) DECL_SAVED_TREE (fn) = NULL_TREE; /* And restore the current source position. */ + current_function_decl = saved_function; lineno = saved_lineno; input_filename = saved_input_filename; extract_interface_info (); timevar_pop (TV_EXPAND); + + /* Emit any thunks that should be emitted at the same time as FN. */ + emit_associated_thunks (fn); } /* Helper function for walk_tree, used by finish_function to override all @@ -2544,10 +2506,10 @@ nullify_returns_r (tp, walk_subtrees, data) if (TYPE_P (*tp)) *walk_subtrees = 0; else if (TREE_CODE (*tp) == RETURN_STMT) - RETURN_EXPR (*tp) = NULL_TREE; + RETURN_STMT_EXPR (*tp) = NULL_TREE; else if (TREE_CODE (*tp) == CLEANUP_STMT && CLEANUP_DECL (*tp) == nrv) - CLEANUP_EXPR (*tp) = NULL_TREE; + CLEANUP_EH_ONLY (*tp) = 1; /* Keep iterating. */ return NULL_TREE; @@ -2594,15 +2556,13 @@ genrtl_start_function (fn) if (!current_function_cannot_inline) current_function_cannot_inline = cp_function_chain->cannot_inline; - /* We don't need the saved data anymore. */ - free (DECL_SAVED_FUNCTION_DATA (fn)); - DECL_SAVED_FUNCTION_DATA (fn) = NULL; + /* 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; } - /* Tell the cross-reference machinery that we're defining this - function. */ - GNU_xref_function (fn, DECL_ARGUMENTS (fn)); - /* Keep track of how many functions we're presently expanding. */ ++function_depth;