2008-12-04 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Dec 2008 15:55:25 +0000 (15:55 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Dec 2008 15:55:25 +0000 (15:55 +0000)
PR middle-end/36509
PR c++/38334
* Makefile.in (tree-ssa-alias-warnings.o): Remove.
(tree-ssa-structalias.o): Remove errors.h dependency.
(tree-ssa-reassoc.o): Likewise.
* tree-ssa-reassoc.c: Do not include errors.h.
* tree-ssa-alias-warnings.c: Remove.
* tree-ssa-alias.c (compute_may_aliases): Remove call to
strict_aliasing_warning_backend.
* tree-ssa-structalias.c (emit_pointer_definition): New function.
(emit_alias_warning): Likewise.
(set_uids_in_ptset): Warn for clear cases of type-punning.
* tree-inline.c (remap_gimple_op_r): Preserve TREE_NO_WARNING
on INDIRECT_REFs.

cp/
* typeck.c (get_member_function_from_ptrfunc): Mark the vtbl
pointer access with TREE_NO_WARNING.

* gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c: Adjust, remove XFAIL.
* gcc.dg/Wstrict-aliasing-converted-assigned.c: Adjust.
* g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142437 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
gcc/tree-inline.c
gcc/tree-ssa-alias-warnings.c [deleted file]
gcc/tree-ssa-alias.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa-structalias.c

index 49d2b33..d9b81fe 100644 (file)
@@ -1,3 +1,19 @@
+2008-12-04  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/36509
+       * Makefile.in (tree-ssa-alias-warnings.o): Remove.
+       (tree-ssa-structalias.o): Remove errors.h dependency.
+       (tree-ssa-reassoc.o): Likewise.
+       * tree-ssa-reassoc.c: Do not include errors.h.
+       * tree-ssa-alias-warnings.c: Remove.
+       * tree-ssa-alias.c (compute_may_aliases): Remove call to
+       strict_aliasing_warning_backend.
+       * tree-ssa-structalias.c (emit_pointer_definition): New function.
+       (emit_alias_warning): Likewise.
+       (set_uids_in_ptset): Warn for clear cases of type-punning.
+       * tree-inline.c (remap_gimple_op_r): Preserve TREE_NO_WARNING
+       on INDIRECT_REFs.
+
 2008-12-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        * cse.c (equiv_constant): Fix pasto.
index b55c5c1..b50d1f4 100644 (file)
@@ -1243,7 +1243,6 @@ OBJS-common = \
        tree-switch-conversion.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 \
@@ -2089,7 +2088,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TOPLEV_H)
 tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
    $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(GGC_H) $(OBSTACK_H) $(BITMAP_H) \
-   $(FLAGS_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) output.h errors.h \
+   $(FLAGS_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) output.h \
    $(DIAGNOSTIC_H) $(TREE_H) $(C_COMMON_H) $(TREE_FLOW_H) $(TREE_INLINE_H) varray.h \
    $(C_TREE_H) $(GIMPLE_H) $(HASHTAB_H) $(FUNCTION_H) $(CGRAPH_H) tree-pass.h \
    $(TIMEVAR_H) alloc-pool.h $(SPLAY_TREE_H) $(PARAMS_H) gt-tree-ssa-structalias.h \
@@ -2309,11 +2308,6 @@ tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_FLOW_H) $(CONFIG_H) \
 tree-ssa-math-opts.o : tree-ssa-math-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(FLAGS_H) $(TREE_H) $(TREE_FLOW_H) $(REAL_H) $(TIMEVAR_H) tree-pass.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 \
@@ -2321,7 +2315,7 @@ tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    hard-reg-set.h $(GIMPLE_H) vec.h tree-ssa-structalias.h \
    $(IPA_TYPE_ESCAPE_H) vecprim.h pointer-set.h alloc-pool.h
 tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
-   $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TIMEVAR_H) \
+   $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
    $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) tree-iterator.h\
    $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_INLINE_H) vec.h langhooks.h \
    alloc-pool.h pointer-set.h $(CFGLOOP_H)
