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 <[email protected]>
+
+ * 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 <[email protected]>
* 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