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:
parent
b52cf5a743
commit
d8472c75e8
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
17
gcc/tree.h
17
gcc/tree.h
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue