re PR tree-optimization/16115 (double-destruction problem with argument passing via temporary (breaks auto_ptr))

PR c++/16115
        * stor-layout.c (relayout_decl): New fn.
        * tree.h: Declare it.
        (DECL_BY_REFERENCE): New macro.
        * cp/call.c (type_passed_as): Make the invisible reference type
        __restrict.
        * cp/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.
        * cp/decl.c (store_parm_decls): Don't generate any code for clones.

From-SVN: r84887
This commit is contained in:
Jason Merrill 2004-07-18 01:44:18 -04:00 committed by Jason Merrill
parent b52cf5a743
commit d8472c75e8
7 changed files with 130 additions and 18 deletions

View File

@ -1,3 +1,10 @@
2004-07-17 Jason Merrill <jason@redhat.com>
PR c++/16115
* stor-layout.c (relayout_decl): New fn.
* tree.h: Declare it.
(DECL_BY_REFERENCE): New macro.
2004-07-17 Eric Botcazou <ebotcazou@act-europe.fr>
* libgcc2.c (__enable_execute_stack): New symbol.

View File

@ -1,3 +1,15 @@
2004-07-17 Jason Merrill <jason@redhat.com>
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 <jsm@polyomino.org.uk>
* cp-tree.h (builtin_function): Declare.

View File

@ -4503,7 +4503,11 @@ type_passed_as (tree type)
{
/* Pass classes with copy ctors by invisible reference. */
if (TREE_ADDRESSABLE (type))
type = build_reference_type (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)

View File

@ -29,7 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-common.h"
#include "toplev.h"
#include "tree-gimple.h"
#include "hashtab.h"
/* Genericize a TRY_BLOCK. */
@ -264,31 +264,88 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
return ret;
}
/* Genericize a CLEANUP_STMT. This just turns into a TRY_FINALLY or
TRY_CATCH depending on whether it's EH-only. */
static inline bool
is_invisiref_parm (tree t)
{
return (TREE_CODE (t) == PARM_DECL
&& DECL_BY_REFERENCE (t));
}
/* Perform any pre-gimplification lowering of C++ front end trees to
GENERIC. */
static tree
gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
{
tree stmt = *stmt_p;
htab_t htab = (htab_t) data;
void **slot;
if (DECL_P (stmt) || TYPE_P (stmt))
if (is_invisiref_parm (stmt))
{
*stmt_p = build_fold_indirect_ref (stmt);
*walk_subtrees = 0;
return NULL;
}
/* Other than invisiref parms, don't walk the same tree twice. */
slot = htab_find_slot (htab, stmt, INSERT);
if (*slot)
{
*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 (DECL_P (stmt) || TYPE_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 = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR,
void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt));
*slot = *stmt_p;
return NULL;
}
void
cp_genericize (tree fndecl)
{
/* 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. */
walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL);
tree t;
htab_t htab;
/* Fix up the types of parms passed by invisible reference. */
for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
{
if (DECL_BY_REFERENCE (t))
abort ();
if (TREE_ADDRESSABLE (TREE_TYPE (t)))
{
if (DECL_ARG_TYPE (t) == TREE_TYPE (t))
abort ();
DECL_BY_REFERENCE (t) = 1;
TREE_TYPE (t) = DECL_ARG_TYPE (t);
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. */
htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, htab, NULL);
htab_delete (htab);
/* Do everything else. */
c_genericize (fndecl);

View File

@ -9991,11 +9991,16 @@ store_parm_decls (tree current_function_parms)
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 ();
/* 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 ();
}
}

View File

@ -524,6 +524,20 @@ layout_decl (tree decl, unsigned int known_align)
SET_DECL_RTL (decl, rtl);
}
}
/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
a previous call to layout_decl and calls it again. */
void
relayout_decl (tree decl)
{
DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
DECL_MODE (decl) = VOIDmode;
DECL_ALIGN (decl) = 0;
SET_DECL_RTL (decl, 0);
layout_decl (decl, 0);
}
/* Hook for a front-end function that can modify the record layout as needed
immediately before it is finalized. */

View File

@ -234,6 +234,8 @@ struct tree_common GTY(())
..._DECL
CALL_EXPR_HAS_RETURN_SLOT_ADDR in
CALL_EXPR
DECL_BY_REFERENCE in
PARM_DECL, RESULT_DECL
protected_flag:
@ -855,6 +857,10 @@ extern void tree_operand_check_failed (int, enum tree_code,
argument list. */
#define CALL_EXPR_HAS_RETURN_SLOT_ADDR(NODE) ((NODE)->common.private_flag)
/* In a RESULT_DECL or PARM_DECL, means that it is passed by invisible
reference (and the TREE_TYPE is a pointer to the true type). */
#define DECL_BY_REFERENCE(NODE) (DECL_CHECK (NODE)->common.private_flag)
/* In a CALL_EXPR, means that the call is the jump from a thunk to the
thunked-to function. */
#define CALL_FROM_THUNK_P(NODE) ((NODE)->common.protected_flag)
@ -2976,6 +2982,11 @@ extern tree type_hash_canon (unsigned int, tree);
extern void layout_decl (tree, unsigned);
/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
a previous call to layout_decl and calls it again. */
extern void relayout_decl (tree);
/* Return the mode for data of a given size SIZE and mode class CLASS.
If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
The value is BLKmode if no other mode is found. This is like
@ -3659,11 +3670,13 @@ extern void dwarf2out_return_save (const char *, HOST_WIDE_INT);
extern void dwarf2out_return_reg (const char *, unsigned);
/* In tree-inline.c */
/* The type of a callback function for walking over tree structure. */
typedef tree (*walk_tree_fn) (tree *, int *, void *);
tree walk_tree (tree*, walk_tree_fn, void*, void*);
tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
extern tree walk_tree (tree*, walk_tree_fn, void*, void*);
extern tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
/* In tree-dump.c */