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  <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/g++.dg/warn/Wstrict-aliasing-inline-parameter.C: New test.
+
 2014-08-21  Manuel López-Ibáñez  <m...@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


Reply via email to