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]

Ping^2: Patch: Implementation of -Wstrict-aliasing, take 2


Original post: http://gcc.gnu.org/ml/gcc-patches/2007-02/msg01477.html


Changes from take 1 ===================

I believe the patch addresses all the comments and recommendations. The major
changes from the previous submission are:
1. Keep front end checks and avoid duplicates between frontend and backend.
2. Replace the --param based interface with warning levels.



Patch Description =================

The proposed patch adds an implementation of -Wstrict-aliasing in the
backend, and updates the -Wstrict-aliasing interface accordingly.

The current implementation of -Wstrict-aliasing looks at a single expression
at once. Although it does OK given the limited scope, it has several drawbacks.
First, it produces false positives, i.e., it warns when it should not.
For instance, it warns about pointer conversions even when the pointers
are never dereferenced.
Second, it has many false negatives, i.e., it does not warn when it should.
It does not warn when an address is not taken, for instance:
float *f = ...
int *i = (int*)f;
*f = ...
... = *i


The proposed implementation lives in the backend and is based on flow-sensitive
points-to information, which is computed by analyzing the entire source of
each function. It is not perfect (the problem is undecidable), but it improves
in both directions: it checks whether pointers get dereferenced and
it detects aliasing across multiple statements.


The frontend was also modified to work better with the new analysis in the
backend (match levels, avoid duplicates).

Here is a brief description of proposed warning levels.  The default is 3.
1: All pointer conversions are flagged if the source and
 destination types are incompatible according to
 alias_sets_might_conflict_p.  Runs in frontend only.
2: All pointer conversions from "address taken" are flagged if the source
 and destination types are incompatible according to
 alias_sets_might_conflict_p.  Runs in frontend only.
3: Immediate dereferences of conversions from "address taken" are flagged
 if the source and destination are incompatible according to
 alias_sets_conflict_p.  This takes place in the frontend.
 Also, warn about aliased named objects that are referenced when
 their types are incompatible according to alias_sets_conflict_p.
 This runs in the backend.
4: Same as 3, but also include analysis of unnamed objects, such as those
 created by calls to malloc.

More information about the benefits and limitations of the new implementation
can be found in file gcc/tree-ssa-alias-warnings.c



Bootstrapping and Testing =========================

The patch was tested by bootstrapping on i686-linux and
by running 'make -k check'.
I could not build the fortran frontend with or without the patch,
but did build c,c++,objc,java successfully.
There was no difference in diagnostics without and with the patch.


gcc/ChangeLog =============

2007-02-14 Silvius Rus <rus@google.com>

  * Makefile.in (OBJS-common): Add tree-ssa-alias-warnings.o.
  * c-common.c (strict_aliasing_warning): Modify -Wstrict-aliasing logic.
  * c-common.h (strict_aliasing_warning): Change return type.
  * c-opts.c (c_common_handle_option): Add call to set_Wstrict_aliasing.
  * c-typeck.c (build_indirect_ref): Add call to strict_aliasing_warning.
  (build_c_cast): Condition call to strict_aliasing_warning.
  * doc/invoke.texi: Update description of -Wstrict-aliasing[=n].
  * flags.h (set_Wstrict_aliasing): Declare.
  * opts.c (set_Wstrict_alising): Define, add call to.
  * tree-flow.h (strict_aliasing_warning_backend): Declare.
  * tree-ssa-alias-warnings.c: New file.
  * tree-ssa-alias.c (compute_may_aliases): Add call to
  strict_aliasing_warning_backend.


gcc/cp/ChangeLog ================

2007-02-14 Silvius Rus <rus@google.com>

  * cp/typeck.c (build_indirect_ref): Add call to strict_aliasing_warning.
  (build_reinterpret_cast_1): Condition call to
  strict_aliasing_warning.


gcc/testsuite/ChangeLog =======================

2007-02-14 Silvius Rus <rus@google.com>

  * gcc.dg/Wstrict-aliasing-bogus-const-ptr-nonconst-ptr.c: New test.
  * gcc.dg/Wstrict-aliasing-bogus-never-dereferenced.c: New test.
  * gcc.dg/Wstrict-aliasing-bogus-struct-included.c: New test.
  * gcc.dg/Wstrict-aliasing-converted-assigned.c: New test.
  * gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c: New test.
  * gc.dg/Wstrict-aliasing-malloc.c: New test.
  * gcc.dg/alias-1.c: Update option: -Wstrict-aliasing=2.
  * gcc.dg/alias-9.c: Update option: -Wstrict-aliasing=2.
  * g++.dg/warn/Wstrict-aliasing-7.C: Update option: -Wstrict-aliasing=2.
  * g++.dg/warn/Wstrict-aliasing-bogus-base-derived.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-char-1.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-const.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-nested-arrays.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-signed-unsigned.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-struct-included.C: New test.
  * g++.dg/warn/Wstrict-aliasing-bogus-union.C: New test.
  * g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C: New test.
  * g++.dg/warn/Wstrict-aliasing-malloc.C: New test.


==== trunk/gcc/Makefile.in#35 - /home/rus/local/gcc/ggcc/gcc/Makefile.in ====
--- old/gcc/Makefile.in#35	2007-02-13 18:03:17.000000000 -0800
+++ new/gcc/Makefile.in	2007-02-11 14:01:41.000000000 -0800
@@ -1099,6 +1099,7 @@ OBJS-common = \
 	tree-sra.o \
 	tree-ssa-address.o \
 	tree-ssa-alias.o \
+	tree-ssa-alias-warnings.o \
 	tree-ssa-ccp.o \
 	tree-ssa-coalesce.o \
 	tree-ssa-copy.o \
@@ -2157,6 +2158,11 @@ tree-ssa-loop-im.o : tree-ssa-loop-im.c 
 tree-ssa-math-opts.o : tree-ssa-math-opts.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(TIMEVAR_H) tree-pass.h $(TM_H) $(FLAGS_H) \
    alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H)
+tree-ssa-alias-warnings.o : tree-ssa-alias-warnings.c \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(TREE_DUMP_H) \
+   $(TREE_FLOW_H) $(PARAMS_H) $(FUNCTION_H) $(EXPR_H) toplev.h \
+   tree-ssa-structalias.h tree-ssa-propagate.h langhooks.h alloc-pool.h \
+   $(DIAGNOSTIC_H)
 tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(TREE_INLINE_H) $(FLAGS_H) \
    $(FUNCTION_H) $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h \
==== trunk/gcc/c-common.c#20 - /home/rus/local/gcc/ggcc/gcc/c-common.c ====
--- old/gcc/c-common.c#20	2007-02-13 18:03:17.000000000 -0800
+++ new/gcc/c-common.c	2007-02-16 13:41:51.000000000 -0800
@@ -971,10 +971,10 @@ overflow_warning (tree value)
    strict aliasing mode is in effect. OTYPE is the original
    TREE_TYPE of EXPR, and TYPE the type we're casting to. */
 
-void
+bool
 strict_aliasing_warning (tree otype, tree type, tree expr)
 {
-  if (flag_strict_aliasing && warn_strict_aliasing
+  if (flag_strict_aliasing && (warn_strict_aliasing > 1)
       && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
       && TREE_CODE (expr) == ADDR_EXPR
       && (DECL_P (TREE_OPERAND (expr, 0))
@@ -983,23 +983,51 @@ strict_aliasing_warning (tree otype, tre
     {
       /* Casting the address of an object to non void pointer. Warn
          if the cast breaks type based aliasing.  */
-      if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
-        warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
-                 "might break strict-aliasing rules");
+      if (!COMPLETE_TYPE_P (TREE_TYPE (type))
+          && warn_strict_aliasing == 2)
+	{
+	  warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+		   "might break strict-aliasing rules");
+	  return true;
+	}
       else
         {
-          HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+          HOST_WIDE_INT set1 = 
+	    get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
           HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
 
           if (!alias_sets_conflict_p (set1, set2))
-            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
-                     "pointer will break strict-aliasing rules");
-          else if (warn_strict_aliasing > 1
-                  && !alias_sets_might_conflict_p (set1, set2))
-            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
-                     "pointer might break strict-aliasing rules");
+	    {
+	      warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+		       "pointer will break strict-aliasing rules");
+	      return true;
+	    }
+          else if (warn_strict_aliasing == 2
+		   && !alias_sets_might_conflict_p (set1, set2))
+	    {
+	      warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+		       "pointer might break strict-aliasing rules");
+	      return true;
+	    }
         }
     }
