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]

[PATCH] Re-enable strict-aliasing warnings from points-to analysis


This re-enables the warnings that were disabled when we fixed TBAA
pruning of points-to sets.  It removes the old implementation and
only issues warnings for cases we do know we would miscompile if
we would not fall back to anything.  Which means we issue a warning
if TBAA pruning ends up pruning the points-to set to nothing, which
means there is no path in the program where a valid pointed-to object
is available.

Unfortunately this uncovers a problem with pmf access, see PR c++/38334.

Bootstrapped and tested on x86_64-unknown-linux-gnu with g++.dg/opt/pmf1.C
regressing.

All further false positives are either bugs in points-to analysis or bugs
in frontends or optimizers.  That said, wider testing is appreciated
(as is fixing PR38334).

Thanks,
Richard.

2008-11-30  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.

	* 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.

Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig	2008-10-25 20:28:12.000000000 +0200
--- gcc/Makefile.in	2008-11-30 16:24:31.000000000 +0100
*************** OBJS-common = \
*** 1243,1249 ****
  	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 \
--- 1243,1248 ----
*************** stor-layout.o : stor-layout.c $(CONFIG_H
*** 2089,2095 ****
     $(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 \
     $(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 \
--- 2088,2094 ----
     $(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 \
     $(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 \
*************** tree-ssa-loop-im.o : tree-ssa-loop-im.c 
*** 2309,2319 ****
  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 \
--- 2308,2313 ----
*************** tree-ssa-alias.o : tree-ssa-alias.c $(TR
*** 2321,2327 ****
     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) \
     $(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)
--- 2315,2321 ----
     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) $(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: gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
===================================================================
*** gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c.orig	2008-10-22 15:52:32.000000000 +0200
--- gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c	2008-11-30 19:40:20.000000000 +0100
*************** int foo() {
*** 11,22 ****
    float* r;
  
    if (flag) {
!     q = (float*) &x;  /* { dg-warning "type-punn" "" { xfail *-*-* } } */
    } else {
!     q = (float*) &y;  /* { dg-warning "type-punn" "" { xfail *-*-* } } */
    }
  
!   *q = 1.0;
  
    return x;
  
--- 11,22 ----
    float* r;
  
    if (flag) {
!     q = (float*) &x;  /* { dg-message "initialized" } */
    } else {
!     q = (float*) &y;  /* { dg-message "initialized" } */
    }
  
!   *q = 1.0;  /* { dg-warning "does break strict-aliasing" } */
  
    return x;
  
Index: gcc/tree-ssa-alias-warnings.c
===================================================================
*** gcc/tree-ssa-alias-warnings.c	2008-10-22 15:52:32.000000000 +0200
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
***************
*** 1,1033 ****
- /* 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);
- 
- 
- 
- /* 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;
-   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;
- }
- 
- 
- 
- /* 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);
- }
- 
- 
- 
- /* 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 ();
-     }
- }
--- 0 ----
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2008-11-25 22:26:54.000000000 +0100
--- gcc/tree-ssa-alias.c	2008-11-30 13:39:28.000000000 +0100
*************** compute_may_aliases (void)
*** 1825,1833 ****
  	dump_referenced_vars (dump_file);
      }
  
-   /* Report strict aliasing violations.  */
-   strict_aliasing_warning_backend ();
- 
    /* Deallocate memory used by aliasing data structures.  */
    delete_alias_info (ai);
  
--- 1825,1830 ----
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig	2008-11-28 12:23:43.000000000 +0100
--- gcc/tree-ssa-structalias.c	2008-11-30 19:38:56.000000000 +0100
***************
*** 31,44 ****
  #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 "gimple.h"
  #include "hashtab.h"
  #include "function.h"
--- 31,44 ----
  #include "hard-reg-set.h"
  #include "basic-block.h"
  #include "output.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"
*************** shared_bitmap_add (bitmap pt_vars)
*** 4648,4661 ****
     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.  */
  
! static void
  set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
  		   bool no_tbaa_pruning)
  {
    unsigned int i;
    bitmap_iterator bi;
  
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
  
--- 4648,4662 ----
     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.  Returns the number of pruned variables.  */
  
! 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)));
  
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4688,4701 ****
--- 4689,4785 ----
  	      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
*************** find_what_p_points_to (tree p)
*** 4740,4746 ****
        else
  	{
  	  struct ptr_info_def *pi = get_ptr_info (p);
! 	  unsigned int i;
  	  bitmap_iterator bi;
  	  bool was_pt_anything = false;
  	  bitmap finished_solution;
--- 4824,4830 ----
        else
  	{
  	  struct ptr_info_def *pi = get_ptr_info (p);
! 	  unsigned int i, pruned;
  	  bitmap_iterator bi;
  	  bool was_pt_anything = false;
  	  bitmap finished_solution;
*************** find_what_p_points_to (tree p)
*** 4792,4800 ****
  	  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);
  	  result = shared_bitmap_lookup (finished_solution);
  
  	  if (!result)
--- 4876,4884 ----
  	  finished_solution = BITMAP_GGC_ALLOC ();
  	  stats.points_to_sets_created++;
  
! 	  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)
*************** find_what_p_points_to (tree p)
*** 4808,4815 ****
  	      bitmap_clear (finished_solution);
  	    }
  
! 	  if (bitmap_empty_p (pi->pt_vars))
! 	    pi->pt_vars = NULL;
  
  	  return true;
  	}
--- 4892,4917 ----
  	      bitmap_clear (finished_solution);
  	    }
  
! 	  if (bitmap_empty_p (pi->pt_vars)
! 	      && pruned > 0)
! 	    {
! 	      pi->pt_vars = NULL;
! 	      if (pi->is_dereferenced
! 		  && warn_strict_aliasing > 0
! 		  && !SSA_NAME_IS_DEFAULT_DEF (p)
! 		  /* ???  We too often get empty solutions for
! 		     "non-pointers" that really are pointers.
! 		  && !bitmap_empty_p (vi->solution) */)
! 		{
! 		  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;
  	}
Index: gcc/tree-ssa-reassoc.c
===================================================================
*** gcc/tree-ssa-reassoc.c.orig	2008-11-30 16:19:37.000000000 +0100
--- gcc/tree-ssa-reassoc.c	2008-11-30 16:19:44.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 22,28 ****
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
- #include "errors.h"
  #include "ggc.h"
  #include "tree.h"
  #include "basic-block.h"
--- 22,27 ----
Index: gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
===================================================================
*** gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C.orig	2008-11-30 17:41:06.000000000 +0100
--- gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C	2008-11-30 19:44:18.000000000 +0100
***************
*** 4,10 ****
  
  int foo() {
    int x;
!   float& q = reinterpret_cast<float&> (x);  /* { dg-warning "type-punn" } */
!   q = 1.0;
    return x;
  }
--- 4,12 ----
  
  int foo() {
    int x;
!   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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]