Patchwork C++ PATCH to avoid double copying of default arguments

login
register
mail settings
Submitter Jason Merrill
Date Sept. 20, 2011, 7:32 p.m.
Message ID <4E78EA3E.1080201@redhat.com>
Download mbox | patch
Permalink /patch/115626/
State New
Headers show

Comments

Jason Merrill - Sept. 20, 2011, 7:32 p.m.
While working on something else I noticed that we were copying the trees 
in a default argument twice: once in break_out_target_exprs and then 
again with an explicit unshare_expr.  So I removed the redundant 
unshare_expr.  This didn't cause any regressions by itself, but just to 
be safe I also changed bot_manip to copy everything.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 53528dc80860cd96862c008501f3ad419bcaa7d5
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 15 15:13:33 2011 -0400

    	* call.c (convert_default_arg): Avoid redundant copy.
    	* tree.c (bot_manip): Copy everything.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 873b48b..b616cff 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6130,6 +6130,8 @@  convert_default_arg (tree type, tree arg, tree fn, int parmnum)
 
      we must not perform access checks here.  */
   push_deferring_access_checks (dk_no_check);
+  /* We must make a copy of ARG, in case subsequent processing
+     alters any part of it.  */
   arg = break_out_target_exprs (arg);
   if (TREE_CODE (arg) == CONSTRUCTOR)
     {
@@ -6140,14 +6142,6 @@  convert_default_arg (tree type, tree arg, tree fn, int parmnum)
     }
   else
     {
-      /* We must make a copy of ARG, in case subsequent processing
-	 alters any part of it.  For example, during gimplification a
-	 cast of the form (T) &X::f (where "f" is a member function)
-	 will lead to replacing the PTRMEM_CST for &X::f with a
-	 VAR_DECL.  We can avoid the copy for constants, since they
-	 are never modified in place.  */
-      if (!CONSTANT_CLASS_P (arg))
-	arg = unshare_expr (arg);
       arg = convert_for_initialization (0, type, arg, LOOKUP_IMPLICIT,
 					ICR_DEFAULT_ARGUMENT, fn, parmnum,
                                         tf_warning_or_error);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9987953..a9e1a26 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1865,9 +1865,13 @@  bot_manip (tree* tp, int* walk_subtrees, void* data)
 
   if (!TYPE_P (t) && TREE_CONSTANT (t) && !TREE_SIDE_EFFECTS (t))
     {
-      /* There can't be any TARGET_EXPRs or their slot variables below
-	 this point.  */
+      /* There can't be any TARGET_EXPRs or their slot variables below this
+	 point.  But we must make a copy, in case subsequent processing
+	 alters any part of it.  For example, during gimplification a cast
+	 of the form (T) &X::f (where "f" is a member function) will lead
+	 to replacing the PTRMEM_CST for &X::f with a VAR_DECL.  */
       *walk_subtrees = 0;
+      *tp = unshare_expr (t);
       return NULL_TREE;
     }
   if (TREE_CODE (t) == TARGET_EXPR)
@@ -1928,8 +1932,8 @@  bot_replace (tree* t,
 
 /* When we parse a default argument expression, we may create
    temporary variables via TARGET_EXPRs.  When we actually use the
-   default-argument expression, we make a copy of the expression, but
-   we must replace the temporaries with appropriate local versions.  */
+   default-argument expression, we make a copy of the expression
+   and replace the temporaries with appropriate local versions.  */
 
 tree
 break_out_target_exprs (tree t)