diff options
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 4 | ||||
-rw-r--r-- | gcc/cp/expr.c | 96 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 78 | ||||
-rw-r--r-- | gcc/cp/tree.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/inline1.C | 20 |
6 files changed, 118 insertions, 102 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 072823f..b6505e5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 1999-12-09 Mark Mitchell <mark@codesourcery.com> + * decl.c (init_decl_processing): Reenable inlining on trees. + (finish_function): Likewise. + * expr.c (cplus_expand_expr): Don't handle AGGR_INIT_EXPR here. + * semantics.c (simplify_aggr_init_exprs): New function. + (expand_body): Use it. + * tree.c (walk_tree): Special-case TARGET_EXPRs since they + sometimes present the same sub-tree twice. + * dump.c (dequeue_and_dump): Abbreviate `class' as `cls', not `csl'. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8e233f6..b6a62ea 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5973,10 +5973,8 @@ init_decl_processing () flag_strict_prototype = pedantic; if (! flag_permissive && ! pedantic) flag_pedantic_errors = 1; -#if 0 if (!flag_no_inline) flag_inline_trees = 1; -#endif strict_prototypes_lang_c = flag_strict_prototype; @@ -13669,7 +13667,6 @@ finish_function (lineno, flags) if (!expanding_p && !processing_template_decl) save_function_data (fndecl); -#if 0 /* 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 @@ -13681,7 +13678,6 @@ finish_function (lineno, flags) function.) */ if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl)) DECL_UNINLINABLE (fndecl) = 1; -#endif if (expand_p) { diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 094ba50..2ac29f9 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -120,102 +120,6 @@ cplus_expand_expr (exp, target, tmode, modifier) switch (code) { - case AGGR_INIT_EXPR: - { - /* Something needs to be initialized, but we didn't know - where that thing was when building the tree. For example, - it could be the return value of a function, or a parameter - to a function which lays down in the stack, or a temporary - variable which must be passed by reference. - - Cleanups are handled in a language-specific way: they - might be run by the called function (true in GNU C++ - for parameters with cleanups), or they might be - run by the caller, after the call (true in GNU C++ - for other cleanup needs). */ - - tree func = TREE_OPERAND (exp, 0); - tree args = TREE_OPERAND (exp, 1); - tree type = TREE_TYPE (exp), slot; - tree call_exp; - rtx call_target, return_target; - int pcc_struct_return = 0; - - /* The expression `init' wants to initialize what - `target' represents. SLOT holds the slot for TARGET. */ - slot = TREE_OPERAND (exp, 2); - - /* Should always be called with a target. */ - my_friendly_assert (target != NULL_RTX, 205); - - /* The target the initializer will initialize (CALL_TARGET) - must now be directed to initialize the target we are - supposed to initialize (TARGET). The semantics for - choosing what CALL_TARGET is is language-specific, - as is building the call which will perform the - initialization. It is left here to show the choices that - exist for C++. */ - - if (AGGR_INIT_VIA_CTOR_P (exp)) - { - type = build_pointer_type (type); - mark_addressable (slot); - args = tree_cons (NULL_TREE, - build1 (ADDR_EXPR, type, slot), - TREE_CHAIN (args)); - call_target = 0; - } - else - { - call_target = target; -#ifdef PCC_STATIC_STRUCT_RETURN - if (aggregate_value_p (type)) - { - pcc_struct_return = 1; - call_target = 0; - } -#endif - } - - call_exp = build (CALL_EXPR, type, func, args, NULL_TREE); - TREE_SIDE_EFFECTS (call_exp) = 1; - return_target = expand_call (call_exp, call_target, ignore); - - if (call_target) - /* Trust that the right thing has been done; it's too hard to - verify. */ - return return_target; - - /* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN - calling convention, we need to copy the return value out of - the static return buffer into slot. */ - if (pcc_struct_return) - { - extern int flag_access_control; - int old_ac = flag_access_control; - - tree init = build_decl (VAR_DECL, NULL_TREE, - build_reference_type (type)); - DECL_RTL (init) = XEXP (return_target, 0); - init = convert_from_reference (init); - - flag_access_control = 0; - expand_expr (build_aggr_init (slot, init, - LOOKUP_ONLYCONVERTING), - target, tmode, EXPAND_NORMAL); - flag_access_control = old_ac; - - if (TYPE_NEEDS_DESTRUCTOR (type)) - { - init = maybe_build_cleanup (init); - if (init != NULL_TREE) - expand_expr (init, const0_rtx, VOIDmode, 0); - } - } - - return DECL_RTL (slot); - } - case PTRMEM_CST: return expand_expr (cplus_expand_constant (exp), target, tmode, modifier); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8637e3b..ca0201d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2547,6 +2547,81 @@ expand_stmt (t) return rval; } +/* Called from expand_body via walk_tree. Replace all AGGR_INIT_EXPRs + will equivalent CALL_EXPRs. */ + +static tree +simplify_aggr_init_exprs_r (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; +{ + tree aggr_init_expr; + tree call_expr; + tree fn; + tree args; + tree slot; + tree type; + tree call_type; + int copy_from_buffer_p; + + /* Only AGGR_INIT_EXPRs are interesting. */ + aggr_init_expr = *tp; + if (TREE_CODE (aggr_init_expr) != AGGR_INIT_EXPR) + return NULL_TREE; + + /* Form an appropriate CALL_EXPR. */ + fn = TREE_OPERAND (aggr_init_expr, 0); + args = TREE_OPERAND (aggr_init_expr, 1); + slot = TREE_OPERAND (aggr_init_expr, 2); + type = TREE_TYPE (aggr_init_expr); + call_type = type; + if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr)) + { + /* Replace the first argument with the address of the third + argument to the AGGR_INIT_EXPR. */ + call_type = build_pointer_type (type); + mark_addressable (slot); + args = tree_cons (NULL_TREE, build1 (ADDR_EXPR, call_type, slot), + TREE_CHAIN (args)); + } + call_expr = build (CALL_EXPR, call_type, fn, args, NULL_TREE); + TREE_SIDE_EFFECTS (call_expr) = 1; + + /* If we're using the non-reentrant PCC calling convention, then we + need to copy the returned value out of the static buffer into the + SLOT. */ + copy_from_buffer_p = 0; +#ifdef PCC_STATIC_STRUCT_RETURN + if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type)) + { + int old_ac; + + flag_access_control = 0; + call_expr = build_aggr_init (slot, call_expr, LOOKUP_ONLYCONVERTING); + flag_access_control = old_ac; + copy_from_buffer_p = 1; + } +#endif + + /* If this AGGR_INIT_EXPR indicates the value returned by a + function, then we want to use the value of the initialized + location as the result. */ + if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p) + { + call_expr = build (COMPOUND_EXPR, type, + call_expr, slot); + TREE_SIDE_EFFECTS (call_expr) = 1; + } + + /* Replace the AGGR_INIT_EXPR with the CALL_EXPR. */ + TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr); + *tp = call_expr; + + /* Keep iterating. */ + return NULL_TREE; +} + /* Generate RTL for FN. */ void @@ -2574,6 +2649,9 @@ expand_body (fn) return; } + /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */ + walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL); + /* There's no reason to do any of the work here if we're only doing semantic analysis; this code just generates RTL. */ if (flag_syntax_only) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 1cabf82..31fbec0 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1626,8 +1626,18 @@ walk_tree (tp, func, data) int i; /* Walk over all the sub-trees of this operand. */ - for (i = first_rtl_op (code) - 1; i >= 0; --i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); + i = first_rtl_op (code) - 1; + /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. + But, we only want to walk once. */ + if (code == TARGET_EXPR + && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) + --i; + /* Go through the subtrees. */ + while (i >= 0) + { + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + --i; + } /* For statements, we also walk the chain so that we cover the entire statement tree. */ diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline1.C b/gcc/testsuite/g++.old-deja/g++.other/inline1.C new file mode 100644 index 0000000..c4c71b7 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/inline1.C @@ -0,0 +1,20 @@ +// Build don't link: +// Origin: Martin Reinecke <martin@MPA-Garching.MPG.DE> +// Special g++ Options: -O2 -Winline + +class foo +{ + public: + float x; + + foo (float xval) + : x (xval) {} + + foo operator+ (const foo &foo2) const + { return foo (x+foo2.x); } +}; + +int main() +{ + foo f=foo(1)+foo(2); +} |