aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/cp-gimplify.c77
-rw-r--r--gcc/cp/decl.c15
-rw-r--r--gcc/stor-layout.c14
-rw-r--r--gcc/tree.h17
7 files changed, 130 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index afea289..e279ea2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1e0bec1..0108c29 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d2a17d9..0e734b8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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)
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index db88e05..ed0a6a1 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6279eb5..874cfcb 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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 ();
+ }
}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 6897685..0ca26c2 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -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. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 31e1173..9871387 100644
--- a/gcc/tree.h
+++ b/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 */