This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/39480


It's pedantically invalid to call memcpy to copy an object to itself, and apparently it even breaks on some targets. So avoid doing this. The best solution is for me to fix 22488 so we can go back to using a MODIFY_EXPR for copying the base subobject...

Tested x86_64-pc-linux-gnu, applying to trunk, 4.4 and 4.3.


2009-04-09  Jason Merrill  <jason@redhat.com>

	PR c++/39480
	* call.c (build_over_call): Don't call memcpy if the target is
	the same as the source.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 869146e..ef7c045 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5396,14 +5396,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	     instead of an explicit call to memcpy.  */
 	
 	  tree arg0, arg1, arg2, t;
+	  tree test = NULL_TREE;
 
 	  arg2 = TYPE_SIZE_UNIT (as_base);
 	  arg1 = arg;
 	  arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain);
+
+	  if (!(optimize && flag_tree_ter))
+	    {
+	      /* When TER is off get_pointer_alignment returns 0, so a call
+		 to __builtin_memcpy is expanded as a call to memcpy, which
+		 is invalid with identical args.  When TER is on it is
+		 expanded as a block move, which should be safe.  */
+	      arg0 = save_expr (arg0);
+	      arg1 = save_expr (arg1);
+	      test = build2 (EQ_EXPR, boolean_type_node, arg0, arg1);
+	    }
 	  t = implicit_built_in_decls[BUILT_IN_MEMCPY];
 	  t = build_call_n (t, 3, arg0, arg1, arg2);
 
 	  t = convert (TREE_TYPE (arg0), t);
+	  if (test)
+	    t = build3 (COND_EXPR, TREE_TYPE (t), test, arg0, t);
 	  val = cp_build_indirect_ref (t, 0, complain);
 	}
 
diff --git a/gcc/testsuite/g++.dg/init/copy7.C b/gcc/testsuite/g++.dg/init/copy7.C
new file mode 100644
index 0000000..f4364f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/copy7.C
@@ -0,0 +1,32 @@
+// PR c++/39480
+// It isn't always safe to call memcpy with identical arguments.
+// { dg-do run }
+
+extern "C" void abort();
+extern "C" void *
+memcpy(void *dest, void *src, __SIZE_TYPE__ n)
+{
+  abort();
+}
+
+struct A
+{
+  double d[10];
+};
+
+struct B: public A
+{
+  char bc;
+};
+
+B b;
+
+void f(B *a1, B* a2)
+{
+  *a1 = *a2;
+}
+
+int main()
+{
+  f(&b,&b);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]