+  else
+    if (flag_strict_aliasing && (warn_strict_aliasing == 1)
+        && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
+        && !VOID_TYPE_P (TREE_TYPE (type)) && !VOID_TYPE_P (TREE_TYPE (otype)))
+    {
+      HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (otype));
+      HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+      if (!COMPLETE_TYPE_P(type)
+	  || !alias_sets_might_conflict_p (set1, set2))
+	{
+	  warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+		   "pointer might break strict-aliasing rules");
+	  return true;
+	}
+    }
+
+  return false;
 }
 
 /* Print a warning about if (); or if () .. else; constructs
==== trunk/gcc/c-common.h#8 - /home/rus/local/gcc/ggcc/gcc/c-common.h ====
--- old/gcc/c-common.h#8	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/c-common.h	2007-02-11 15:21:12.000000000 -0800
@@ -669,7 +669,7 @@ extern void binary_op_error (enum tree_c
 extern tree fix_string_type (tree);
 struct varray_head_tag;
 extern void constant_expression_warning (tree);
-extern void strict_aliasing_warning (tree, tree, tree);
+extern bool strict_aliasing_warning (tree, tree, tree);
 extern void empty_body_warning (tree, tree);
 extern tree convert_and_check (tree, tree);
 extern void overflow_warning (tree);
==== trunk/gcc/c-opts.c#12 - /home/rus/local/gcc/ggcc/gcc/c-opts.c ====
--- old/gcc/c-opts.c#12	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/c-opts.c	2007-02-12 16:47:57.000000000 -0800
@@ -393,7 +393,7 @@ c_common_handle_option (size_t scode, co
       if (c_dialect_cxx ())
 	warn_sign_compare = value;
       warn_switch = value;
-      warn_strict_aliasing = value;
+      set_Wstrict_aliasing (value);
       warn_string_literal_comparison = value;
       warn_always_true = value;
       warn_array_bounds = value;
==== trunk/gcc/c-typeck.c#12 - /home/rus/local/gcc/ggcc/gcc/c-typeck.c ====
--- old/gcc/c-typeck.c#12	2007-02-14 15:48:01.000000000 -0800
+++ new/gcc/c-typeck.c	2007-02-14 15:47:30.000000000 -0800
@@ -1876,6 +1876,19 @@ build_indirect_ref (tree ptr, const char
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
+      if (TREE_CODE (pointer) == CONVERT_EXPR
+          || TREE_CODE (pointer) == NOP_EXPR
+          || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
+	{
+	  /* If a warning is issued, mark it to avoid duplicates from
+	     the backend.  This only needs to be done at
+	     warn_strict_aliasing > 2.  */
+	  if (warn_strict_aliasing > 2)
+	    if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+					 type, TREE_OPERAND (pointer, 0)))
+	      TREE_NO_WARNING (pointer) = 1;
+	}
+
       if (TREE_CODE (pointer) == ADDR_EXPR
 	  && (TREE_TYPE (TREE_OPERAND (pointer, 0))
 	      == TREE_TYPE (type)))
@@ -3562,7 +3575,8 @@ build_c_cast (tree type, tree expr)
 	warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
 		 "of different size");
 
-      strict_aliasing_warning (otype, type, expr);
+      if (warn_strict_aliasing <= 2)
+        strict_aliasing_warning (otype, type, expr);
 
       /* If pedantic, warn for conversions between function and object
 	 pointer types, except for converting a null pointer constant
==== trunk/gcc/cp/typeck.c#15 - /home/rus/local/gcc/ggcc/gcc/cp/typeck.c ====
--- old/gcc/cp/typeck.c#15	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/cp/typeck.c	2007-02-12 11:52:37.000000000 -0800
@@ -2352,6 +2352,19 @@ build_indirect_ref (tree ptr, const char
 	 types.  */
       tree t = canonical_type_variant (TREE_TYPE (type));
 
+      if (TREE_CODE (ptr) == CONVERT_EXPR
+          || TREE_CODE (ptr) == NOP_EXPR
+          || TREE_CODE (ptr) == VIEW_CONVERT_EXPR)
+	{
+	  /* If a warning is issued, mark it to avoid duplicates from
+	     the backend.  This only needs to be done at
+	     warn_strict_aliasing > 2.  */
+	  if (warn_strict_aliasing > 2)
+	    if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (ptr, 0)),
+					 type, TREE_OPERAND (ptr, 0)))
+	      TREE_NO_WARNING (ptr) = 1;
+	}
+
       if (VOID_TYPE_P (t))
 	{
 	  /* A pointer to incomplete type (other than cv void) can be
@@ -5340,7 +5353,8 @@ build_reinterpret_cast_1 (tree type, tre
       /* We need to strip nops here, because the front end likes to
 	 create (int *)&a for array-to-pointer decay, instead of &a[0].  */
       STRIP_NOPS (sexpr);
-      strict_aliasing_warning (intype, type, sexpr);
+      if (warn_strict_aliasing <= 2)
+	strict_aliasing_warning (intype, type, sexpr);
 
       return fold_if_not_in_template (build_nop (type, expr));
     }
==== trunk/gcc/doc/invoke.texi#44 - /home/rus/local/gcc/ggcc/gcc/doc/invoke.texi ====
--- old/gcc/doc/invoke.texi#44	2007-02-14 15:48:01.000000000 -0800
+++ new/gcc/doc/invoke.texi	2007-02-16 10:57:33.000000000 -0800
@@ -247,7 +247,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wredundant-decls @gol
 -Wreturn-type  -Wsequence-point  -Wshadow @gol
 -Wsign-compare  -Wstack-protector @gol
--Wstrict-aliasing -Wstrict-aliasing=2 @gol
+-Wstrict-aliasing -Wstrict-aliasing=n @gol
 -Wstring-literal-comparison @gol
 -Wswitch  -Wswitch-default  -Wswitch-enum @gol
 -Wsystem-headers  -Wtrigraphs  -Wundef  -Wuninitialized @gol
@@ -2963,14 +2963,19 @@ It warns about code which might break th
 compiler is using for optimization.  The warning does not catch all
 cases, but does attempt to catch the more common pitfalls.  It is
 included in @option{-Wall}.
+It is equivalent to -Wstrict-aliasing=3
 
-@item -Wstrict-aliasing=2
-@opindex Wstrict-aliasing=2
+@item -Wstrict-aliasing=n
+@opindex Wstrict-aliasing=n
 This option is only active when @option{-fstrict-aliasing} is active.
 It warns about code which might break the strict aliasing rules that the
-compiler is using for optimization.  This warning catches more cases than
-@option{-Wstrict-aliasing}, but it will also give a warning for some ambiguous
-cases that are safe.
+compiler is using for optimization.  
+Higher levels correspond to higher accuracy (fewer false positives).
+Higher levels also correspond to more effort, similar to the way -O works.
+-Wstrict-aliasing is equivalent to -Wstrict-aliasing=3.
+Levels 1-3 are fully functional.  Level 4 is experimental, and  
+includes checks for aliasing of unnamed objects, such as those created
+by malloc.  Level 4 will run, and is most effective, with -fno-strict-aliasing.
 
 @item -Warray-bounds
 @opindex Wno-array-bounds
==== trunk/gcc/flags.h#4 - /home/rus/local/gcc/ggcc/gcc/flags.h ====
--- old/gcc/flags.h#4	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/flags.h	2007-02-12 16:50:59.000000000 -0800
@@ -102,6 +102,12 @@ extern bool extra_warnings;
 
 extern void set_Wunused (int setting);
 
+/* Nonzero to warn about type punning.  Used to set the default level of
+   -Wstrict-aliasing.  The external way to set the default level is to use
+   -Wstrict-aliasing=level.  */
+
+extern void set_Wstrict_aliasing (int level);
+
 /* Nonzero means warn about any objects definitions whose size is larger
    than N bytes.  Also want about function definitions whose returned
    values are larger than N bytes. The value N is in `larger_than_size'.  */
