[PATCH] Fix C++ strict-aliasing issues with memcpy folding

Richard Guenther rguenther@suse.de
Fri Jan 22 16:10:00 GMT 2010


This fixes the bogus aliasing we introduce for memcpy folding for C++
code and LTO.  This allows fixing std::functional aliasing issues
using memcpy.

Other than C, C++ allows the dynamic type of an object with a declared
type to change.  This is used both from our standard library
implementation and from its boost roots.  While I can't find C++
standard wording on the effect of memcpy to the dynamic type of
an object with a declared type the only reasonable assumption is
that the dynamic type, if any, is transfered (which, surprisingly
leaves us with the GCC union type-punning way of doing
type-punning in C++).

For 4.6 I hope to get the folding back when it is safe, determined
by tracking dynamic type changes in a to-be-written alignment
tracking/propagation pass.

Bootstrap and regtest on x86_64-unknown-linux-gnu pending.

Ok?

Thanks,
Richard.

2010-01-22  Richard Guenther  <rguenther@suse.de>

	PR middle-end/42834
	* c-opts.c (c_common_post_options): Adjust flag_strict_aliasing
	to 2 if it was set for C++.
	* builtins.c (fold_builtin_memory_op): Disable memcpy
	inline-expansion for flag_strict_aliasing >= 2.

	lto/
	* lto-lang.c (lto_post_options): Use C++ strict-aliasing mode.

	* g++.dg/torture/pr42834.C: New testcase.

Index: gcc/c-opts.c
===================================================================
*** gcc/c-opts.c	(revision 156153)
--- gcc/c-opts.c	(working copy)
*************** c_common_post_options (const char **pfil
*** 1060,1065 ****
--- 1060,1070 ----
    if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
      flag_exceptions = 1;
  
+   /* In C++ TBAA is less strict than in C as it allows the dynamic type
+      of objects with a declared type to change.  */
+   if (c_dialect_cxx ())
+     flag_strict_aliasing = flag_strict_aliasing ? 2 : 0;
+ 
    /* -Wextra implies the following flags
       unless explicitly overridden.  */
    if (warn_type_limits == -1)
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c	(revision 156153)
--- gcc/builtins.c	(working copy)
*************** fold_builtin_memory_op (location_t loc,
*** 8244,8249 ****
--- 8244,8257 ----
  	  return NULL_TREE;
  	}
  
+       /* The C++ standard allows the dynamic type of an object to be
+ 	 different from its declared type, so memcpy has to transfer
+ 	 the effective type even in that case.  We can't do any
+ 	 meaningful folding with the knowledge of just the memcpy
+ 	 statement here in that case.  */
+       if (flag_strict_aliasing >= 2)
+ 	return NULL_TREE;
+ 
        if (!host_integerp (len, 0))
  	return NULL_TREE;
        /* FIXME:
Index: gcc/testsuite/g++.dg/torture/pr42834.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr42834.C	(revision 0)
--- gcc/testsuite/g++.dg/torture/pr42834.C	(revision 0)
***************
*** 0 ****
--- 1,13 ----
+ // { dg-do run }
+ 
+ int main()
+ {
+   int i = 0;
+   float f = 1.0;
+   int *p = (int *)&f;
+   __builtin_memcpy (&i, p, 4);
+   if (*(float *)&i != 1.0)
+     __builtin_abort ();
+   return 0;
+ }
+ 
Index: gcc/lto/lto-lang.c
===================================================================
*** gcc/lto/lto-lang.c	(revision 156153)
--- gcc/lto/lto-lang.c	(working copy)
*************** lto_post_options (const char **pfilename
*** 674,679 ****
--- 674,682 ----
       support.  */
    flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
  
+   /* Use the more stricter C++ mode.  */
+   flag_strict_aliasing = flag_strict_aliasing ? 2 : 0;
+ 
    lto_read_all_file_options ();
  
    /* Initialize the compiler back end.  */



More information about the Gcc-patches mailing list