re PR tree-optimization/16115 (double-destruction problem with argument passing via...
authorJason Merrill <jason@redhat.com>
Sun, 18 Jul 2004 05:44:18 +0000 (01:44 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 18 Jul 2004 05:44:18 +0000 (01:44 -0400)
        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

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-gimplify.c
gcc/cp/decl.c
gcc/stor-layout.c
gcc/tree.h

index afea2890af88ebee939e76c2043e577e9b830aec..e279ea24f10cc4682c153e22754c29ea2d876489 100644 (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.
index 1e0bec12ccbf61ae95d2083c421eb21027392f8a..0108c2954940d0b4b58dee9ab1a1938b25b2234d 100644 (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.
index d2a17d9a7ed4ea7318e9e2925f64c5ee18894554..0e734b80179143e14d34c33ab5e6be39c455c2cc 100644 (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)
index db88e052b4df79c2de1536fdaa237002fe483e93..ed0a6a19d41901f7d8de08e34f768e760b8ad4bb 100644 (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);
index 6279eb5d9b7401b2f5e4c3ecad73fe2697ef507a..874cfcba1508843a0fa3d45d0891bb5a64831409 100644 (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 ();
+    }
 }
 
 \f
index 689768536af17a88f5f97a08000d2b60c00f24af..0ca26c238f766baafe5f8a9dcdf057fa3234418e 100644 (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);
+}
 \f
 /* Hook for a front-end function that can modify the record layout as needed
    immediately before it is finalized.  */
index 31e117312fa8e2d6b71971dafa66ab00e3fa556f..9871387c7e390afa930f4ffa97dec6c216bf4485 100644 (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 */