aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/expr.c96
-rw-r--r--gcc/cp/semantics.c78
-rw-r--r--gcc/cp/tree.c14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/inline1.C20
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);
+}