c-family: Update unaligned adress of packed member check
authorH.J. Lu <hongjiu.lu@intel.com>
Fri, 18 Jan 2019 13:05:18 +0000 (13:05 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Fri, 18 Jan 2019 13:05:18 +0000 (05:05 -0800)
Check unaligned pointer conversion and strip NOPS.

gcc/c-family/

PR c/51628
PR c/88664
* c-common.h (warn_for_address_or_pointer_of_packed_member):
Remove the boolean argument.
* c-warn.c (check_address_of_packed_member): Renamed to ...
(check_address_or_pointer_of_packed_member): This.  Also
warn pointer conversion.
(check_and_warn_address_of_packed_member): Renamed to ...
(check_and_warn_address_or_pointer_of_packed_member): This.
Also warn pointer conversion.
(warn_for_address_or_pointer_of_packed_member): Remove the
boolean argument.  Don't check pointer conversion here.

gcc/c

PR c/51628
PR c/88664
* c-typeck.c (convert_for_assignment): Upate the
warn_for_address_or_pointer_of_packed_member call.

gcc/cp

PR c/51628
PR c/88664
* call.c (convert_for_arg_passing): Upate the
warn_for_address_or_pointer_of_packed_member call.
* typeck.c (convert_for_assignment): Likewise.

gcc/testsuite/

PR c/51628
PR c/88664
* c-c++-common/pr51628-33.c: New test.
* c-c++-common/pr51628-35.c: New test.
* c-c++-common/pr88664-1.c: Likewise.
* c-c++-common/pr88664-2.c: Likewise.
* gcc.dg/pr51628-34.c: Likewise.

From-SVN: r268075

14 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/c-warn.c
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr51628-33.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr51628-35.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr88664-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr88664-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr51628-34.c [new file with mode: 0644]

index 03ea65b4bce40b43f6993f726fd00d8079abfa69..4aaf8197e7e7bbe3edaeace20c58ef54b4982905 100644 (file)
@@ -1,3 +1,18 @@
+2019-01-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR c/51628
+       PR c/88664
+       * c-common.h (warn_for_address_or_pointer_of_packed_member):
+       Remove the boolean argument.
+       * c-warn.c (check_address_of_packed_member): Renamed to ...
+       (check_address_or_pointer_of_packed_member): This.  Also
+       warn pointer conversion.
+       (check_and_warn_address_of_packed_member): Renamed to ...
+       (check_and_warn_address_or_pointer_of_packed_member): This.
+       Also warn pointer conversion.
+       (warn_for_address_or_pointer_of_packed_member): Remove the
+       boolean argument.  Don't check pointer conversion here.
+
 2019-01-15  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR inline-asm/52813
index 9fe90f32b163aaa4ec5e83475ea8912718deab08..69cb76cf49dd54acf7c8b8a659c866ac888966f0 100644 (file)
@@ -1293,7 +1293,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
                                  bool);
 extern void warn_for_omitted_condop (location_t, tree);
 extern bool warn_for_restrict (unsigned, tree *, unsigned);
-extern void warn_for_address_or_pointer_of_packed_member (bool, tree, tree);
+extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.
    Used to select diagnostic messages in lvalue_error and
index 79b2d8ad4490c974b7e499d2c32061310b622675..7821cc894a70da2aa79c3518aab89e943b151298 100644 (file)
@@ -2713,12 +2713,14 @@ check_alignment_of_packed_member (tree type, tree field)
   return NULL_TREE;
 }
 
-/* Return struct or union type if the right hand value, RHS, takes the
-   unaligned address of packed member of struct or union when assigning
-   to TYPE.  Otherwise, return NULL_TREE.  */
+/* Return struct or union type if the right hand value, RHS:
+   1. Is a pointer value which isn't aligned to a pointer type TYPE.
+   2. Is an address which takes the unaligned address of packed member
+      of struct or union when assigning to TYPE.
+   Otherwise, return NULL_TREE.  */
 
 static tree
