[PATCH] Fix PR36509, re-enable alias warnings from PTA
Richard Guenther
rguenther@suse.de
Wed Dec 3 10:00:00 GMT 2008
This re-implements alias warnings from PTA in a way to only warn if
we are sure the warning is not a false positive and in a way aware
of TBAA pruning done by PTA. The previous implementation was
pretty much ineffective after TBAA pruning was fixed.
Bootstrapped and tested on x86_64-unknown-linux-gnu, I plan to apply
this tomorrow in case of no further comments.
Thanks,
Richard.
2008-12-03 Richard Guenther <rguenther@suse.de>
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.
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig 2008-12-01 15:56:42.000000000 +0100
--- gcc/Makefile.in 2008-12-01 15:57:10.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-07-21 11:04:54.000000000 +0200
--- gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c 2008-12-01 15:57:10.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-08-08 12:04:06.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 11:32:43.000000000 +0100
--- gcc/tree-ssa-alias.c 2008-12-01 15:57:10.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-27 10:45:08.000000000 +0100
--- gcc/tree-ssa-structalias.c 2008-12-01 15:57:10.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-10-13 10:58:07.000000000 +0200
--- gcc/tree-ssa-reassoc.c 2008-12-01 15:57:10.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 2007-11-30 13:59:37.000000000 +0100
--- gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C 2008-12-01 15:57:10.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: gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
===================================================================
*** gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c.orig 2007-11-30 13:59:34.000000000 +0100
--- gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c 2008-12-01 16:00:07.000000000 +0100
*************** int foo()
*** 8,10 ****
--- 8,13 ----
*(long*)&i = 0; /* { dg-warning "type-punn" } */
return i;
}
+
+ /* { dg-message "does break strict-aliasing" "" { target *-*-* } 8 } */
+ /* { dg-message "initialized" "" { target *-*-* } 8 } */
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c (revision 142371)
--- gcc/tree-inline.c (working copy)
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 710,715 ****
--- 710,716 ----
{
*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;
Index: gcc/cp/typeck.c
===================================================================
*** gcc/cp/typeck.c (revision 142371)
--- gcc/cp/typeck.c (working copy)
*************** get_member_function_from_ptrfunc (tree *
*** 2790,2795 ****
--- 2790,2799 ----
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,
More information about the Gcc-patches
mailing list