Commit 4e8dca1c by Jason Merrill Committed by Jason Merrill

fold-const.c (fold): Avoid NOP_EXPRs better.

        * fold-const.c (fold) [COND_EXPR]: Avoid NOP_EXPRs better.

        * integrate.c (copy_decl_for_inlining): Don't clear the rtl for
        static/external decls.
cp/
        * call.c (build_conditional_expr): Stabilize lvalues properly.
        * cvt.c (ocp_convert): Don't build NOP_EXPRs of class type.
        * tree.c (lvalue_p_1): Don't allow sloppy NOP_EXPRs as lvalues.
        Don't allow CALL_EXPR or VA_ARG_EXPR, either.

        * call.c (convert_like_real): Call decl_constant_value for an
        IDENTITY_CONV even if there are no more conversions.

        * cvt.c (build_up_reference): Don't push unnamed temps.

        * decl2.c (do_namespace_alias): Namespace aliases are DECL_EXTERNAL.

        * dump.c (cp_dump_tree): Don't try to dump class-specific fields
        for a backend struct.

        * except.c (wrap_cleanups_r, build_throw): Make
        MUST_NOT_THROW_EXPRs void.
        * init.c (expand_default_init): Update to handle MUST_NOT_THROW_EXPR.

        * init.c (build_vec_delete_1): Pre-evaluate the base address.

        * init.c (get_temp_regvar): Simplify logic.

        * tree.c (cp_copy_res_decl_for_inlining): Only do debug tweaks if
        our replacement is a decl.