-check_address_of_packed_member (tree type, tree rhs)
+check_address_or_pointer_of_packed_member (tree type, tree rhs)
 {
   if (INDIRECT_REF_P (rhs))
     rhs = TREE_OPERAND (rhs, 0);
@@ -2726,6 +2728,46 @@ check_address_of_packed_member (tree type, tree rhs)
   if (TREE_CODE (rhs) == ADDR_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
+  if (POINTER_TYPE_P (type))
+    type = TREE_TYPE (type);
+
+  if (TREE_CODE (rhs) == PARM_DECL
+      || VAR_P (rhs)
+      || TREE_CODE (rhs) == CALL_EXPR)
+    {
+      if (TREE_CODE (rhs) == CALL_EXPR)
+       {
+         rhs = CALL_EXPR_FN (rhs);     /* Pointer expression.  */
+         if (rhs == NULL_TREE)
+           return NULL_TREE;
+         rhs = TREE_TYPE (rhs);        /* Pointer type.  */
+         rhs = TREE_TYPE (rhs);        /* Function type.  */
+       }
+      tree rhstype = TREE_TYPE (rhs);
+      if ((POINTER_TYPE_P (rhstype)
+          || TREE_CODE (rhstype) == ARRAY_TYPE)
+         && TYPE_PACKED (TREE_TYPE (rhstype)))
+       {
+         unsigned int type_align = TYPE_ALIGN_UNIT (type);
+         unsigned int rhs_align = TYPE_ALIGN_UNIT (TREE_TYPE (rhstype));
+         if ((rhs_align % type_align) != 0)
+           {
+             location_t location = EXPR_LOC_OR_LOC (rhs, input_location);
+             warning_at (location, OPT_Waddress_of_packed_member,
+                         "converting a packed %qT pointer (alignment %d) "
+                         "to %qT (alignment %d) may result in an "
+                         "unaligned pointer value",
+                         rhstype, rhs_align, type, type_align);
+             tree decl = TYPE_STUB_DECL (TREE_TYPE (rhstype));
+             inform (DECL_SOURCE_LOCATION (decl), "defined here");
+             decl = TYPE_STUB_DECL (type);
+             if (decl)
+               inform (DECL_SOURCE_LOCATION (decl), "defined here");
+           }
+       }
+      return NULL_TREE;
+    }
+
   tree context = NULL_TREE;
 
   /* Check alignment of the object.  */
@@ -2744,18 +2786,56 @@ check_address_of_packed_member (tree type, tree rhs)
   return context;
 }
 
-/* Check and warn if the right hand value, RHS, takes the unaligned
-   address of packed member of struct or union when assigning to TYPE.  */
+/* Check and warn if the right hand value, RHS:
+   1. Is a pointer value which isn't aligned to a pointer type TYPE.
+   2. Is an address which takes the unaligned address of packed member
+      of struct or union when assigning to TYPE.
+ */
 
 static void
-check_and_warn_address_of_packed_member (tree type, tree rhs)
+check_and_warn_address_or_pointer_of_packed_member (tree type, tree rhs)
 {
-  if (TREE_CODE (rhs) != COND_EXPR)
+  bool nop_p;
+
+  while (TREE_CODE (rhs) == COMPOUND_EXPR)
+    rhs = TREE_OPERAND (rhs, 1);
+
+  tree orig_rhs = rhs;
+  STRIP_NOPS (rhs);
+  nop_p = orig_rhs != rhs;
+
+  if (TREE_CODE (rhs) == COND_EXPR)
     {
-      while (TREE_CODE (rhs) == COMPOUND_EXPR)
-       rhs = TREE_OPERAND (rhs, 1);
+      /* Check the THEN path.  */
+      check_and_warn_address_or_pointer_of_packed_member
+       (type, TREE_OPERAND (rhs, 1));
 
-      tree context = check_address_of_packed_member (type, rhs);
+      /* Check the ELSE path.  */
+      check_and_warn_address_or_pointer_of_packed_member
+       (type, TREE_OPERAND (rhs, 2));
+    }
+  else
+    {
+      if (nop_p)
+       {
+         switch (TREE_CODE (rhs))
+           {
+           case ADDR_EXPR:
+             /* Address is taken.   */
+           case PARM_DECL:
+           case VAR_DECL:
+             /* Pointer conversion.  */
+             break;
+           case CALL_EXPR:
+             /* Function call. */
+             break;
+           default:
+             return;
+           }
+       }
+
+      tree context
+       = check_address_or_pointer_of_packed_member (type, rhs);
       if (context)
        {
          location_t loc = EXPR_LOC_OR_LOC (rhs, input_location);
@@ -2764,26 +2844,17 @@ check_and_warn_address_of_packed_member (tree type, tree rhs)
                      "in an unaligned pointer value",
                      context);
        }
-      return;
     }
-
-  /* Check the THEN path.  */
-  check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 1));
-
-  /* Check the ELSE path.  */
-  check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 2));
 }
 
 /* Warn if the right hand value, RHS:
-   1. For CONVERT_P == true, is a pointer value which isn't aligned to a
-      pointer type TYPE.
-   2. For CONVERT_P == false, is an address which takes the unaligned
-      address of packed member of struct or union when assigning to TYPE.
+   1. Is a pointer value which isn't aligned to a pointer type TYPE.
+   2. Is an address which takes the unaligned address of packed member
+      of struct or union when assigning to TYPE.
 */
 
 void
-warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type,
-                                             tree rhs)
+warn_for_address_or_pointer_of_packed_member (tree type, tree rhs)
 {
   if (!warn_address_of_packed_member)
     return;
@@ -2792,61 +2863,5 @@ warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type,
   if (!POINTER_TYPE_P (type))
     return;
 
-  while (TREE_CODE (rhs) == COMPOUND_EXPR)
-    rhs = TREE_OPERAND (rhs, 1);
-
-  if (convert_p)
-    {
-      bool rhspointer_p;
-      tree rhstype;
-
-      /* Check the original type of RHS.  */
-      switch (TREE_CODE (rhs))
-       {
-       case PARM_DECL:
-       case VAR_DECL:
-         rhstype = TREE_TYPE (rhs);
-         rhspointer_p = POINTER_TYPE_P (rhstype);
-         break;
-       case NOP_EXPR:
-         rhs = TREE_OPERAND (rhs, 0);
-         if (TREE_CODE (rhs) == ADDR_EXPR)
-           rhs = TREE_OPERAND (rhs, 0);
-         rhstype = TREE_TYPE (rhs);
-         rhspointer_p = TREE_CODE (rhstype) == ARRAY_TYPE;
-         break;
-       default:
-         return;
-       }
-
-      if (rhspointer_p && TYPE_PACKED (TREE_TYPE (rhstype)))
-       {
-         unsigned int type_align = TYPE_ALIGN_UNIT (TREE_TYPE (type));
-         unsigned int rhs_align = TYPE_ALIGN_UNIT (TREE_TYPE (rhstype));
-         if ((rhs_align % type_align) != 0)
-           {
-             location_t location = EXPR_LOC_OR_LOC (rhs, input_location);
-             warning_at (location, OPT_Waddress_of_packed_member,
-                         "converting a packed %qT pointer (alignment %d) "
-                         "to %qT (alignment %d) may result in an "
-                         "unaligned pointer value",
-                         rhstype, rhs_align, type, type_align);
-             tree decl = TYPE_STUB_DECL (TREE_TYPE (rhstype));
-             inform (DECL_SOURCE_LOCATION (decl), "defined here");
-             decl = TYPE_STUB_DECL (TREE_TYPE (type));
-             if (decl)
-               inform (DECL_SOURCE_LOCATION (decl), "defined here");
-           }
-       }
-    }
-  else
-    {
-      /* Get the type of the pointer pointing to.  */
-      type = TREE_TYPE (type);
-
-      if (TREE_CODE (rhs) == NOP_EXPR)
-       rhs = TREE_OPERAND (rhs, 0);
-
-      check_and_warn_address_of_packed_member (type, rhs);
-    }
+  check_and_warn_address_or_pointer_of_packed_member (type, rhs);
 }
index 2accb8fc9016c5b33821a297419bc2a542f172ad..fe83d69de8777cd6fd52284df31be5fddd5d5145 100644 (file)
@@ -1,3 +1,10 @@
+2019-01-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR c/51628
+       PR c/88664
+       * c-typeck.c (convert_for_assignment): Upate the
+       warn_for_address_or_pointer_of_packed_member call.
+
 2019-01-16  Tom Honermann  <tom@honermann.net>
            Jason Merrill  <jason@redhat.com>
 
index 6da1f321835583c10be4ceee1da97c3878907d13..cbd612c4fb936c3b3893260ce92e80d583bae387 100644 (file)
@@ -6729,8 +6729,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     {
-      warn_for_address_or_pointer_of_packed_member (false, type,
-                                                   orig_rhs);
+      warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
       return rhs;
     }
 
@@ -7289,8 +7288,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 
       /* If RHS isn't an address, check pointer or array of packed
         struct or union.  */
-      warn_for_address_or_pointer_of_packed_member
-       (TREE_CODE (orig_rhs) != ADDR_EXPR, type, orig_rhs);
+      warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
 
       return convert (type, rhs);
     }
