On Tue, Aug 19, 2014 at 7:20 AM, lin zuojian <manjian2...@gmail.com> wrote: > Hi, > Here patch v2. Move the function as Andrew instructed. > > * tree-inline.c (setup_one_parameter): Add strict aliasing check. > * c-family/c-common.c (strict_aliasing_warning): Move to alias.c. > * c-family/c-common.h (strict_aliasing_warning): Move to tree.h. > * alias.c (strict_aliasing_warning): New function moved from > c-family/c-common.c. > * tree.h (strict_aliasing_warning): New function declaration moved from > c-family/c-common.h. > * testsuite/gcc.dg/Wstrict-aliasing-inline.C: New test.
Generally I don't think we want to expand the use of the IMHO broken strict_aliasing_warning code. We should be able to do better after some constant/forward propagation, scanning for MEM_REFs operating on decls and accessing those with an alias set that is not a subset of the set of the decl. Like simply warn as part of the tree-ssa-forwprop.c sweep (maybe only for those MEM_REFs we simplified to avoid duplicates, but then also watch for CCP doing the same). Richard. > --- > gcc/ChangeLog | 11 +++ > gcc/alias.c | 78 > ++++++++++++++++++++++ > gcc/c-family/c-common.c | 78 > ---------------------- > gcc/c-family/c-common.h | 1 - > .../gcc.dg/Wstrict-aliasing-inline-parameter.C | 42 ++++++++++++ > gcc/tree-inline.c | 4 ++ > gcc/tree.h | 2 + > 7 files changed, 137 insertions(+), 79 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/Wstrict-aliasing-inline-parameter.C > > diff --git a/gcc/ChangeLog b/gcc/ChangeLog > index 8ccdde2..6514313 100644 > --- a/gcc/ChangeLog > +++ b/gcc/ChangeLog > @@ -1,3 +1,14 @@ > +2014-08-19 Lin Zuojian <manjian2...@gmail.com> > + > + * tree-inline.c (setup_one_parameter): Add strict aliasing check. > + * c-family/c-common.c (strict_aliasing_warning): Move to alias.c. > + * c-family/c-common.h (strict_aliasing_warning): Move to tree.h. > + * alias.c (strict_aliasing_warning): New function moved from > + c-family/c-common.c. > + * tree.h (strict_aliasing_warning): New function declaration moved > from > + c-family/c-common.h. > + * testsuite/gcc.dg/Wstrict-aliasing-inline.C: New test. > + > 2014-08-19 David Malcolm <dmalc...@redhat.com> > > * basic-block.h (BB_HEAD): Convert to a function. Strengthen the > diff --git a/gcc/alias.c b/gcc/alias.c > index 39df09b..8496435 100644 > --- a/gcc/alias.c > +++ b/gcc/alias.c > @@ -3044,4 +3044,82 @@ end_alias_analysis (void) > sbitmap_free (reg_known_equiv_p); > } > > +/* Print a warning about casts that might indicate violation > + of strict aliasing rules if -Wstrict-aliasing is used and > + strict aliasing mode is in effect. OTYPE is the original > + TREE_TYPE of EXPR, and TYPE the type we're casting to. */ > + > +bool > +strict_aliasing_warning (tree otype, tree type, tree expr) > +{ > + /* Strip pointer conversion chains and get to the correct original type. > */ > + STRIP_NOPS (expr); > + otype = TREE_TYPE (expr); > + > + if (!(flag_strict_aliasing > + && POINTER_TYPE_P (type) > + && POINTER_TYPE_P (otype) > + && !VOID_TYPE_P (TREE_TYPE (type))) > + /* If the type we are casting to is a ref-all pointer > + dereferencing it is always valid. */ > + || TYPE_REF_CAN_ALIAS_ALL (type)) > + return false; > + > + if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR > + && (DECL_P (TREE_OPERAND (expr, 0)) > + || handled_component_p (TREE_OPERAND (expr, 0)))) > + { > + /* Casting the address of an object to non void pointer. Warn > + if the cast breaks type based aliasing. */ > + if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2) > + { > + warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " > + "might break strict-aliasing rules"); > + return true; > + } > + else > + { > + /* warn_strict_aliasing >= 3. This includes the default (3). > + Only warn if the cast is dereferenced immediately. */ > + alias_set_type set1 = > + get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))); > + alias_set_type set2 = get_alias_set (TREE_TYPE (type)); > + > + if (set1 != set2 && set2 != 0 > + && (set1 == 0 || !alias_sets_conflict_p (set1, set2))) > + { > + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > + "pointer will break strict-aliasing rules"); > + return true; > + } > + else if (warn_strict_aliasing == 2 > + && !alias_sets_must_conflict_p (set1, set2)) > + { > + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > + "pointer might break strict-aliasing rules"); > + return true; > + } > + } > + } > + else > + if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype))) > + { > + /* At this level, warn for any conversions, even if an address is > + not taken in the same statement. This will likely produce many > + false positives, but could be useful to pinpoint problems that > + are not revealed at higher levels. */ > + alias_set_type set1 = get_alias_set (TREE_TYPE (otype)); > + alias_set_type set2 = get_alias_set (TREE_TYPE (type)); > + if (!COMPLETE_TYPE_P (type) > + || !alias_sets_must_conflict_p (set1, set2)) > + { > + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > + "pointer might break strict-aliasing rules"); > + return true; > + } > + } > + > + return false; > +} > + > #include "gt-alias.h" > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c > index acc9a20..bc4f420 100644 > --- a/gcc/c-family/c-common.c > +++ b/gcc/c-family/c-common.c > @@ -1846,84 +1846,6 @@ warn_if_unused_value (const_tree exp, location_t locus) > } > > > -/* Print a warning about casts that might indicate violation > - of strict aliasing rules if -Wstrict-aliasing is used and > - strict aliasing mode is in effect. OTYPE is the original > - TREE_TYPE of EXPR, and TYPE the type we're casting to. */ > - > -bool > -strict_aliasing_warning (tree otype, tree type, tree expr) > -{ > - /* Strip pointer conversion chains and get to the correct original type. > */ > - STRIP_NOPS (expr); > - otype = TREE_TYPE (expr); > - > - if (!(flag_strict_aliasing > - && POINTER_TYPE_P (type) > - && POINTER_TYPE_P (otype) > - && !VOID_TYPE_P (TREE_TYPE (type))) > - /* If the type we are casting to is a ref-all pointer > - dereferencing it is always valid. */ > - || TYPE_REF_CAN_ALIAS_ALL (type)) > - return false; > - > - if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR > - && (DECL_P (TREE_OPERAND (expr, 0)) > - || handled_component_p (TREE_OPERAND (expr, 0)))) > - { > - /* Casting the address of an object to non void pointer. Warn > - if the cast breaks type based aliasing. */ > - if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2) > - { > - warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " > - "might break strict-aliasing rules"); > - return true; > - } > - else > - { > - /* warn_strict_aliasing >= 3. This includes the default (3). > - Only warn if the cast is dereferenced immediately. */ > - alias_set_type set1 = > - get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))); > - alias_set_type set2 = get_alias_set (TREE_TYPE (type)); > - > - if (set1 != set2 && set2 != 0 > - && (set1 == 0 || !alias_sets_conflict_p (set1, set2))) > - { > - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > - "pointer will break strict-aliasing rules"); > - return true; > - } > - else if (warn_strict_aliasing == 2 > - && !alias_sets_must_conflict_p (set1, set2)) > - { > - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > - "pointer might break strict-aliasing rules"); > - return true; > - } > - } > - } > - else > - if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype))) > - { > - /* At this level, warn for any conversions, even if an address is > - not taken in the same statement. This will likely produce many > - false positives, but could be useful to pinpoint problems that > - are not revealed at higher levels. */ > - alias_set_type set1 = get_alias_set (TREE_TYPE (otype)); > - alias_set_type set2 = get_alias_set (TREE_TYPE (type)); > - if (!COMPLETE_TYPE_P (type) > - || !alias_sets_must_conflict_p (set1, set2)) > - { > - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " > - "pointer might break strict-aliasing rules"); > - return true; > - } > - } > - > - return false; > -} > - > /* Warn about memset (&a, 0, sizeof (&a)); and similar mistakes with > sizeof as last operand of certain builtins. */ > > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h > index 26aaee2..1a10038 100644 > --- a/gcc/c-family/c-common.h > +++ b/gcc/c-family/c-common.h > @@ -770,7 +770,6 @@ extern void binary_op_error (location_t, enum tree_code, > tree, tree); > extern tree fix_string_type (tree); > extern void constant_expression_warning (tree); > extern void constant_expression_error (tree); > -extern bool strict_aliasing_warning (tree, tree, tree); > extern void sizeof_pointer_memaccess_warning (location_t *, tree, > vec<tree, va_gc> *, tree *, > bool (*) (tree, tree)); > diff --git a/gcc/testsuite/gcc.dg/Wstrict-aliasing-inline-parameter.C > b/gcc/testsuite/gcc.dg/Wstrict-aliasing-inline-parameter.C > new file mode 100644 > index 0000000..9a667be > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/Wstrict-aliasing-inline-parameter.C > @@ -0,0 +1,42 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wstrict-aliasing=10 -fstrict-aliasing" } */ > + > +struct A > +{ > + int a; > + int b; > + int c; > +}; > + > +static inline int hash2(const unsigned short* change2, int len) > +{ > + int result = 0; > + for(int i = 0; i < len; ++i) { > + > + result += change2[i]; > + result ^= result << 11; > + result += result >> 17; > + > + // Force "avalanching" of final 31 bits. > + result ^= result << 3; > + result += result >> 5; > + result ^= result << 2; > + result += result >> 15; > + result ^= result << 10; > + } > + return result; > +} > + > +static inline int hash(const void* change1, int len) > +{ > + return hash2(static_cast<const unsigned short*>(change1), len / 2); > +} > + > + > +int foo(int a, int b, int c) > +{ > + struct A a_struct = {a, b, c}; > + return hash(&a_struct, sizeof(struct A)); > +} > + > +/* { dg-message "dereferencing type-punned pointer will break > strict-aliasing rules" } */ > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c > index b6ecaa4..95e745c 100644 > --- a/gcc/tree-inline.c > +++ b/gcc/tree-inline.c > @@ -2913,6 +2913,10 @@ setup_one_parameter (copy_body_data *id, tree p, tree > value, tree fn, > } > } > > + if (warn_strict_aliasing > 2) > + if (strict_aliasing_warning (TREE_TYPE (rhs), TREE_TYPE(p), rhs)) > + warning (OPT_Wstrict_aliasing, "during inlining function %s into > function %s", fndecl_name(fn), function_name(cfun)); > + > /* Make an equivalent VAR_DECL. Note that we must NOT remap the type > here since the type of this decl must be visible to the calling > function. */ > diff --git a/gcc/tree.h b/gcc/tree.h > index e000e4e..e7c4318 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -4788,4 +4788,6 @@ extern tree get_inner_reference (tree, HOST_WIDE_INT *, > HOST_WIDE_INT *, > EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ > extern tree array_ref_low_bound (tree); > > +extern bool strict_aliasing_warning (tree, tree, tree); > + > #endif /* GCC_TREE_H */ > -- > 1.9.1 > > --- > Lin Zuojian