index 0c6ecf8..029d2ad 100644 (file)
@@ -1,3 +1,9 @@
+2008-12-04  Richard Guenther  <rguenther@suse.de>
+
+       PR c++/38334
+       * typeck.c (get_member_function_from_ptrfunc): Mark the vtbl
+       pointer access with TREE_NO_WARNING.
+
 2008-12-03  Jason Merrill  <jason@redhat.com>
 
        PR c++/38232
index 7595b58..ed01c51 100644 (file)
@@ -2790,6 +2790,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
                     instance_ptr);
       vtbl = cp_build_indirect_ref (vtbl, NULL, tf_warning_or_error);
+      /* If the object is not dynamic the access invokes undefined
+        behavior.  As it is not executed in this case silence the
+        spurious warnings it may provoke.  */
+      TREE_NO_WARNING (vtbl) = 1;
 
       /* Finally, extract the function pointer from the vtable.  */
       e2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
index e54d5ea..e58bdbb 100644 (file)
@@ -1,3 +1,10 @@
+2008-12-04  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/36509
+       * gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c: Adjust, remove XFAIL.
+       * gcc.dg/Wstrict-aliasing-converted-assigned.c: Adjust.
+       * g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C: Likewise.
+
 2008-12-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.dg/union-4.c: New test.
index 5527808..d88ed43 100644 (file)
@@ -4,7 +4,9 @@
 
 int foo() {
   int x;
-  float& q = reinterpret_cast<float&> (x);  /* { dg-warning "type-punn" } */
-  q = 1.0;
+  float& q = reinterpret_cast<float&> (x);  /* { dg-message "initialized" } */
+  q = 1.0; /* { dg-warning "does break strict-aliasing" } */
   return x;
 }
+
+/* { dg-message "dereferencing type-punned" "" { target *-*-* } 7 } */
index 409120f..eb404a1 100644 (file)
@@ -8,3 +8,6 @@ int foo()
   *(long*)&i = 0;  /* { dg-warning "type-punn" } */
   return i;
 }
+
+/* { dg-message "does break strict-aliasing" "" { target *-*-* } 8 } */
+/* { dg-message "initialized" "" { target *-*-* } 8 } */
index 7371915..fccc178 100644 (file)
@@ -11,12 +11,12 @@ int foo() {
   float* r;
 
   if (flag) {
-    q = (float*) &x;  /* { dg-warning "type-punn" "" { xfail *-*-* } } */
+    q = (float*) &x;  /* { dg-message "initialized" } */
   } else {
-    q = (float*) &y;  /* { dg-warning "type-punn" "" { xfail *-*-* } } */
+    q = (float*) &y;  /* { dg-message "initialized" } */
   }
 
-  *q = 1.0;
+  *q = 1.0;  /* { dg-warning "does break strict-aliasing" } */
 
   return x;
 
index 33ccafd..075e575 100644 (file)
@@ -710,6 +710,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
                    {
                      *tp = build1 (INDIRECT_REF, type, new_tree);
                      TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
+                     TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
                    }
                }
              *walk_subtrees = 0;