==== trunk/gcc/opts.c#9 - /home/rus/local/gcc/ggcc/gcc/opts.c ====
--- old/gcc/opts.c#9	2007-02-14 15:48:01.000000000 -0800
+++ new/gcc/opts.c	2007-02-14 15:47:35.000000000 -0800
@@ -1100,6 +1100,9 @@ common_handle_option (size_t scode, cons
       break;
 
     case OPT_Wstrict_aliasing:
+      set_Wstrict_aliasing (value);
+      break;
+
     case OPT_Wstrict_aliasing_:
       warn_strict_aliasing = value;
       break;
@@ -1453,6 +1456,20 @@ set_Wunused (int setting)
   warn_unused_value = setting;
 }
 
+/* Used to set the level of strict aliasing warnings, 
+   when no level is specified (i.e., when -Wstrict-aliasing, and not
+   -Wstrict-aliasing=level was given).
+   ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified,
+   and 0 otherwise.  After calling this function, wstrict_aliasing will be
+   set to the default value of -Wstrict_aliasing=level, currently 3.  */
+void
+set_Wstrict_aliasing (int onoff)
+{
+  gcc_assert (onoff == 0 || onoff == 1);
+  if (onoff != 0)
+    warn_strict_aliasing = 3;
+}
+
 /* The following routines are useful in setting all the flags that
    -ffast-math and -fno-fast-math imply.  */
 void
==== trunk/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-7.C#1 - /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-7.C ====
--- old/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-7.C#1	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-7.C	2007-02-14 15:40:28.000000000 -0800
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-Wstrict-aliasing -O2" } */
+/* { dg-options "-Wstrict-aliasing=2 -O2" } */
 
 int a[2];
 
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-base-derived.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-base-derived.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+class base {
+ public:
+  int x;
+};
+
+class derived: public base {
+ public:
+  int y;
+};
+
+base foo () {
+  derived d;
+  base* pb = &d;  /* { dg-bogus "base vs. derived" } */
+  pb->x = 1;
+
+  return d;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-char-1.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-char-1.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+int foo () {
+  int i;
+  char* c= reinterpret_cast<char*>(&i);  /* { dg-bogus "char" } */
+  c[1] = 1;
+  return i;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-const.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-const.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+int foo(int* p) {
+  const int& q = *p;  /* { dg-bogus "const vs. non-const" } */
+  *p = 1;
+  return q;
+}
+
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-nested-arrays.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-nested-arrays.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+int foo () {
+  int buffer[10][10];
+  int* pi = &buffer[0][0];  /* { dg-bogus "same element type" } */
+  *pi = 10;
+  return buffer[0][0];
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-signed-unsigned.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-signed-unsigned.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+int foo () {
+  int i;
+  unsigned int* pu = reinterpret_cast<unsigned int*> (&i);  /* { dg-bogus "signed vs. unsigned" } */
+  *pu = 1000000;
+  return i;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-struct-included.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-struct-included.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+struct S {
+  int i;
+  float f;
+};
+
+int foo () {
+  struct S s;
+  s.i = 7;
+  float* f = &s.f;  /* { dg-bogus "float included in struct S" } */
+  *f = 2.0;
+  return s.i + (int)s.f;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-union.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-union.C	2007-01-19 11:53:01.000000000 -0800
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+union U {
+  int i;
+  float f;
+};
+
+float foo () {
+  union U u;
+  float* f = &u.f;  /* { dg-bogus "unions are holy in GCC" } */
+  u.i = 2;
+  return *f;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C	2007-02-13 17:23:15.000000000 -0800
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+int foo() {
+  int x;
+  float& q = reinterpret_cast<float&> (x);  /* { dg-warning "type-punn" } */
+  q = 1.0;
+  return x;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-malloc.C ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-malloc.C	2007-02-16 10:25:11.000000000 -0800
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wstrict-aliasing=4 -fno-strict-aliasing" } */
+
+
+void* malloc(int);
+
+int foo ()
+{
+  void* mem = malloc (4);
+  int* pi = reinterpret_cast<int*> (mem);
+  float* pf = reinterpret_cast<float*> (mem);
+  *pf = 2.0;
+  return *pi+1;  /* { dg-warning "type-punn" } */
+}
+
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-const-ptr-nonconst-ptr.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-const-ptr-nonconst-ptr.c	2007-01-18 19:19:15.000000000 -0800
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+const int* foo (void)
+{
+  int *i;
+  const int** cpi = (const int**) &i; /* { dg-bogus "const vs. non-const" } */
+  i = 0;
+  return *cpi;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-never-dereferenced.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-never-dereferenced.c	2007-01-18 19:20:20.000000000 -0800
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+int foo ()
+{
+  int x = 10;
+  int *p;
+  float *q;
+
+  q = (float*) &x;  /* { dg-bogus "not referenced" } */
+
+  return x;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-struct-included.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-struct-included.c	2007-01-18 19:23:52.000000000 -0800
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+struct U
+{
+  float f;
+  int i;
+};
+
+
+int foo ()
+{
+  struct U u;
+  float *pf = (float*)&u;  /* { dg-bogus "float included in struct U" } */
+  *pf = 2.0;
+  return u.i;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c	2007-02-13 15:14:39.000000000 -0800
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-aliasing -fstrict-aliasing" } */
+
+
+int foo()
+{
+  int i;
+  *(long*)&i = 0;  /* { dg-warning "type-punn" } */
+  return i;
+}
==== (added) /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c	2007-02-13 15:06:45.000000000 -0800
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wstrict-aliasing -fstrict-aliasing" } */
+
+extern int flag;
+
+int foo() {
+
+  int x;
+  int y = 9;
+  float* q;
+  float* r;
+
+  if (flag) {
+    q = (float*) &x;  /* { dg-warning "type-punn" } */
+  } else {
+    q = (float*) &y;  /* { dg-warning "type-punn" } */
+  }
+
+  *q = 1.0;
+
+  return x;
+
+}
==== trunk/gcc/testsuite/gcc.dg/alias-1.c#1 - /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/alias-1.c ====
--- old/gcc/testsuite/gcc.dg/alias-1.c#1	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/testsuite/gcc.dg/alias-1.c	2007-02-13 15:09:08.000000000 -0800
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-Wstrict-aliasing -fstrict-aliasing" }
+// { dg-options "-Wstrict-aliasing=2 -fstrict-aliasing" }
 
 // Copyright (C) 2002 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 29 Sep 2002 <nathan@codesourcery.com>
==== trunk/gcc/testsuite/gcc.dg/alias-9.c#1 - /home/rus/local/gcc/ggcc/gcc/testsuite/gcc.dg/alias-9.c ====
--- old/gcc/testsuite/gcc.dg/alias-9.c#1	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/testsuite/gcc.dg/alias-9.c	2007-02-14 15:41:04.000000000 -0800
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-Wstrict-aliasing -O2" } */
+/* { dg-options "-Wstrict-aliasing=2 -O2" } */
 
 int a[2];
 
==== trunk/gcc/tree-flow.h#26 - /home/rus/local/gcc/ggcc/gcc/tree-flow.h ====
--- old/gcc/tree-flow.h#26	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/tree-flow.h	2007-02-11 14:02:21.000000000 -0800
@@ -741,6 +741,8 @@ extern tree create_tag_raw (enum tree_co
    definition, a function with this prototype is called.  */
 typedef bool (*walk_use_def_chains_fn) (tree, tree, void *);
 
+/* In tree-ssa-alias-warnings.c  */
+extern void strict_aliasing_warning_backend (void);
 
 /* In tree-ssa.c  */
 extern void init_tree_ssa (void);
==== (added) /home/rus/local/gcc/ggcc/gcc/tree-ssa-alias-warnings.c ====
--- /dev/null	2006-05-22 07:25:23.000000000 -0700
+++ new/gcc/tree-ssa-alias-warnings.c	2007-02-16 10:58:32.000000000 -0800
@@ -0,0 +1,1199 @@
+/* Strict aliasing checks.
+   Copyright (C) 2006,2007 Free Software Foundation, Inc.
+   Contributed by Silvius Rus <rus@google.com>.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "alloc-pool.h"
+#include "tree.h"
+#include "tree-dump.h"
+#include "tree-flow.h"
+#include "params.h"
+#include "function.h"
+#include "expr.h"
+#include "toplev.h"
+#include "diagnostic.h"
+#include "tree-ssa-structalias.h"
+#include "tree-ssa-propagate.h"
+#include "langhooks.h"
+
+/* Module to issue a warning when a program uses data through a type 
+   different from the type through which the data were defined.
+   Implements -Wstrict-aliasing and -Wstrict-aliasing=n.
+   Generally, -Wstrict-aliasing checks will only happen when -fstrict-aliasing
+   is present.  However, some checks may also happen with -fno-strict-aliasing
+   at -Wstrict-aliasing=4 (see the detailed discussion of level 4 below).
+
+   Our idea is that we can use the compiler to identify the occurrences 
+   of nonstandard aliasing, and report them to programmers. After they get 
+   fixed by programmers, the whole code base can be compiled at a higher 
+   optimization level.
+
+   Also, code that follows the standard is easier to maintain and port.
+   The current (as of November 2006) C and C++ language standards forbid 
+   accessing data of type A through an lvalue of another type B 
+   (with certain exceptions). See the C Standard ISO/IEC 9899:1999, 
+   section 6.5, paragraph 7, and the C++ Standard ISO/IEC 14882:1998, 
+   section 3.10, paragraph 15.
+
+   Example 1:*a is used as int but was defined as a float, *b.
+        int* a = ...;
+        float* b = reinterpret_cast<float*> (a);
+        *b = 2.0;
+        return *a
+
+   Unfortunately, the problem is in general undecidable if we take into 
+   account arithmetic expression such as array indices or pointer arithmetic.
+   (It is at least as hard as Peano arithmetic decidability.)
+   Even ignoring arithmetic, the problem is still NP-hard, because it is 
+   at least as hard as flow-insensitive may-alias analysis, which was proved 
+   NP-hard by Horwitz et al, TOPLAS 1997.
+
+   It is clear that we need to choose some heuristics.
+   Unfortunately, various users have different goals which correspond to
+   different time budgets so a common approach will not suit all.
+   We present the user with four effort/accuracy levels.  By accuracy, we mean
+   a common-sense mix of low count of false positives with a 
+   reasonably low number of false negatives.  We are heavily biased
+   towards false positives.
+   The effort (compilation time) is likely to increase with the level.
+
+   -Wstrict-aliasing=1
+   ===================
+   Most aggressive, least accurate.  Possibly useful when higher levels
+   do not warn but -fstrict-aliasing still breaks the code, as
+   it has very few false negatives.
+   Warn for all bad pointer conversions, even if never dereferenced.
+   Implemented in the front end (c-common.c).
+   Uses alias_sets_might_conflict to compare types.
+
+   -Wstrict-aliasing=2
+   ===================
+   Aggressive, not too precise.
+   May still have many false positives (not as many as level 1 though),
+   and few false negatives (but possibly more than level 1).
+   Runs only in the front end. Uses alias_sets_might_conflict to
+   compare types. Does not check for pointer dereferences.
+   Only warns when an address is taken. Warns about incomplete type punning.
+
+   -Wstrict-aliasing=3 (default)
+   ===================
+   Should have very few false positives and few false negatives.
+   Takes care of the common punn+dereference pattern in the front end: 
+   *(int*)&some_float.
+   Takes care of multiple statement cases in the back end, 
+   using flow-sensitive points-to information (-O required).
+   Uses alias_sets_conflict_p to compare types and only warns 
+   when the converted pointer is dereferenced.
+   Does not warn about incomplete type punning.
+
+   -Wstrict-aliasing=4
+   ===================
+   Variation on level 3, but uses techniques that increase 
+   overall accuracy, at the cost of slightly more false positives.
+   This is actually the most accurate overall, but the current 
+   implementation has some false positives during bootstrap, 
+   so it cannot be the default.
+   Runs in the front end and back end.  In addition to level 3, 
+   it reports aliases to unnamed variables, such as heap variables 
+   and structure fields.
+   Future improvements can be included either by modifying the 
+   implementation of level 4, or by adding higher levels.
+
+   This level will run (and is most effective) with -fno-strict-aliasing.
+   The reason is that points-to information of
+   unnamed objects (such as those created with malloc) gets tainted
+   by -fstrict-aliasing before we have a chance to check for warnings.
+   The following case can only be caught 
+   with -fno-strict-aliasing -Wstrict-aliasing:
+
+   Example 2.
+        void* mem = malloc (...);
+	int* pi = reinterpret_cast<int*> (mem);
+	float* b = reinterpret_cast<float*> (mem);
+	*b = 2.0;
+	return *pi+1;
+
+
+   In summary, expression level analysis is performed in the front-end,
+   and multiple-statement analysis is performed in the backend.
+   The remainder of this discussion is only about the backend analysis.
+
+   At this time, the implementation uses flow-sensitive points-to information.
+   Flow-sensitivity refers to the pointer, and not the object pointed.
+   For instance, we do not warn about the following case.
+
+   Example 3.
+        int* a = (int*)malloc (...);
+        float* b = reinterpret_cast<float*> (a);
+        *b = 2.0;
+        a = (int*)malloc (...);
+        return *a;
+
+   In SSA, it becomes clear that the INT value *A_2 referenced in the 
+   return statement is not aliased to the FLOAT defined through *B_1.
+        int* a_1 = (int*)malloc (...);
+        float* b_1 = reinterpret_cast<float*> (a_1);
+        *b_1 = 2.0;
+        a_2 = (int*)malloc (...);
+        return *a_2;
+
+
+   Limitations of the current implementation
+   =========================================
+
+   1. We do not check whether the two conflicting (de)references can
+   reach each other in the control flow sense.
+
+   Example 4.
+        void* raw = malloc (...);
+        if (...) {
+         float* b = reinterpret_cast<float*> (raw);
+         *b = 2.0;
+         return (int)*b;
+        } else {
+         int* a = reinterpret_cast<int*> (raw);
+         *a = 1;
+         return *a;
+
+   2. We do not check whether the two conflicting (de)references can
+   reach each other in the data flow sense.
+
+   Example 5.
+
+        int* a = ...;
+        float* b = reinterpret_cast<float*> (a);
+        *b = 2.0;
+        ... = *b;
+        *a = 1;
+        return *a
+
+   3. There are limitations with aliased structures.  Some of them
+   are due to the way field-level aliasing is represented in GCC.
+   Some features are simply not implemented yet, such as the prefix rule,
+   in which two fields of two different structures are allowed to overlap
+   if all the fields preceding (and including) them match.  
+
+   4. All analysis is intraprocedural.  */
+
+
+
+/* Get main type of tree TYPE, stripping array dimensions and qualifiers.  */
+
+static tree
+get_main_type (tree type)
+{
+  while (TREE_CODE (type) == ARRAY_TYPE)
+    type = TREE_TYPE (type);
+  return TYPE_MAIN_VARIANT (type);
+}
+
+
+/* Get the type of the given object.  If IS_PTR is true, get the type of the
+   object pointed to or referenced by OBJECT instead.
+   For arrays, return the element type.  Ignore all qualifiers.  */
+
+static tree
+get_otype (tree object, bool is_ptr)
+{
+  tree otype = TREE_TYPE (object);
+
+  if (is_ptr)
+    {
+      gcc_assert (POINTER_TYPE_P (otype));
+      otype = TREE_TYPE (otype);
+    }
+  return get_main_type (otype);
+}
+
+
+/* Return true if tree TYPE is struct, class or union.  */
+
+static bool
+struct_class_union_p (tree type)
+{
+  return (TREE_CODE (type) == RECORD_TYPE
+	  || TREE_CODE (type) == UNION_TYPE
+	  || TREE_CODE (type) == QUAL_UNION_TYPE);
+}
+
+
+
+/* Keep data during a search for an aliasing site.
+   RHS = object or pointer aliased.  No LHS is specified because we are only
+   looking in the UseDef paths of a given variable, so LHS will always be
+   an SSA name of the same variable.
+   When IS_RHS_POINTER = true, we are looking for ... = RHS.  Otherwise,
+   we are looking for ... = &RHS.
+   SITE is the output of a search, non-NULL if the search succeeded.  */
+
+struct alias_match
+{
+  tree rhs;
+  bool is_rhs_pointer;
+  tree site;
+};
+
+
+/* Callback for find_alias_site.  Return true if the right hand site 
+   of STMT matches DATA.  */
+
+static bool
+find_alias_site_helper (tree var ATTRIBUTE_UNUSED, tree stmt, void *data)
+{
+  struct alias_match *match = (struct alias_match*) data;
+  tree rhs_pointer = get_rhs (stmt);
+  tree to_match = NULL_TREE;
+
+  while (TREE_CODE (rhs_pointer) == NOP_EXPR
+         || TREE_CODE (rhs_pointer) == CONVERT_EXPR
+         || TREE_CODE (rhs_pointer) == VIEW_CONVERT_EXPR)
+    rhs_pointer = TREE_OPERAND (rhs_pointer, 0);
+
+  if (!rhs_pointer)
+    /* Not a type conversion.  */
+    return false;
+
+  if (TREE_CODE (rhs_pointer) == ADDR_EXPR && !match->is_rhs_pointer)
+    to_match = TREE_OPERAND (rhs_pointer, 0);
+  else if (POINTER_TYPE_P (rhs_pointer)
+           && match->is_rhs_pointer)
+    to_match = rhs_pointer;
+
+  if (to_match != match->rhs)
+    /* Type conversion, but not a name match.  */
+    return false;
+
+  /* Found it.  */
+  match->site = stmt;
+  return true;
+}
+
+
+/* Find the statement where OBJECT1 gets aliased to OBJECT2.
+   If IS_PTR2 is true, consider OBJECT2 to be the name of a pointer or 
+   reference rather than the actual aliased object.
+   For now, just implement the case where OBJECT1 is an SSA name defined
+   by a PHI statement.  */
+
+static tree
+find_alias_site (tree object1, bool is_ptr1 ATTRIBUTE_UNUSED,
+                 tree object2, bool is_ptr2)
+{
+  struct alias_match match;
+
+  match.rhs = object2;
+  match.is_rhs_pointer = is_ptr2;
+  match.site = NULL_TREE;
+
+  if (TREE_CODE (object1) != SSA_NAME)
+    return NULL_TREE;
+
+  walk_use_def_chains (object1, find_alias_site_helper, &match, false);
+  return match.site;
+}
+
+
+/* Structure to store temporary results when trying to figure out whether
+   an object is referenced.  Just its presence in the text is not enough,
+   as we may just be taking its address.  */
+
+struct match_info
+{
+  tree object;
+  bool is_ptr;
+  /* The difference between the number of references to OBJECT
+     and the number of occurences of &OBJECT.  */
+  int found;
+};
+
+
+/* Return the base if EXPR is an SSA name.  Return EXPR otherwise.  */
+
+static tree
+get_ssa_base (tree expr)
+{
+  if (TREE_CODE (expr) == SSA_NAME)
+    return SSA_NAME_VAR (expr);
+  else
+    return expr;
+}
+
+
+/* Callback for referenced_p.
+   Look for dereferences of *(struct match_info *) in *TP.  */
+
+static tree
+find_references (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+{
+  struct match_info *target = (struct match_info*) data;
+  tree ssa_base_target;
+  tree candidate = NULL_TREE;
+  tree ssa_base_candidate;
+
+  /* Find the target base name.  */
+  ssa_base_target = get_ssa_base (target->object);
+
+  /* Find the candidate name.  */
+  if (target->is_ptr && TREE_CODE (*tp) == INDIRECT_REF)
+    candidate = TREE_OPERAND (*tp, 0);
+  else if (!target->is_ptr)
+    candidate = *tp;
+  else
+    return NULL_TREE;
+
+  /* Decrease the found count if the name just has its address taken (it is not
+     referenced).  XXX: what about return statements?  */
+  if (!target->is_ptr
+      && TREE_CODE (*tp) == ADDR_EXPR
+      && ((TREE_CODE (TREE_OPERAND (*tp, 0)) == SSA_NAME &&
+           SSA_NAME_VAR (TREE_OPERAND (*tp, 0)) == ssa_base_target)
+          || (TREE_OPERAND (*tp, 0) == ssa_base_target)))
+    --target->found;
+
+  /* Find the candidate base name.  */
+  if (TREE_CODE (candidate) == SSA_NAME)
+    ssa_base_candidate = SSA_NAME_VAR (candidate);
+  else
+    ssa_base_candidate = candidate;
+
+  /* Check if they have the same base ssa name.  */
+  if (ssa_base_candidate == ssa_base_target)
+    ++target->found;
+
+  return NULL_TREE;
+}
+
+
+/* Return whether OBJECT is referenced within EXPR.
+   If IS_PTR is true, return whether the given pointer is dereferenced
+   within EXPR.  */
+
+static bool
+referenced_p (tree object, bool is_ptr, tree expr)
+{
+  struct match_info target;
+
+  if (object == NULL_TREE)
+    return false;
+
+  target.object = object;
+  target.is_ptr = is_ptr;
+  target.found = 0;
+  walk_tree (&expr, find_references, (void*) &target, NULL);
+
+  if (target.found)
+    return true;
+  else
+    return false;
+}
+
+
+/* Reference type.  */
+enum ref_type
+  {
+    RT_UNDEFINED,
+    RT_UNTOUCHED,
+    RT_READ,
+    RT_WRITE,
+    RT_READ_WRITE /* Both R and W.  */
+  };
+
+
+/* Find the reference type to OBJECT.  If IS_PTR is true,
+   find the given reference type to the object dereferenced by OBJECT.  */
+
+static enum ref_type
+reference_type (tree object, bool is_ptr, tree stmt)
+{
+  tree rhs  = stmt;
+  bool dlhs = false;
+  bool drhs = false;
+
+  /* Analyze LHS, if any.  */
+  if (TREE_CODE (stmt) == MODIFY_EXPR)
+    {
+      tree lhs = TREE_OPERAND (stmt, 0);
+      tree lhsop = NULL_TREE;
+      rhs = get_rhs (stmt);
+      if (is_ptr && TREE_CODE (lhs) == INDIRECT_REF)
+	lhsop = TREE_OPERAND (lhs, 0);
+      else if (!is_ptr)
+	lhsop = lhs;
+      if (lhsop)
+	{
+	  if (TREE_CODE (lhsop) == SSA_NAME &&
+	      SSA_NAME_VAR (lhsop) == SSA_NAME_VAR (object))
+	    dlhs = true;
+	  else if (lhsop == object)
+	    dlhs = true;
+	}
+    }
+
+  /* Analyze RHS, if any.  */
+  drhs = referenced_p (object, is_ptr, rhs);
+  /* XXX: we may be missing cases such as
+     A[*p] = ... .  Can they occur in GIMPLE?  */
+
+  if (!dlhs && !drhs)
+    return RT_UNTOUCHED;
+  if (!dlhs && drhs)
+    return RT_READ;
+  if (dlhs && !drhs)
+    return RT_WRITE;
+  if (dlhs && drhs)
+    return RT_READ_WRITE;
+
+  gcc_unreachable ();
+}
+
+
+/* Find the reference site and type for OBJECT and return it in *TYPE.
+   If IS_PTR is true, look for derferences of OBJECT instead.
+   XXX: only the first site and type are returned in the current
+   implementation.  */
+
+static tree
+reference_site (tree object, bool is_ptr, enum ref_type *type)
+{
+  basic_block bb;
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator i;
+      for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
+	{
+	  tree stmt = *bsi_stmt_ptr (i);
+	  if ( (*type=reference_type (object, is_ptr, stmt)) != RT_UNTOUCHED)
+	    return stmt;
+	}
+    }
+
+  *type = RT_UNDEFINED;
+  return NULL_TREE;
+}
+
+
+/* Try to get more location info when something is missing.  
+   OBJECT1 and OBJECT2 are aliased names.  If IS_PTR1 or IS_PTR2, the alias
+   is on the memory referenced or pointed to by OBJECT1 and OBJECT2.
+   ALIAS_SITE, DEREF_SITE1 and DEREF_SITE2 are the statements where the
+   alias takes place (some pointer assignment usually) and where the
+   alias is referenced through OBJECT1 and OBJECT2 respectively.
+   REF_TYPE1 and REF_TYPE2 will return the type of the reference at the
+   respective sites.  Only the first matching reference is returned for
+   each name.  If no statement is found, the function header is returned.  */
+
+static void
+maybe_find_missing_stmts (tree object1, bool is_ptr1,
+                          tree object2, bool is_ptr2,
+                          tree *alias_site,
+                          tree *deref_site1,
+                          enum ref_type *ref_type1,
+                          tree *deref_site2,
+                          enum ref_type *ref_type2)
+{
+  if (object1 && object2)
+    {
+      if (!*alias_site || !EXPR_HAS_LOCATION (*alias_site))
+	*alias_site = find_alias_site (object1, is_ptr1, object2, is_ptr2);
+
+      if (!*deref_site1 || !EXPR_HAS_LOCATION (*deref_site1))
+	*deref_site1 = reference_site (object1, is_ptr1,  ref_type1);
+
+      if (!*deref_site2 || !EXPR_HAS_LOCATION (*deref_site2))
+	*deref_site2 = reference_site (object2, is_ptr2,  ref_type2);
+    }
+
+  /* If we could not find the alias site, set it to one of the dereference
+     sites, if available.  */
+  if (!*alias_site)
+    {
+      if (*deref_site1)
+	*alias_site = *deref_site1;
+      else if (*deref_site2)
+	*alias_site = *deref_site2;
+    }
+
+  /* If we could not find the dereference sites, set them to the alias site,
+     if known.  */
+  if (!*deref_site1 && *alias_site)
+    *deref_site1 = *alias_site;
+  if (!*deref_site2 && *alias_site)
+    *deref_site2 = *alias_site;
+}
+
+
+/* Callback for find_first_artificial_name.
+   Find out if there are no artificial names at tree node *T.  */
+
+static tree
+ffan_walker (tree *t,
+             int *ARG_UNUSED (go_below),
+             void *ARG_UNUSED (data))
+{
+  if (DECL_P (*t) && DECL_ARTIFICIAL (*t))
+    return *t;
+  else
+    return NULL_TREE;
+}
+
+
+/* Return the first artificial name within EXPR, or NULL_TREE if
+   none exists.  */
+
+static tree
+find_first_artificial_name (tree expr)
+{
+  return walk_tree_without_duplicates (&expr, ffan_walker, NULL);
+}
+
+
+/* Get a variable from the original program for VAR.  */
+
+static tree
+get_original_var (tree var)
+{
+  tree base = get_ssa_base (var);
+
+  /* If there is no artificial name within var, return it.  */
+  if (!find_first_artificial_name (base))
+    return base;
+
+  /* If this is a temporary pointer such as D.1234 = struct.field, print
+     out struct.field.  */
+  if (TREE_CODE (var) == SSA_NAME)
+    {
+      tree def = SSA_NAME_DEF_STMT (var);
+      tree rhs = get_rhs (def);
+
+      if (!find_first_artificial_name (rhs))
+	return get_original_var (rhs);
+    }
+
+  /* XXX: don't know what to do otherwise, so for now return it anyway.  */
+  return base;  
+}
+
+
+/* Get a name from the original program for VAR.  */
+
+static const char*
+get_var_name (tree var)
+{
+  if (TREE_CODE (var) == SSA_NAME)
+    return get_var_name (get_ssa_base (var));
+
+  if (find_first_artificial_name (var))
+    return "{unknown}";
+
+  if (TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL) 
+    if (DECL_NAME (var))
+      return IDENTIFIER_POINTER (DECL_NAME (var));
+
+  return "{unknown}";
+}
+
+
+/* Return "*" if OBJECT is not the actual alias but a pointer to it, or
+   "" otherwise.
+   IS_PTR is true when OBJECT is not the actual alias.
+   In addition to checking IS_PTR, we also make sure that OBJECT is a pointer
+   since IS_PTR would also be true for C++ references, but we should only
+   print a * before a pointer and not before a reference.  */
+
+static const char*
+get_maybe_star_prefix (tree object, bool is_ptr)
+{
+  gcc_assert (object);
+  return (is_ptr && TREE_CODE (TREE_TYPE (object)) == POINTER_TYPE) ? "*" : "";
+}
+
+
+/* Callback for contains_node_type_p.  
+   Returns true if *T has tree code *(int*)DATA.  */
+
+static tree
+contains_node_type_p_callback (tree *t, 
+			       int *go_below ATTRIBUTE_UNUSED,
+			       void *data)
+{
+  return (int)TREE_CODE (*t) == *((int*)data) ? *t : NULL_TREE;
+}
+
+
+/* Return true if T contains a node with tree code TYPE.  */
+
+static bool
+contains_node_type_p (tree t, int type)
+{
+  return walk_tree_without_duplicates (&t, contains_node_type_p_callback,
+				       (void*)&type) != NULL_TREE;
+}
+
+
+/* Return true if a warning was issued in the front end at STMT.  */
+
+static bool
+already_warned_in_frontend_p (tree stmt)
+{
+  tree rhs_pointer;
+
+  if (stmt == NULL_TREE)
+    return false;
+
+  rhs_pointer = get_rhs (stmt);
+
+  if ((TREE_CODE (rhs_pointer) == NOP_EXPR
+       || TREE_CODE (rhs_pointer) == CONVERT_EXPR
+       || TREE_CODE (rhs_pointer) == VIEW_CONVERT_EXPR)
+      && TREE_NO_WARNING (rhs_pointer))
+    return true;
+  else
+    return false;
+}
+
+
+/* Issue a -Wstrict-aliasing warning.
+   OBJECT1 and OBJECT2 are aliased names.
+   If IS_PTR1 and/or IS_PTR2 is true, then the corresponding name
+   OBJECT1/OBJECT2 is a pointer or reference to the aliased memory,
+   rather than actual storage.
+   ALIAS_SITE is a statement where the alias took place.  In the most common
+   case, that is where a pointer was assigned to the address of an object.  */
+
+static bool
+strict_aliasing_warn (tree alias_site,
+                      tree object1, bool is_ptr1,
+                      tree object2, bool is_ptr2,
+		      bool filter_artificials)
+{
+  enum ref_type rt1 = RT_UNDEFINED;
+  enum ref_type rt2 = RT_UNDEFINED;
+  tree ref_site1 = NULL_TREE;
+  tree ref_site2 = NULL_TREE;
+  const char *name1;
+  const char *name2;
+  location_t alias_loc;
+  location_t ref1_loc;
+  location_t ref2_loc;
+  gcc_assert (object1);
+  gcc_assert (object2);
+  name1 = get_var_name (object1);
+  name2 = get_var_name (object2);
+
+  maybe_find_missing_stmts (object1, is_ptr1, object2, is_ptr2, &alias_site,
+                            &ref_site1, &rt1, &ref_site2, &rt2);
+
+  if (EXPR_HAS_LOCATION (alias_site))
+    alias_loc = EXPR_LOCATION (alias_site);
+  else
+    return false;
+
+  if (EXPR_HAS_LOCATION (ref_site1))
+    ref1_loc = EXPR_LOCATION (ref_site1);
+  else 
+    ref1_loc = alias_loc;
+
+  if (EXPR_HAS_LOCATION (ref_site2))
+    ref2_loc = EXPR_LOCATION (ref_site2);
+  else 
+    ref2_loc = alias_loc;
+
+  if (already_warned_in_frontend_p (alias_site))
+      return false;
+
+  /* If they are not SSA names, but contain SSA names, drop the warning
+     because it cannot be displayed well.
+     Also drop it if they both contain artificials.
+     XXX: this is a hack, must figure out a better way to display them.  */
+  if (filter_artificials)
+    if ((find_first_artificial_name (get_ssa_base (object1))
+	 && find_first_artificial_name (get_ssa_base (object2)))
+	|| (TREE_CODE (object1) != SSA_NAME
+	    && contains_node_type_p (object1, SSA_NAME))
+	|| (TREE_CODE (object2) != SSA_NAME
+	    && contains_node_type_p (object2, SSA_NAME)))
+      return false;
+
+
+  /* XXX: In the following format string, %s:%d should be replaced by %H.
+     However, in my tests only the first %H printed ok, while the
+     second and third were printed as blanks.  */
+  warning (OPT_Wstrict_aliasing,
+	   "%Hlikely type-punning may break strict-aliasing rules: "
+	   "object %<%s%s%> of main type %qT is referenced at or around "
+	   "%s:%d and may be "
+	   "aliased to object %<%s%s%> of main type %qT which is referenced "
+	   "at or around %s:%d.",
+	   &alias_loc,
+	   get_maybe_star_prefix (object1, is_ptr1),
+	   name1,
+	   get_otype (object1, is_ptr1),
+	   LOCATION_FILE (ref1_loc),
+	   LOCATION_LINE (ref1_loc),
+	   get_maybe_star_prefix (object2, is_ptr2),
+	   name2,
+	   get_otype (object2, is_ptr2),
+	   LOCATION_FILE (ref2_loc),
+	   LOCATION_LINE (ref2_loc));
+
+  return true;
+}
+
+
+
+/* Returns true if TYPE1 is a base class for TYPE2.  */
+
+static bool
+is_base_class_p (tree type1, tree type2)
+{
+  int i;
+  tree binfo, base_binfo;
+
+  if (lang_hooks.types_compatible_p (type1, type2))
+    return true;
+
+  if (TYPE_BINFO (type2))
+    for (binfo = TYPE_BINFO (type2), i = 0;
+         BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+      {
+	tree binfotype = BINFO_TYPE (base_binfo);
+	if (is_base_class_p (type1, binfotype))
+	  return true;
+      }
+
+  return false;
+}
+
+
+/* Return true if TYPE1 is a subtype of TYPE2 or one of its components or
+   base classes.  */
+
+static bool
+subtype_p (tree type1, tree type2)
+{
+  tree field;
+
+  type1 = get_main_type (type1);
+  type2 = get_main_type (type2);
+
+  /* Treat pointer specially so we can find const char* and char* the same.  */
+  if (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2))
+    return subtype_p (TREE_TYPE (type1), TREE_TYPE (type2));
+
+  if (lang_hooks.types_compatible_p  (type1, type2))
+    return true;
+
+  if (!struct_class_union_p (type2))
+    return false;
+
+  if (is_base_class_p (type1, type2))
+    return true;
+
+  for (field = TYPE_FIELDS (type2); field; field = TREE_CHAIN (field))
+    if ((TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
+        && subtype_p (type1, TREE_TYPE (field)))
+      return true;
+
+  return false;
+}
+
+
+/* Computes the value of
+   !alias_sets_conflict_p (get_alias_set (TYPE1), get_alias_set (TYPE2)).
+   Since alias_sets_conflict_p only works with -fstrict-aliasing, this
+   is an alternative with -fno-strict-aliasing.
+   This is a crude implementation and is only used at -Wstrict-aliasing=4,
+   but will catch many common cases.
+   See the documentation of -Wstrict-aliasing=4 at the top of the file for
+   more details on why this is needed.  */
+
+static bool
+cannot_alias_simple_types (tree type1, tree type2)
+{
+  gcc_assert (!flag_strict_aliasing);
+
+  /* Integer vs. real.  */
+  if ((TREE_CODE (type1) == REAL_TYPE 
+       && TREE_CODE (type2) == INTEGER_TYPE
+       && TYPE_PRECISION (type1) != 8)
+      || (TREE_CODE (type1) == INTEGER_TYPE 
+	  && TREE_CODE (type2) == REAL_TYPE
+	  && TYPE_PRECISION (type2) != 8))
+    return true;
+
+  /* Integers of different precisions, but not 8.  */
+  if (TREE_CODE (type1) == INTEGER_TYPE 
+      && TREE_CODE (type2) == INTEGER_TYPE
+      && TYPE_PRECISION (type1) != TYPE_PRECISION (type2)
+      && TYPE_PRECISION (type1) != 8
+      && TYPE_PRECISION (type2) != 8)
+    return true;
+
+  /* Reals of different precisions.  */
+  if (TREE_CODE (type1) == REAL_TYPE
+      && TREE_CODE (type2) == REAL_TYPE
+      && TYPE_PRECISION (type1) != TYPE_PRECISION (type2))
+    return true;
+
+  return false;
+}
+
+
+/* Return true when any objects of TYPE1 and TYPE2 respectively 
+   may not be aliased according to the language standard.  */
+
+static bool
+nonstandard_alias_types_p (tree type1, tree type2)
+{
+  if (flag_strict_aliasing)
+    {
+      HOST_WIDE_INT set1;
+      HOST_WIDE_INT set2;
+      
+      if (VOID_TYPE_P (type1) || VOID_TYPE_P (type2))
+	return false;
+      
+      if ((!struct_class_union_p (type1) 
+	   && struct_class_union_p (type2)
+	   && COMPLETE_TYPE_P (type2)
+	   && !subtype_p (type1, type2))
+	  || (struct_class_union_p (type1) 
+	      && !struct_class_union_p (type2)
+	      && COMPLETE_TYPE_P (type1)
+	      && !subtype_p (type2, type1)))
+	return true;
+      
+      set1 = get_alias_set (type1);
+      set2 = get_alias_set (type2);
+      return !alias_sets_conflict_p (set1, set2);
+    }
+  else
+    return cannot_alias_simple_types (type1, type2);
+}
+
+
+/* Is VAR the field of a struct, union or class?  */
+
+static bool
+struct_field_tag_p (tree var)
+{
+  return TREE_CODE (var) == STRUCT_FIELD_TAG;
+}
+
+
+/* Is VAR the field of a union?  */
+
+static bool
+union_member_p (tree var)
+{
+  if (struct_field_tag_p (var))
+    if (TREE_CODE (TREE_TYPE (SFT_PARENT_VAR (var))) == UNION_TYPE
+        || TREE_CODE (TREE_TYPE (SFT_PARENT_VAR (var))) == QUAL_UNION_TYPE)
+      return true;
+
+  return false;
+}
+
+
+/* Return true if OBJECT1 of TYPE1 is ok be aliased to OBJECT2 of TYPE2
+   from the point of view of structures.
+   XXX: the prefix rule is not implemented yet.  */
+
+static bool
+ok_alias_structures_p (tree object1, tree type1,
+                       tree object2, tree type2)
+{
+  /* If either of them is union member, let it be.  */
+  if (union_member_p (object1) || union_member_p (object2))
+    return true;
+
+  /* If either of them is a field, forget about it.  */
+  if (struct_field_tag_p (object1) || struct_field_tag_p (object2))
+    return true;
+
+  /* If they are both structs, check if they are prefix compatible.
+     XXX: not implemented.  */
+  if (struct_class_union_p (type1) && struct_class_union_p (type2))
+    return true;
+    
+  /* If it gets here, at most one of them is a struct, so try to see whether
+     the other one is a subtype.  */
+  if (subtype_p (type1, type2) || subtype_p (type2, type1))
+    return true;
+
+  /* At least one of them is a struct, and is not related to the other
+     from the point of view of structures.  That is not OK.  Boo!  */
+  return false;
+}
+
+
+
+/* Returns true when *PTR may not be aliased to ALIAS.
+   See C standard 6.5p7 and C++ standard 3.10p15.
+   If PTR_PTR is true, ALIAS represents a pointer or reference to the
+   aliased storage rather than its actual name.  */
+
+static bool
+nonstandard_alias_p (tree ptr, tree alias, bool ptr_ptr)
+{
+  /* Find the types to compare.  */
+  tree ptr_type   = get_otype (ptr, true);
+  tree alias_type = get_otype (alias, ptr_ptr);
+
+  /* XXX: for now, say it's OK if the alias escapes.  
+     Not sure this is needed in general, but otherwise GCC will not
+     bootstrap.  */
+  if (var_ann (get_ssa_base (alias))->escape_mask != NO_ESCAPE)
+    return false;
+
+  /* If they are both SSA names of artificials, let it go, the warning
+     is too confusing.  */
+  if (find_first_artificial_name (ptr)
+      && find_first_artificial_name (alias))
+    return false;
+
+  /* Deal with class, struct and union.  */
+  if (ok_alias_structures_p (ptr, ptr_type, alias, alias_type))
+    return false;
+
+  /* Compare the types.  */
+  return nonstandard_alias_types_p (ptr_type, alias_type);
+}
+
+
+/* Return true when we should skip analysis for pointer PTR based on the
+   fact that their alias information *PI is not considered relevant.  */
+static bool
+skip_this_pointer (tree ptr ATTRIBUTE_UNUSED, struct ptr_info_def *pi)
+{
+  /* If it is not dereferenced, it is not a problem (locally).  */
+  if (!pi->is_dereferenced)
+    return true;
+
+  /* This would probably cause too many false positives.  */
+  if (pi->value_escapes_p || pi->pt_anything)
+    return true;
+
+  return false;
+}
+
+
+/* Find aliasing to named objects for pointer PTR.  */
+
+static void
+dsa_named_for (tree ptr)
+{
+  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+
+  if (pi)
+    {
+      if (skip_this_pointer (ptr, pi))
+	return;
+    
+      /* For all the variables it could be aliased to.  */
+      if (pi->pt_vars)
+	{
+	  unsigned ix;
+	  bitmap_iterator bi;
+      
+	  EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
+	    {
+	      tree alias = referenced_var (ix);
+
+	      if (nonstandard_alias_p (ptr, alias, false))
+		strict_aliasing_warn (SSA_NAME_DEF_STMT (ptr),
+				      ptr, true, alias, false, true);
+	    }
+	}
+    }
+}
+
+
+/* Detect and report strict aliasing violation of named objects.  */
+
+static void
+detect_strict_aliasing_named (void)
+{
+  unsigned int i;
+
+  for (i = 1; i < num_ssa_names; i++)
+    {
+      tree ptr = ssa_name (i);
+      struct ptr_info_def *pi;
+    
+      if (ptr == NULL_TREE)
+	continue;
+    
+      pi = SSA_NAME_PTR_INFO (ptr);
+
+      if (!SSA_NAME_IN_FREE_LIST (ptr) && pi && pi->name_mem_tag)
+	dsa_named_for (ptr);
+    }
+}
+
+
+/* Detect and report strict aliasing violation of unnamed objects.
+   PTR is a pointer that points to unnamed object ALIAS.
+   UNNAMED_MAPPINGS stores a map<unnamed object, pointer> which is used to 
+   detect collisions between two pointers which point to the same unnamed
+   object.
+   UNNAMED_MAPPINGS_POOL keeps temporary storage associated with the mappings.
+   It should be cleaned once per function.  */
+
+static void
+dsa_unnamed_for (htab_t unnamed_mappings, alloc_pool unnamed_mappings_pool,
+		 tree ptr, tree alias)
+{
+  struct tree_map tp;
+  void **slot;
+
+  tp.from = alias;
+  slot = htab_find_slot (unnamed_mappings, &tp, INSERT);
+  gcc_assert (slot);
+
+  /* Check whether there is anything in the table yet.  */
+  if (*slot)
+    {
+      /* Check for collision.  */
+      tree other_ptr = ((struct tree_map*) *slot)->to;
+      if (nonstandard_alias_p (other_ptr, ptr, true))
+	strict_aliasing_warn (NULL_TREE, other_ptr, true, ptr, true, true);
+    }
+  else
+    {
+      /* Nothing in, add ptr if it is not char*.  */
+      struct tree_map *tpp = pool_alloc (unnamed_mappings_pool);
+      tpp->from = alias;
+      tpp->to = ptr;
+      (*slot) = (void*) tpp;
+    }
+}
+
+
+/* Detect and report strict aliasing violation of unnamed objects 
+   in the current function.  */
+
+static void
+detect_strict_aliasing_unnamed (void)
+{
+  unsigned int i;
+  htab_t unnamed_mappings =
+    htab_create (10, tree_map_hash, tree_map_eq, NULL);
+  alloc_pool unnamed_mappings_pool = 
+    create_alloc_pool ("Unnamed mappings.", sizeof(struct tree_map), 20);
+
+  for (i = 1; i < num_ssa_names; i++)
+    {
+      tree ptr = ssa_name (i);
+      struct ptr_info_def *pi;
+    
+      if (ptr == NULL_TREE)
+	continue;
+    
+      pi = SSA_NAME_PTR_INFO (ptr);
+
+      if (!SSA_NAME_IN_FREE_LIST (ptr) && pi && pi->name_mem_tag)
+	{
+	  if (skip_this_pointer (ptr, pi))
+	    continue;
+
+	  if (pi->pt_vars)
+	    {
+	      unsigned ix;
+	      bitmap_iterator bi;
+	      EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
+		{
+		  tree alias = referenced_var (ix);
+		  dsa_unnamed_for (unnamed_mappings, unnamed_mappings_pool,
+				   ptr, alias);
+		}
+	    }
+	}
+    }
+
+  htab_delete (unnamed_mappings);
+  free_alloc_pool (unnamed_mappings_pool);
+}
+
+
+/* Return false only the first time I see each instance of FUNC.  */
+
+static bool
+processed_func_p (tree func)
+{
+  static htab_t seen = NULL;
+  void **slot = NULL;
+
+  if (!seen)
+    seen = htab_create (10, tree_map_hash, tree_map_eq, NULL);
+
+  slot = htab_find_slot (seen, func, INSERT);
+  gcc_assert (slot);
+
+  if (*slot)
+    return true;
+
+  gcc_assert (slot);
+  *slot = (void*) func;
+  return false;
+}
+
+
+/* Print some debug information specific to -Wstrict-aliasing.  */
+
+static void
+maybe_print_some_debug_info (void)
+{
+#ifdef _DEBUG_TREE_SSA_ALIAS_WARNING
+  fprintf (stderr, "\nFrom  warn_strict_aliasing_dataflow_insensitive:\n");
+  print_generic_expr (stderr, current_function_decl, TDF_SLIM);
+  fprintf (stderr, ":\n");
+  dump_function_to_file (current_function_decl, stderr, TDF_SLIM);
+  dump_alias_info (stderr);
+  dump_referenced_vars (stderr);
+  dump_points_to_info (stderr);
+#endif
+}
+
+
+/* Detect and warn about strict aliasing violation using points-to
+   information.  */
+
+void
+strict_aliasing_warning_backend (void)
+{
+  /* Do it just once for each function.  */
+  if (processed_func_p (current_function_decl))
+    return;
+
+  maybe_print_some_debug_info ();
+
+  /* Analyze aliases to named objects.  */
+  if ((flag_strict_aliasing && warn_strict_aliasing == 3)
+      || (!flag_strict_aliasing && warn_strict_aliasing > 3))
+    detect_strict_aliasing_named ();
+
+  /* Analyze aliases to unnamed objects.  */
+  if (warn_strict_aliasing == 4)
+    detect_strict_aliasing_unnamed ();
+}
==== trunk/gcc/tree-ssa-alias.c#15 - /home/rus/local/gcc/ggcc/gcc/tree-ssa-alias.c ====
--- old/gcc/tree-ssa-alias.c#15	2007-02-13 18:03:18.000000000 -0800
+++ new/gcc/tree-ssa-alias.c	2007-02-13 17:58:26.000000000 -0800
@@ -109,6 +109,8 @@ static void create_global_var (void);
 static void maybe_create_global_var (struct alias_info *ai);
 static void set_pt_anything (tree ptr);
 
+
+
 void dump_mp_info (FILE *, VEC(mp_info_t,heap) *mp_info_t);
 void debug_mp_info (VEC(mp_info_t,heap) *mp_info_t);
 
@@ -943,7 +945,10 @@ compute_may_aliases (void)
       dump_points_to_info (dump_file);
       dump_alias_info (dump_file);
     }
-  
+
+  /* Report strict aliasing violations.  */
+  strict_aliasing_warning_backend ();
+
   /* Deallocate memory used by aliasing data structures.  */
   delete_alias_info (ai);
 
@@ -3207,7 +3212,7 @@ create_structure_vars (void)
 	      update_stmt (stmt);
 	  }
       }
-  
+
   return 0;
 }
 

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