diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2019-01-21 17:12:09 +0000 |
---|---|---|
committer | Bernd Edlinger <edlinger@gcc.gnu.org> | 2019-01-21 17:12:09 +0000 |
commit | f3a18a5c6cb1fed68ea519f731c8078af2f2f657 (patch) | |
tree | c0fe35267116ff647019a5081d6f5c3a4a6f3d41 /gcc | |
parent | 0fba41e0f0b1fd1db24709577564866dec047c3b (diff) | |
download | gcc-f3a18a5c6cb1fed68ea519f731c8078af2f2f657.zip gcc-f3a18a5c6cb1fed68ea519f731c8078af2f2f657.tar.gz gcc-f3a18a5c6cb1fed68ea519f731c8078af2f2f657.tar.bz2 |
re PR c/88928 (ICE segfault in check_address_or_pointer_of_packed_member since r268075)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 60 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c | 55 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr88928.c | 6 |
5 files changed, 115 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f785a4a..ff92634 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 7821cc8..43b307a 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 653f355..c86de12 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..a1374fb --- /dev/null +++ b/gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c @@ -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 index 0000000..c0a1f76 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88928.c @@ -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 } */ |