re PR c/88928 (ICE segfault in check_address_or_pointer_of_packed_member since r268075)
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Mon, 21 Jan 2019 17:12:09 +0000 (17:12 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Mon, 21 Jan 2019 17:12:09 +0000 (17:12 +0000)
2019-01-21  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c/88928
        * c-warn.c (check_alignment_of_packed_member): Add a boolean parameter
        for rvalue context.  Handle rvalues correctly.  Use min_align_of_type
        instead of TYPE_ALIGN.
        (check_address_or_pointer_of_packed_member): Handle rvalues coorrectly.
        Use min_align_of_type instead of TYPE_ALIGN_UNIT.  Check for NULL
        pointer from TYPE_STUB_DECL.

testsuite:
2019-01-21  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c/88928
        * c-c++-common/Waddress-of-packed-member-1.c: New test case.
        * gcc.dg/pr88928.c: New test case.

From-SVN: r268118

gcc/ChangeLog
gcc/c-family/c-warn.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr88928.c [new file with mode: 0644]

index f785a4a9d179b2e6f29f282f02cfa3e933462d9e..ff92634df4ddcd37bcef605cb62b9aabed89001d 100644 (file)
@@ -1,3 +1,13 @@
+2019-01-21  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c/88928
+       * c-warn.c (check_alignment_of_packed_member): Add a boolean parameter
+       for rvalue context.  Handle rvalues correctly.  Use min_align_of_type
+       instead of TYPE_ALIGN.
+       (check_address_or_pointer_of_packed_member): Handle rvalues coorrectly.
+       Use min_align_of_type instead of TYPE_ALIGN_UNIT.  Check for NULL
+       pointer from TYPE_STUB_DECL.
+
 2019-01-21  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/88934
index 7821cc894a70da2aa79c3518aab89e943b151298..43b307acafec11f00fcb7e292f0f27a4111f7f3a 100644 (file)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "c-family/c-indentation.h"
 #include "calls.h"
+#include "stor-layout.h"
 
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
@@ -2688,25 +2689,26 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc,
 }
 
 /* Return struct or union type if the alignment of data memeber, FIELD,
-   is less than the alignment of TYPE.  Otherwise, return NULL_TREE.  */
+   is less than the alignment of TYPE.  Otherwise, return NULL_TREE.
+   If RVALUE is true, only arrays evaluate to pointers.  */
 
 static tree
-check_alignment_of_packed_member (tree type, tree field)
+check_alignment_of_packed_member (tree type, tree field, bool rvalue)
 {
   /* Check alignment of the data member.  */
   if (TREE_CODE (field) == FIELD_DECL
-      && (DECL_PACKED (field)
-         || TYPE_PACKED (TREE_TYPE (field))))
+      && (DECL_PACKED (field) || TYPE_PACKED (TREE_TYPE (field)))
+      && (!rvalue || TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE))
     {
       /* Check the expected alignment against the field alignment.  */
-      unsigned int type_align = TYPE_ALIGN (type);
+      unsigned int type_align = min_align_of_type (type);
       tree context = DECL_CONTEXT (field);
-      unsigned int record_align = TYPE_ALIGN (context);
-      if ((record_align % type_align) != 0)
+      unsigned int record_align = min_align_of_type (context);
+      if (record_align < type_align)
        return context;
       tree field_off = byte_position (field);
       if (!multiple_of_p (TREE_TYPE (field_off), field_off,
-                         size_int (type_align / BITS_PER_UNIT)))
+                         size_int (type_align)))
        return context;
     }
 