index 3fb1a895b5ac9f18102a8cebb8bd47a84cf19a04..d224b72c0bb94dd5bc1cf63802e05b664b9d0381 100644 (file)
@@ -1,3 +1,11 @@
+2019-01-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR c/51628
+       PR c/88664
+       * call.c (convert_for_arg_passing): Upate the
+       warn_for_address_or_pointer_of_packed_member call.
+       * typeck.c (convert_for_assignment): Likewise.
+
 2019-01-17  Jason Merrill  <jason@redhat.com>
 
        PR c++/86205 - ICE with ?: of throw and template-id.
index c639f5f23e86ea4d35eb0f0179559690048e1c45..499894b353f01a93c866cfd1ac5062d06be10af4 100644 (file)
@@ -7644,7 +7644,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
     }
 
   if (complain & tf_warning)
-    warn_for_address_or_pointer_of_packed_member (false, type, val);
+    warn_for_address_or_pointer_of_packed_member (type, val);
 
   return val;
 }
index 2fff2625bee1c3da5929f76bbe6acf2fb6a256b8..47e407d1faae97a380b6253f12039702ecd60434 100644 (file)
@@ -9069,7 +9069,7 @@ convert_for_assignment (tree type, tree rhs,
     }
 
   if (complain & tf_warning)
-    warn_for_address_or_pointer_of_packed_member (false, type, rhs);
+    warn_for_address_or_pointer_of_packed_member (type, rhs);
 
   return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
                                            complain, flags);
index dbb02baff4ac202e3220fea69175164d96681a50..88a590ee9fa93d0261106973b92833f90a2c46f0 100644 (file)
@@ -1,3 +1,13 @@
+2019-01-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR c/51628
+       PR c/88664
+       * c-c++-common/pr51628-33.c: New test.
+       * c-c++-common/pr51628-35.c: New test.
+       * c-c++-common/pr88664-1.c: Likewise.
+       * c-c++-common/pr88664-2.c: Likewise.
+       * gcc.dg/pr51628-34.c: Likewise.
+
 2019-01-18  Richard Earnshaw  <rearnsha@arm.com>
 
        PR target/88799
diff --git a/gcc/testsuite/c-c++-common/pr51628-33.c b/gcc/testsuite/c-c++-common/pr51628-33.c
new file mode 100644 (file)
index 0000000..0092f32
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR c/51628.  */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct pair_t
+{
+  char x;
+  int i[4];
+} __attribute__ ((packed, aligned (4)));
+
+extern struct pair_t p;
+extern void bar (int *);
+
+void
+foo (struct pair_t *p)
+{
+  bar (p ? p->i : (int *) 0);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/pr51628-35.c b/gcc/testsuite/c-c++-common/pr51628-35.c
new file mode 100644 (file)
index 0000000..2087779
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR c/51628.  */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct B { int i; };
+struct C { struct B b; } __attribute__ ((packed));
+
+extern struct C *p;
+extern struct C *bar (void);
+
+long *
+foo1 (void)
+{
+  return (long *) p;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+long *
+foo2 (void)
+{
+  return (long *) bar ();
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/pr88664-1.c b/gcc/testsuite/c-c++-common/pr88664-1.c
new file mode 100644 (file)
index 0000000..5e680b9
--- /dev/null
@@ -0,0 +1,20 @@
+/* PR c/88664.  */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct data
+{
+  void *ptr;
+} __attribute__((packed));
+
+int *
+fun1 (struct data *p)
+{
+  return (int *) p->ptr;
+}
+
+int *
+fun2 (struct data *p, int *x)
+{
+  return x ? (*x = 1, (int *) p->ptr) : (int *) 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr88664-2.c b/gcc/testsuite/c-c++-common/pr88664-2.c
new file mode 100644 (file)
index 0000000..d2d880a
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR c/88664.  */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct data
+{
+  void *ptr;
+} __attribute__((packed));
+
+void **
+fun1 (struct data *p)
+{
+  return &p->ptr;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+int *
+fun2 (struct data *p, int *x)
+{
+  return p ? (*x = 1, (int *) &p->ptr) : (int *) 0;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr51628-34.c b/gcc/testsuite/gcc.dg/pr51628-34.c
new file mode 100644 (file)
index 0000000..51d4b26
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR c/51628.  */
+/* { dg-do compile } */
+/* { dg-options "-O -Wno-incompatible-pointer-types" } */
+
+struct __attribute__((packed)) S { char p; int a, b, c; };
+
+short *
+baz (int x, struct S *p)
+{
+  return (x
+         ? &p->a 
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+         : &p->b);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+short *
+qux (int x, struct S *p)
+{
+  return (short *) (x
+                   ?  &p->a
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+                   : &p->b);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}