diff --git a/gcc/tree-ssa-alias-warnings.c b/gcc/tree-ssa-alias-warnings.c
deleted file mode 100644 (file)
index 5bae978..0000000
+++ /dev/null
@@ -1,1033 +0,0 @@
-/* Strict aliasing checks.
-   Copyright (C) 2007, 2008 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 3, 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 COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#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.
-   These checks only happen when -fstrict-aliasing is present.
-
-   The idea is to use the compiler to identify occurrences of nonstandard
-   aliasing, and report them to programmers.  Programs free of such aliasing
-   are more portable, maintainable, and can usually be optimized better.
-
-   The current, as of April 2007, 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 expressions 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 three 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 a low count of 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 pun+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.
-
-   Future improvements can be included by adding higher levels.
-
-   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.
-
-   This implementation uses flow-sensitive points-to information.
-   Flow-sensitivity refers to accesses to the pointer, and not the object
-   pointed.  For instance, we do not warn about the following case.
-
-   Example 2.
-        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;
-
-
-   Algorithm Outline
-   =================
-
-   ForEach (ptr, object) in the points-to table
-     If (incompatible_types (*ptr, object))
-       If (referenced (ptr, current function)
-           and referenced (object, current function))
-         Issue warning (ptr, object, reference locations)
-
-   The complexity is:
-   O (sizeof (points-to table)
-      + sizeof (function body) * lookup_time (points-to table))
-
-   Pointer dereference locations are looked up on demand.  The search is
-   a single scan of the function body, in which all references to pointers
-   and objects in the points-to table are recorded.  However, this dominant
-   time factor occurs rarely, only when cross-type aliasing was detected.
-
-
-   Limitations of the Proposed Implementation
-   ==========================================
-
-   1. We do not catch the following case, because -fstrict-aliasing will
-      associate different tags with MEM while building points-to information,
-      thus before we get to analyze it.
-      XXX: this could be solved by either running with -fno-strict-aliasing
-      or by recording the points-to information before splitting the original
-      tag based on type.
-
-   Example 3.
-        void* mem = malloc (...);
-       int* pi = reinterpret_cast<int*> (mem);
-       float* b = reinterpret_cast<float*> (mem);
-       *b = 2.0;
-       return *pi+1;
-
-   2. We do not check whether the two conflicting (de)references can
-      reach each other in the control flow sense.  If we fixed limitation
-      1, we would wrongly issue a warning in the following case.
-
-   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;
-
-   3. Only simple types are compared, thus no structures, unions or classes
-      are analyzed.  A first attempt to deal with structures introduced much
-      complication and has not showed much improvement in preliminary tests,
-      so it was left out.
-
-   4. All analysis is intraprocedural.  */
-
-
-/* Local declarations.  */
-static void find_references_in_function (void);
-\f
-
-
-/* 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);
-}
-\f
-
-
-/* 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;
-  gimple 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, gimple stmt, void *data)
-{
-  struct alias_match *match = (struct alias_match *) data;
-  tree rhs_pointer = NULL_TREE;
-  tree to_match = NULL_TREE;
-
-  if (gimple_assign_cast_p (stmt))
-    rhs_pointer = gimple_assign_rhs1 (stmt);
-
-  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 gimple
-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;
-
-  if (TREE_CODE (object1) != SSA_NAME)
-    return NULL;
-
-  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 occurrences 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;
-}
-
-
-/* Record references to objects and pointer dereferences across some piece of
-   code.  The number of references is recorded for each item.
-   References to an object just to take its address are not counted.
-   For instance, if PTR is a pointer and OBJ is an object:
-   1. Expression &obj + *ptr will have the following reference match structure:
-   ptrs: <ptr, 1>
-   objs: <ptr, 1>
-   OBJ does not appear as referenced because we just take its address.
-   2. Expression ptr + *ptr will have the following reference match structure:
-   ptrs: <ptr, 1>
-   objs: <ptr, 2>
-   PTR shows up twice as an object, but is dereferenced only once.
-
-   The elements of the hash tables are gimple_map objects.  */
-struct reference_matches
-{
-  htab_t ptrs;
-  htab_t objs;
-};
-
-struct gimple_tree_map
-{
-  tree from;
-  gimple to;
-};
-
-/* Return true if the from tree in both gimple-tree maps are equal.
-   VA and VB are really instances of struct gimple_tree_map.  */
-
-static int
-gimple_tree_map_eq (const void *va, const void *vb)
-{
-  const struct gimple_tree_map *const a = (const struct gimple_tree_map *) va;
-  const struct gimple_tree_map *const b = (const struct gimple_tree_map *) vb;
-  return (a->from == b->from);
-}
-
-/* Hash a from tree in a gimple_tree_map.  ITEM is really an instance
-   of struct gimple_tree_map.  */
-
-static unsigned int
-gimple_tree_map_hash (const void *item)
-{
-  return htab_hash_pointer (((const struct gimple_tree_map *)item)->from);
-}
-
-/* Return the match, if any.  Otherwise, return NULL.  It will return
-   NULL even when a match was found, if the value associated to KEY is
-   NULL.  */
-
-static inline gimple
-match (htab_t ref_map, tree key)
-{
-  struct gimple_tree_map *found;
-  void **slot = NULL;
-  slot = htab_find_slot (ref_map, &key, NO_INSERT);
-
-  if (!slot)
-    return NULL;
-
-  found = (struct gimple_tree_map *) *slot;
-
-  return found->to;
-}
-
-
-/* Set the entry corresponding to KEY, but only if the entry
-   already exists and its value is NULL_TREE.  Otherwise, do nothing.  */
-
-static inline void
-maybe_add_match (htab_t ref_map, struct gimple_tree_map *key)
-{
-  struct gimple_tree_map *found;
-  
-  found = (struct gimple_tree_map *) htab_find (ref_map, key);
-
-  if (found && !found->to)
-    found->to = key->to;
-}
-
-
-/* Add an entry to HT, with key T and value NULL_TREE.  */
-
-static void
-add_key (htab_t ht, tree t, alloc_pool references_pool)
-{
-  void **slot;
-  struct gimple_tree_map *tp;
-  
-  tp = (struct gimple_tree_map *) pool_alloc (references_pool);
-
-  tp->from = t;
-  tp->to = NULL;
-  slot = htab_find_slot (ht, &t, INSERT);
-  *slot = (void *) tp;
-}
-
-
-/* Some memory to keep the objects in the reference table.  */
-
-static alloc_pool ref_table_alloc_pool = NULL;
-
-
-/* Get some memory to keep the objects in the reference table.  */
-
-static inline alloc_pool
-reference_table_alloc_pool (bool build)
-{
-  if (ref_table_alloc_pool || !build)
-    return ref_table_alloc_pool;
-
-  ref_table_alloc_pool = create_alloc_pool ("ref_table_alloc_pool",
-                                           sizeof (struct gimple_tree_map),
-                                           20);
-
-  return ref_table_alloc_pool;
-}
-
-
-/* Initialize the reference table by adding all pointers in the points-to
-   table as keys, and NULL_TREE as associated values.  */
-
-static struct reference_matches *
-build_reference_table (void)
-{
-  unsigned int i;
-  struct reference_matches *ref_table = NULL;
-  alloc_pool references_pool = reference_table_alloc_pool (true);
-
-  ref_table = XNEW (struct reference_matches);
-  ref_table->objs = htab_create (10, gimple_tree_map_hash, gimple_tree_map_eq,
-                                NULL);
-  ref_table->ptrs = htab_create (10, gimple_tree_map_hash, gimple_tree_map_eq,
-                                NULL);
-
-  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)
-       {
-         /* Add pointer to the interesting dereference list.  */
-         add_key (ref_table->ptrs, ptr, references_pool);
-
-         /* Add all aliased names to the interesting reference list.  */
-         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);
-                 add_key (ref_table->objs, alias, references_pool);
-               }
-           }
-       }
-    }
-
-  return ref_table;
-}
-
-
-/*  Reference table.  */
-
-static struct reference_matches *ref_table = NULL;
-
-
-/* Clean up the reference table if allocated.  */
-
-static void
-maybe_free_reference_table (void)
-{
-  if (ref_table)
-    {
-      htab_delete (ref_table->ptrs);
-      htab_delete (ref_table->objs);
-      free (ref_table);
-      ref_table = NULL;
-    }
-
-  if (ref_table_alloc_pool)
-    {
-      free_alloc_pool (ref_table_alloc_pool);
-      ref_table_alloc_pool = NULL;
-    }
-}
-
-
-/* Get the reference table.  Initialize it if needed.  */
-
-static inline struct reference_matches *
-reference_table (bool build)
-{
-  if (ref_table || !build)
-    return ref_table;
-
-  ref_table = build_reference_table ();
-  find_references_in_function ();
-  return ref_table;
-}
-
-
-/* Callback for find_references_in_function.
-   Check whether *TP is an object reference or pointer dereference for the
-   variables given in ((struct match_info*)DATA)->OBJS or
-   ((struct match_info*)DATA)->PTRS.  The total number of references
-   is stored in the same structures.  */
-
-static tree
-find_references_in_tree_helper (tree *tp,
-                               int *walk_subtrees ATTRIBUTE_UNUSED,
-                               void *data)
-{
-  struct gimple_tree_map match;
-  static int parent_tree_code = ERROR_MARK;
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
-
-  /* Do not report references just for the purpose of taking an address.
-     XXX: we rely on the fact that the tree walk is in preorder
-     and that ADDR_EXPR is not a leaf, thus cannot be carried over across
-     walks.  */
-  if (parent_tree_code == ADDR_EXPR)
-    goto finish;
-
-  match.to = (gimple) wi->info;
-
-  if (TREE_CODE (*tp) == INDIRECT_REF)
-    {
-      match.from = TREE_OPERAND (*tp, 0);
-      maybe_add_match (reference_table (true)->ptrs, &match);
-    }
-  else
-    {
-      match.from = *tp;
-      maybe_add_match (reference_table (true)->objs, &match);
-    }
-
-finish:
-  parent_tree_code = TREE_CODE (*tp);
-  return NULL_TREE;
-}
-
-
-/* Find all the references to aliased variables in the current function.  */
-
-static void
-find_references_in_function (void)
-{
-  basic_block bb;
-  gimple_stmt_iterator i;
-
-  FOR_EACH_BB (bb)
-    for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
-      {
-       struct walk_stmt_info wi;
-       memset (&wi, 0, sizeof (wi));
-       wi.info = (void *) gsi_stmt (i);
-       walk_gimple_op (gsi_stmt (i), find_references_in_tree_helper, &wi);
-      }
-}
-
-
-/* Find the reference site for OBJECT.
-   If IS_PTR is true, look for dereferences of OBJECT instead.
-   XXX: only the first site is returned in the current
-   implementation.  If there are no matching sites, return NULL_TREE.  */
-
-static gimple
-reference_site (tree object, bool is_ptr)
-{
-  if (is_ptr)
-    return match (reference_table (true)->ptrs, object);
-  else
-    return match (reference_table (true)->objs, object);
-}
-
-
-/* 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,
-                          gimple *alias_site,
-                          gimple *deref_site1,
-                          gimple *deref_site2)
-{
-  if (object1 && object2)
-    {
-      if (!*alias_site || !gimple_has_location (*alias_site))
-       *alias_site = find_alias_site (object1, is_ptr1, object2, is_ptr2);
-
-      if (!*deref_site1 || !gimple_has_location (*deref_site1))
-       *deref_site1 = reference_site (object1, is_ptr1);
-
-      if (!*deref_site2 || !gimple_has_location (*deref_site2))
-       *deref_site2 = reference_site (object2, is_ptr2);
-    }
-
-  /* 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 *go_below ATTRIBUTE_UNUSED,
-             void *data ATTRIBUTE_UNUSED)
-{
-  if (DECL_P (*t) && !MTAG_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 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 (gimple stmt)
-{
-  if (stmt == NULL)
-    return false;
-
-  if (gimple_assign_cast_p (stmt)
-      && TREE_NO_WARNING (gimple_assign_rhs1 (stmt)))
-    return true;
-  else
-    return false;
-}
-
-
-/* Return true if and only if TYPE is a function or method pointer type,
-   or pointer to a pointer to ... to a function or method.  */
-
-static bool
-is_method_pointer (tree type)
-{
-  while (TREE_CODE (type) == POINTER_TYPE)
-    type = TREE_TYPE (type);
-  return TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == FUNCTION_TYPE;
-}
-
-
-/* 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 (gimple alias_site,
-                      tree object1, bool is_ptr1,
-                      tree object2, bool is_ptr2,
-                     bool filter_artificials)
-{
-  gimple ref_site1 = NULL;
-  gimple ref_site2 = NULL;
-  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);
-
-
-  if (is_method_pointer (get_main_type (TREE_TYPE (object2))))
-    return false;
-
-  maybe_find_missing_stmts (object1, is_ptr1, object2, is_ptr2, &alias_site,
-                            &ref_site1, &ref_site2);
-
-  if (gimple_has_location (alias_site))
-    alias_loc = gimple_location (alias_site);
-  else
-    return false;
-
-  if (gimple_has_location (ref_site1))
-    ref1_loc = gimple_location (ref_site1);
-  else
-    ref1_loc = alias_loc;
-
-  if (gimple_has_location (ref_site2))
-    ref2_loc = gimple_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;
-}
-\f
-
-
-/* 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)
-{
-  alias_set_type set1;
-  alias_set_type set2;
-
-  if (VOID_TYPE_P (type1) || VOID_TYPE_P (type2))
-    return false;
-
-  set1 = get_alias_set (type1);
-  set2 = get_alias_set (type2);
-  return !alias_sets_conflict_p (set1, set2);
-}
-\f
-
-
-/* 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);
-
-  /* If this is a ref-all pointer the access is ok.  */
-  if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr)))
-    return false;
-
-  /* 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;
-
-  /* XXX: don't get into structures for now.  It brings much complication
-     and little benefit.  */
-  if (struct_class_union_p (ptr_type) || struct_class_union_p (alias_type))
-    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;
-
-  /* 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 ATTRIBUTE_UNUSED)
-{
-  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;
-         bool any = false;
-
-         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);
-             else
-               any = true;
-           }
-
-         /* If there was no object in the points-to set that the pointer
-            may alias, unconditionally warn.  */
-         if (!any)
-           warning (OPT_Wstrict_aliasing,
-                    "dereferencing type-punned pointer %D will "
-                    "break strict-aliasing rules", SSA_NAME_VAR (ptr));
-       }
-    }
-}
-
-
-/* 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);
-    }
-}
-
-
-/* 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, gimple_tree_map_hash, gimple_tree_map_eq, NULL);
-
-  slot = htab_find_slot (seen, &func, INSERT);
-  gcc_assert (slot);
-
-  if (*slot)
-    return true;
-
-  gcc_assert (slot);
-  *slot = &func;
-  return false;
-}
-
-
-/* Detect and warn about type-punning using points-to information.  */
-
-void
-strict_aliasing_warning_backend (void)
-{
-  if (flag_strict_aliasing && warn_strict_aliasing == 3
-      && !processed_func_p (current_function_decl))
-    {
-      detect_strict_aliasing_named ();
-      maybe_free_reference_table ();
-    }
-}
index 6155809..4e9d28b 100644 (file)
@@ -1825,9 +1825,6 @@ compute_may_aliases (void)
        dump_referenced_vars (dump_file);
     }
 