@@ -2722,19 +2724,27 @@ check_alignment_of_packed_member (tree type, tree field)
 static tree
 check_address_or_pointer_of_packed_member (tree type, tree rhs)
 {
+  bool rvalue = true;
+
   if (INDIRECT_REF_P (rhs))
     rhs = TREE_OPERAND (rhs, 0);
 
   if (TREE_CODE (rhs) == ADDR_EXPR)
-    rhs = TREE_OPERAND (rhs, 0);
+    {
+      rhs = TREE_OPERAND (rhs, 0);
+      rvalue = false;
+    }
+
+  if (!POINTER_TYPE_P (type))
+    return NULL_TREE;
 
-  if (POINTER_TYPE_P (type))
-    type = TREE_TYPE (type);
+  type = TREE_TYPE (type);
 
   if (TREE_CODE (rhs) == PARM_DECL
       || VAR_P (rhs)
       || TREE_CODE (rhs) == CALL_EXPR)
     {
+      tree rhstype = TREE_TYPE (rhs);
       if (TREE_CODE (rhs) == CALL_EXPR)
        {
          rhs = CALL_EXPR_FN (rhs);     /* Pointer expression.  */
@@ -2742,24 +2752,30 @@ check_address_or_pointer_of_packed_member (tree type, tree rhs)
            return NULL_TREE;
          rhs = TREE_TYPE (rhs);        /* Pointer type.  */
          rhs = TREE_TYPE (rhs);        /* Function type.  */
+         rhstype = TREE_TYPE (rhs);
+         if (!POINTER_TYPE_P (rhstype))
+           return NULL_TREE;
+         rvalue = true;
        }
-      tree rhstype = TREE_TYPE (rhs);
-      if ((POINTER_TYPE_P (rhstype)
-          || TREE_CODE (rhstype) == ARRAY_TYPE)
-         && TYPE_PACKED (TREE_TYPE (rhstype)))
+      if (rvalue && POINTER_TYPE_P (rhstype))
+       rhstype = TREE_TYPE (rhstype);
+      while (TREE_CODE (rhstype) == ARRAY_TYPE)
+       rhstype = TREE_TYPE (rhstype);
+      if (TYPE_PACKED (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)
+         unsigned int type_align = min_align_of_type (type);
+         unsigned int rhs_align = min_align_of_type (rhstype);
+         if (rhs_align < type_align)
            {
              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 "
+                         "to a %qT pointer (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");
+             tree decl = TYPE_STUB_DECL (rhstype);
+             if (decl)
+               inform (DECL_SOURCE_LOCATION (decl), "defined here");
              decl = TYPE_STUB_DECL (type);
              if (decl)
                inform (DECL_SOURCE_LOCATION (decl), "defined here");
@@ -2776,7 +2792,7 @@ check_address_or_pointer_of_packed_member (tree type, tree rhs)
       if (TREE_CODE (rhs) == COMPONENT_REF)
        {
          tree field = TREE_OPERAND (rhs, 1);
-         context = check_alignment_of_packed_member (type, field);
+         context = check_alignment_of_packed_member (type, field, rvalue);
          if (context)
            break;
        }
index 653f35532143a683bb7e642198b1763eb1a56df9..c86de12e9a77ce1c003880cd81d1c44a27e5f419 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-21  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c/88928
+       * c-c++-common/Waddress-of-packed-member-1.c: New test case.
+       * gcc.dg/pr88928.c: New test case.
+
 2019-01-21  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/utf-array.c: Allow wchar_t to be printed as
diff --git a/gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c b/gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c
new file mode 100644 (file)
index 0000000..a1374fb
--- /dev/null
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-Waddress-of-packed-member" } */
+
+struct t {
+  char a;
+  int b;
+  int *c;
+  int d[10];
+} __attribute__((packed));
+
+struct t t0;
+struct t t10[10];
+struct t t100[10][10];
+struct t *t1;
+struct t **t2;
+struct t *bar();
+struct t (*baz())[10];
+struct t (*bazz())[10][10];
+int *i1;
+__UINTPTR_TYPE__ u1;
+__UINTPTR_TYPE__ baa();
+
+void foo (void)
+{
+  t1 = &t0;                    /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = t10;                    /* { dg-bogus "may result in an unaligned pointer value" } */
+  t2 = &t1;                    /* { dg-bogus "may result in an unaligned pointer value" } */
+  t2 = t2;                     /* { dg-bogus "may result in an unaligned pointer value" } */
+  t2 = (struct t**)t2;         /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = (struct t*)t2;          /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = bar();                  /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = (struct t*) baz();      /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = (struct t*) bazz();     /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = *baz();                 /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = **bazz();               /* { dg-bogus "may result in an unaligned pointer value" } */
+  t1 = (struct t*) baa();      /* { dg-bogus "may result in an unaligned pointer value" } */
+  t2 = (struct t**) baa();     /* { dg-bogus "may result in an unaligned pointer value" } */
+  i1 = t0.c;                   /* { dg-bogus "may result in an unaligned pointer value" } */
+  i1 = t1->c;                  /* { dg-bogus "may result in an unaligned pointer value" } */
+  i1 = t10[0].c;               /* { dg-bogus "may result in an unaligned pointer value" } */
+  u1 = (__UINTPTR_TYPE__) &t0; /* { dg-bogus "may result in an unaligned pointer value" } */
+  u1 = (__UINTPTR_TYPE__) t1;  /* { dg-bogus "may result in an unaligned pointer value" } */
+  t2 = (struct t**) t10;     /* { dg-warning "may result in an unaligned pointer value" } */
+  t2 = (struct t**) t100;    /* { dg-warning "may result in an unaligned pointer value" } */
+  t2 = (struct t**) t1;      /* { dg-warning "may result in an unaligned pointer value" } */
+  t2 = (struct t**) bar();   /* { dg-warning "may result in an unaligned pointer value" } */
+  t2 = (struct t**) baz();   /* { dg-warning "may result in an unaligned pointer value" } */
+  t2 = (struct t**) bazz();  /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = &t0.b;                /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = &t1->b;               /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = &t10[0].b;            /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = t0.d;                 /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = t1->d;                /* { dg-warning "may result in an unaligned pointer value" } */
+  i1 = t10[0].d;             /* { dg-warning "may result in an unaligned pointer value" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr88928.c b/gcc/testsuite/gcc.dg/pr88928.c
new file mode 100644 (file)
index 0000000..c0a1f76
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wno-pedantic -Waddress-of-packed-member" } */
+struct a { } __attribute__((__packed__));
+void c (struct a **);
+void d (const struct a *b) { c ((struct a **) b); }
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */