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