-  /* Report strict aliasing violations.  */
-  strict_aliasing_warning_backend ();
-
   /* Deallocate memory used by aliasing data structures.  */
   delete_alias_info (ai);
 
index aa01258..c71680a 100644 (file)
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "errors.h"
 #include "ggc.h"
 #include "tree.h"
 #include "basic-block.h"
index 3be76ac..46781b8 100644 (file)
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
-#include "errors.h"
-#include "diagnostic.h"
 #include "tree.h"
 #include "c-common.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
 #include "varray.h"
 #include "c-tree.h"
+#include "diagnostic.h"
+#include "toplev.h"
 #include "gimple.h"
 #include "hashtab.h"
 #include "function.h"
@@ -4648,14 +4648,15 @@ shared_bitmap_add (bitmap pt_vars)
    IS_DEREFED is true if PTR was directly dereferenced, which we use to
    help determine whether we are we are allowed to prune using TBAA.
    If NO_TBAA_PRUNING is true, we do not perform any TBAA pruning of
-   the from set.  */
+   the from set.  Returns the number of pruned variables.  */
 
-static void
+static unsigned
 set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
                   bool no_tbaa_pruning)
 {
   unsigned int i;
   bitmap_iterator bi;
+  unsigned pruned = 0;
 
   gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
 
@@ -4688,14 +4689,97 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
              if (may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
                               vi->decl, var_alias_set, true))
                bitmap_set_bit (into, DECL_UID (vi->decl));