From-SVN: r60851
parent 9aad8f83
2003-01-02 Jason Merrill <jason@redhat.com> 2003-01-02 Jason Merrill <jason@redhat.com>
* fold-const.c (fold) [COND_EXPR]: Avoid NOP_EXPRs better.
* integrate.c (copy_decl_for_inlining): Don't clear the rtl for
static/external decls.
* c-common.c (finish_fname_decls): Put the DECL_STMTs inside the * c-common.c (finish_fname_decls): Put the DECL_STMTs inside the
outermost scope. outermost scope.
* c-decl.c (c_make_fname_decl): Push the decls there, too. * c-decl.c (c_make_fname_decl): Push the decls there, too.
......
...@@ -16,6 +16,32 @@ ...@@ -16,6 +16,32 @@
2003-01-02 Jason Merrill <jason@redhat.com> 2003-01-02 Jason Merrill <jason@redhat.com>
* call.c (build_conditional_expr): Stabilize lvalues properly.
* cvt.c (ocp_convert): Don't build NOP_EXPRs of class type.
* tree.c (lvalue_p_1): Don't allow sloppy NOP_EXPRs as lvalues.
Don't allow CALL_EXPR or VA_ARG_EXPR, either.
* call.c (convert_like_real): Call decl_constant_value for an
IDENTITY_CONV even if there are no more conversions.
* cvt.c (build_up_reference): Don't push unnamed temps.
* decl2.c (do_namespace_alias): Namespace aliases are DECL_EXTERNAL.
* dump.c (cp_dump_tree): Don't try to dump class-specific fields
for a backend struct.
* except.c (wrap_cleanups_r, build_throw): Make
MUST_NOT_THROW_EXPRs void.
* init.c (expand_default_init): Update to handle MUST_NOT_THROW_EXPR.
* init.c (build_vec_delete_1): Pre-evaluate the base address.
* init.c (get_temp_regvar): Simplify logic.
* tree.c (cp_copy_res_decl_for_inlining): Only do debug tweaks if
our replacement is a decl.
* decl.c (cp_make_fname_decl): Push the decls inside the * decl.c (cp_make_fname_decl): Push the decls inside the
outermost scope. outermost scope.
......
...@@ -2977,7 +2977,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) ...@@ -2977,7 +2977,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
{ {
if (pedantic) if (pedantic)
pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression"); pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
arg1 = arg2 = save_expr (arg1);
/* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */
if (real_lvalue_p (arg1))
arg2 = arg1 = stabilize_reference (arg1);
else
arg2 = arg1 = save_expr (arg1);
} }
/* [expr.cond] /* [expr.cond]
...@@ -3964,6 +3969,12 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner) ...@@ -3964,6 +3969,12 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
case IDENTITY_CONV: case IDENTITY_CONV:
if (type_unknown_p (expr)) if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, tf_error | tf_warning); 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);
return expr; return expr;
case AMBIG_CONV: case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */ /* Call build_user_type_conversion again for the error. */
...@@ -3979,13 +3990,6 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner) ...@@ -3979,13 +3990,6 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
if (expr == error_mark_node) if (expr == error_mark_node)
return error_mark_node; return error_mark_node;
/* 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 (TREE_CODE (convs) != REF_BIND
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
expr = decl_constant_value (expr);
switch (TREE_CODE (convs)) switch (TREE_CODE (convs))
{ {
case RVALUE_CONV: case RVALUE_CONV:
......
...@@ -381,7 +381,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl) ...@@ -381,7 +381,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
{ {
/* Automatic; make sure we handle the cleanup properly. */ /* Automatic; make sure we handle the cleanup properly. */
maybe_push_cleanup_level (argtype); maybe_push_cleanup_level (argtype);
arg = pushdecl (arg); /* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
DECL_CONTEXT (arg) = current_function_decl;
} }
/* Process the initializer for the declaration. */ /* Process the initializer for the declaration. */
...@@ -654,6 +655,19 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ...@@ -654,6 +655,19 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
conversion. */ conversion. */
else if (TREE_CODE (type) == COMPLEX_TYPE) else if (TREE_CODE (type) == COMPLEX_TYPE)
return fold (convert_to_complex (type, e)); 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 (CLASS_TYPE_P (type))
abort ();
else else
return fold (build1 (NOP_EXPR, type, e)); return fold (build1 (NOP_EXPR, type, e));
} }
......
...@@ -4258,6 +4258,7 @@ do_namespace_alias (tree alias, tree namespace) ...@@ -4258,6 +4258,7 @@ do_namespace_alias (tree alias, tree namespace)
/* Build the alias. */ /* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace; DECL_NAMESPACE_ALIAS (alias) = namespace;
DECL_EXTERNAL (alias) = 1;
pushdecl (alias); pushdecl (alias);
} }
......
...@@ -273,6 +273,9 @@ cp_dump_tree (dump_info, t) ...@@ -273,6 +273,9 @@ cp_dump_tree (dump_info, t)
return 1; return 1;
} }
if (! IS_AGGR_TYPE (t))
break;
dump_child ("vfld", TYPE_VFIELD (t)); dump_child ("vfld", TYPE_VFIELD (t));
if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t)) if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t))
dump_string(di, "spec"); dump_string(di, "spec");
......
...@@ -561,7 +561,7 @@ wrap_cleanups_r (tp, walk_subtrees, data) ...@@ -561,7 +561,7 @@ wrap_cleanups_r (tp, walk_subtrees, data)
cleanup = TARGET_EXPR_CLEANUP (exp); cleanup = TARGET_EXPR_CLEANUP (exp);
if (cleanup) if (cleanup)
{ {
cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup); cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
TARGET_EXPR_CLEANUP (exp) = cleanup; TARGET_EXPR_CLEANUP (exp) = cleanup;
} }
...@@ -733,7 +733,7 @@ build_throw (exp) ...@@ -733,7 +733,7 @@ build_throw (exp)
return error_mark_node; return error_mark_node;
} }
exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp); exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
/* Prepend the allocation. */ /* Prepend the allocation. */
exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
if (temp_expr != void_zero_node) if (temp_expr != void_zero_node)
......
...@@ -1206,13 +1206,16 @@ expand_default_init (binfo, true_exp, exp, init, flags) ...@@ -1206,13 +1206,16 @@ expand_default_init (binfo, true_exp, exp, init, flags)
else else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
if (TREE_CODE (init) == TRY_CATCH_EXPR) if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
/* We need to protect the initialization of a catch parm /* We need to protect the initialization of a catch parm with a
with a call to terminate(), which shows up as a TRY_CATCH_EXPR call to terminate(), which shows up as a MUST_NOT_THROW_EXPR
around the TARGET_EXPR for the copy constructor. See around the TARGET_EXPR for the copy constructor. See
expand_start_catch_block. */ initialize_handler_parm. */
TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp, {
TREE_OPERAND (init, 0)); TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
TREE_OPERAND (init, 0));
TREE_TYPE (init) = void_type_node;
}
else else
init = build (INIT_EXPR, TREE_TYPE (exp), exp, init); init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
TREE_SIDE_EFFECTS (init) = 1; TREE_SIDE_EFFECTS (init) = 1;
...@@ -2652,10 +2655,14 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete) ...@@ -2652,10 +2655,14 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
if (controller) if (controller)
{ {
TREE_OPERAND (controller, 1) = body; TREE_OPERAND (controller, 1) = body;
return controller; body = controller;
} }
else
return cp_convert (void_type_node, body); 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 cp_convert (void_type_node, body);
} }
/* Create an unnamed variable of the indicated TYPE. */ /* Create an unnamed variable of the indicated TYPE. */
...@@ -2693,7 +2700,7 @@ get_temp_regvar (type, init) ...@@ -2693,7 +2700,7 @@ get_temp_regvar (type, init)
decl = create_temporary_var (type); decl = create_temporary_var (type);
if (building_stmt_tree ()) if (building_stmt_tree ())
add_decl_stmt (decl); add_decl_stmt (decl);
if (!building_stmt_tree ()) else
SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1)); SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
......
...@@ -93,13 +93,7 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue) ...@@ -93,13 +93,7 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
allow_cast_as_lvalue); allow_cast_as_lvalue);
case NOP_EXPR: case NOP_EXPR:
/* If expression doesn't change the type, we consider it as an if (allow_cast_as_lvalue)
lvalue even when cast_as_lvalue extension isn't selected.
That's because parts of the compiler are alleged to be sloppy
about sticking in NOP_EXPR node for no good reason. */
if (allow_cast_as_lvalue ||
same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
return lvalue_p_1 (TREE_OPERAND (ref, 0), return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues, treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue); allow_cast_as_lvalue);
...@@ -179,9 +173,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue) ...@@ -179,9 +173,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
case CALL_EXPR: case CALL_EXPR:
case VA_ARG_EXPR: case VA_ARG_EXPR:
return ((treat_class_rvalues_as_lvalues /* Any class-valued call would be wrapped in a TARGET_EXPR. */
&& IS_AGGR_TYPE (TREE_TYPE (ref))) return clk_none;
? clk_class : clk_none);
case FUNCTION_DECL: case FUNCTION_DECL:
/* All functions (except non-static-member functions) are /* All functions (except non-static-member functions) are
...@@ -2353,13 +2346,16 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_, ...@@ -2353,13 +2346,16 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
/* We have a named return value; copy the name and source /* We have a named return value; copy the name and source
position so we can get reasonable debugging information, and position so we can get reasonable debugging information, and
register the return variable as its equivalent. */ register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv); if (TREE_CODE (var) == VAR_DECL)
DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv); {
DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv); DECL_NAME (var) = DECL_NAME (nrv);
/* Don't lose initialization info. */ DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
DECL_INITIAL (var) = DECL_INITIAL (nrv); DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
/* Don't forget that it needs to go in the stack. */ /* Don't lose initialization info. */
TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv); DECL_INITIAL (var) = DECL_INITIAL (nrv);
/* Don't forget that it needs to go in the stack. */
TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
}
splay_tree_insert (decl_map, splay_tree_insert (decl_map,
(splay_tree_key) nrv, (splay_tree_key) nrv,
......
...@@ -7002,7 +7002,11 @@ fold (expr) ...@@ -7002,7 +7002,11 @@ fold (expr)
/* Avoid adding NOP_EXPRs in case this is an lvalue. */ /* Avoid adding NOP_EXPRs in case this is an lvalue. */
if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type)) if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
comp_type = type; {
comp_type = type;
comp_op0 = arg1;
comp_op1 = arg2;
}
switch (comp_code) switch (comp_code)
{ {
......
...@@ -394,7 +394,8 @@ copy_decl_for_inlining (decl, from_fn, to_fn) ...@@ -394,7 +394,8 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl); DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
/* The new variable/label has no RTL, yet. */ /* The new variable/label has no RTL, yet. */
SET_DECL_RTL (copy, NULL_RTX); if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
SET_DECL_RTL (copy, NULL_RTX);
/* These args would always appear unused, if not for this. */ /* These args would always appear unused, if not for this. */
TREE_USED (copy) = 1; TREE_USED (copy) = 1;
...@@ -405,10 +406,10 @@ copy_decl_for_inlining (decl, from_fn, to_fn) ...@@ -405,10 +406,10 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
; ;
else if (DECL_CONTEXT (decl) != from_fn) else if (DECL_CONTEXT (decl) != from_fn)
/* Things that weren't in the scope of the function we're inlining /* Things that weren't in the scope of the function we're inlining
from aren't in the scope we're inlining too, either. */ from aren't in the scope we're inlining to, either. */
; ;
else if (TREE_STATIC (decl)) else if (TREE_STATIC (decl))
/* Function-scoped static variables should say in the original /* Function-scoped static variables should stay in the original
function. */ function. */
; ;
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment