This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v4] Add strict aliasing warning when inlining function.
- From: lin zuojian <manjian2006 at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 21 Aug 2014 11:00:52 +0800
- Subject: [PATCH v4] Add strict aliasing warning when inlining function.
- Authentication-results: sourceware.org; auth=none
- References: <20140819043526 dot GA8929 at ubuntu> <20140820090856 dot GA31791 at ubuntu>
Hi,
This patch is to improve the output of strict_aliasing_warning. This
version will output the expression of rhs, type of that expression,
and the type of lhs. That make it easier to debug strict aliasing
bug.
* 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/g++.dg/warn/Wstrict-aliasing-inline-parameter.C: New test.
---
gcc/ChangeLog | 11 +++
gcc/alias.c | 107 +++++++++++++++++++++
gcc/c-family/c-common.c | 78 ---------------
gcc/c-family/c-common.h | 1 -
.../warn/Wstrict-aliasing-inline-parameter.C | 40 ++++++++
gcc/tree-inline.c | 4 +
gcc/tree.h | 2 +
7 files changed, 164 insertions(+), 79 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/warn/Wstrict-aliasing-inline-parameter.C
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1067203..bff6354 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2014-08-21 Lin Zuojian <manjian2006@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/g++.dg/warn/Wstrict-aliasing-inline-parameter.C: New test.
+
2014-08-21 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR fortran/44054
diff --git a/gcc/alias.c b/gcc/alias.c
index 39df09b..ab11ae3 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "is-a.h"
#include "gimple.h"
#include "gimple-ssa.h"
+#include "tree-pretty-print.h"
/* The aliasing API provided here solves related but different problems:
@@ -3044,4 +3045,110 @@ end_alias_analysis (void)
sbitmap_free (reg_known_equiv_p);
}
+/* Helper of strict_aliasing_warning to format warning. */
+static void
+strict_aliasing_warning_output (tree type, tree expr, const char *msg)
+{
+ pretty_printer pp;
+ pp_string (&pp, msg);
+ pp_dot (&pp);
+ pp_space (&pp);
+ pp_string (&pp, "With expression");
+ pp_colon (&pp);
+ pp_space (&pp);
+ dump_generic_node (&pp, expr, 0, 0, false);
+ pp_comma (&pp);
+ pp_space (&pp);
+ pp_string (&pp, "type of expresssion");
+ pp_colon (&pp);
+ pp_space (&pp);
+ dump_generic_node (&pp, TREE_TYPE (expr), 0, 0, false);
+ pp_comma (&pp);
+ pp_space (&pp);
+ pp_string (&pp, "type to cast");
+ pp_colon (&pp);
+ pp_space (&pp);
+ dump_generic_node (&pp, type, 0, 0, false);
+ pp_dot (&pp);
+ warning (OPT_Wstrict_aliasing, pp_formatted_text (&pp), NULL);
+}
+
+/* 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)
+ {
+ strict_aliasing_warning_output (type, expr, "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)))
+ {
+ strict_aliasing_warning_output (type, expr, "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
+ return true;
+ }
+ else if (warn_strict_aliasing == 2
+ && !alias_sets_must_conflict_p (set1, set2))
+ {
+ strict_aliasing_warning_output (type, expr, "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))
+ {
+ strict_aliasing_warning_output (type, expr, "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 c5eb2a7..b04a193 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 995bc8c..a375412 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/g++.dg/warn/Wstrict-aliasing-inline-parameter.C b/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-inline-parameter.C
new file mode 100644
index 0000000..a742eec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-inline-parameter.C
@@ -0,0 +1,40 @@
+/* { 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); /* { dg-warning "dereferencing type-punned pointer will break strict-aliasing rules|during inlining function.*into.*" } */
+}
+
+int foo(int a, int b, int c)
+{
+ struct A a_struct = {a, b, c};
+ return hash(&a_struct, sizeof(struct A));
+}
+
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