+             else
+               ++pruned;
            }
        }
     }
+
+  return pruned;
 }
 
 
 static bool have_alias_info = false;
 
+/* Emit a note for the pointer initialization point DEF.  */
+
+static void
+emit_pointer_definition (gimple def)
+{
+  if (gimple_code (def) == GIMPLE_PHI)
+    {
+      use_operand_p argp;
+      ssa_op_iter oi;
+
+      FOR_EACH_PHI_ARG (argp, def, oi, SSA_OP_USE)
+       {
+         tree arg = USE_FROM_PTR (argp);
+         if (TREE_CODE (arg) == SSA_NAME)
+           emit_pointer_definition (SSA_NAME_DEF_STMT (arg));
+         else
+           inform (0, "initialized from %qE", arg);
+       }
+    }
+  else if (!gimple_nop_p (def))
+    inform (gimple_location (def), "initialized from here");
+}
+
+/* Emit a strict aliasing warning for dereferencing the pointer PTR.  */
+
+static void
+emit_alias_warning (tree ptr)
+{
+  gimple def = SSA_NAME_DEF_STMT (ptr);
+  gimple use;
+  imm_use_iterator ui;
+  unsigned warned = 0;
+
+  FOR_EACH_IMM_USE_STMT (use, ui, ptr)
+    {
+      tree deref = NULL_TREE;
+
+      if (gimple_has_lhs (use))
+       {
+         tree lhs = get_base_address (gimple_get_lhs (use));
+         if (lhs
+             && INDIRECT_REF_P (lhs)
+             && TREE_OPERAND (lhs, 0) == ptr)
+           deref = lhs;
+       }
+      if (gimple_assign_single_p (use))
+       {
+         tree rhs = get_base_address (gimple_assign_rhs1 (use));
+         if (rhs
+             && INDIRECT_REF_P (rhs)
+             && TREE_OPERAND (rhs, 0) == ptr)
+           deref = rhs;
+       }
+      else if (is_gimple_call (use))
+       {
+         unsigned i;
+         for (i = 0; i < gimple_call_num_args (use); ++i)
+           {
+             tree op = get_base_address (gimple_call_arg (use, i));
+             if (op
+                 && INDIRECT_REF_P (op)
+                 && TREE_OPERAND (op, 0) == ptr)
+               deref = op;
+           }
+       }
+      if (deref
+         && !TREE_NO_WARNING (deref))
+       {
+         TREE_NO_WARNING (deref) = 1;
+         warning_at (gimple_location (use), OPT_Wstrict_aliasing,
+                     "dereferencing pointer %qD does break strict-aliasing "
+                     "rules", SSA_NAME_VAR (ptr));
+         ++warned;
+       }
+    }
+  if (warned > 0)
+    emit_pointer_definition (def);
+}
+
 /* Given a pointer variable P, fill in its points-to set, or return
    false if we can't.
    Rather than return false for variables that point-to anything, we
@@ -4740,7 +4824,7 @@ find_what_p_points_to (tree p)
       else
        {
          struct ptr_info_def *pi = get_ptr_info (p);
-         unsigned int i;
+         unsigned int i, pruned;
          bitmap_iterator bi;
          bool was_pt_anything = false;
          bitmap finished_solution;
@@ -4792,9 +4876,9 @@ find_what_p_points_to (tree p)
          finished_solution = BITMAP_GGC_ALLOC ();
          stats.points_to_sets_created++;
 
-         set_uids_in_ptset (p, finished_solution, vi->solution,
-                            pi->is_dereferenced,
-                            vi->no_tbaa_pruning);
+         pruned = set_uids_in_ptset (p, finished_solution, vi->solution,
+                                     pi->is_dereferenced,
+                                     vi->no_tbaa_pruning);
          result = shared_bitmap_lookup (finished_solution);
 
          if (!result)
@@ -4809,7 +4893,22 @@ find_what_p_points_to (tree p)
            }
 
          if (bitmap_empty_p (pi->pt_vars))
-           pi->pt_vars = NULL;
+           {
+             pi->pt_vars = NULL;
+             if (pruned > 0
+                 && pi->is_dereferenced
+                 && warn_strict_aliasing > 0
+                 && !SSA_NAME_IS_DEFAULT_DEF (p))
+               {
+                 if (dump_file && dump_flags & TDF_DETAILS)
+                   {
+                     fprintf (dump_file, "alias warning for ");
+                     print_generic_expr (dump_file, p, 0);
+                     fprintf (dump_file, "\n");
+                   }
+                 emit_alias_warning (p);
+               }
+           }
 
          return true;
        }