On 1/24/19 8:18 AM, Jakub Jelinek wrote:
> On Thu, Jan 24, 2019 at 06:39:22AM +0000, Bernd Edlinger wrote:
>> --- gcc/c-family/c-warn.c (revision 268195)
>> +++ gcc/c-family/c-warn.c (working copy)
>> @@ -2725,14 +2725,18 @@ static tree
>> check_address_or_pointer_of_packed_member (tree type, tree rhs)
>> {
>> bool rvalue = true;
>> + bool indirect = false;
>>
>> if (INDIRECT_REF_P (rhs))
>> - rhs = TREE_OPERAND (rhs, 0);
>> + {
>> + rhs = TREE_OPERAND (rhs, 0);
>> + indirect = true;
>> + }
>>
>> if (TREE_CODE (rhs) == ADDR_EXPR)
>> {
>> rhs = TREE_OPERAND (rhs, 0);
>> - rvalue = false;
>> + rvalue = indirect;
>> }
>
> Given the unfolded *&, I wonder if the above actually shouldn't be
> a loop with indirection integral counter instead of a boolean
> and simply bump the indirection count on INDIRECT_REF_P and decrease on
> ADDR_EXPR, and if indirection count is > 0 after the loop return NULL_TREE?
> Say for *&*& or similar, and ***var.field always not warning etc.
>
Okay, somehow the *&*&x is partially reduced, and arrives as *&x, so that works,
also &*&x is also partially reduced, and arrives as &x, works too.
Since in all test cases the INDIRECT_REFs are at the beginning, and only max.
one
ADDR_EXPR at the end, the counting seems unnecessary, since neither the second
INDIRECT_REF nor the ADDR_EXPR are handled components, therefore there return
value is always NULL_TREE, and no warning, as expected.
Unfortunately **var.field should warn when field is a multi-dimensional array,
and again that did not work in C++, because it happens that after the
INDIRECT_REF there is a NOP_EXPR. So I would like to add a SKIP_NOP, to make
the following additional test cases work:
struct r {
int b[10][10];
int ****i4;
}
i0 = *s0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = *t0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = &**s0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = &**t0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = **&s0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = **&t0.p.b; /* { dg-warning "may result in an unaligned
pointer value" } */
i0 = ***s0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
i0 = ***t0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
i0 = ****&s0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
i0 = ****&t0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
i0 = &****s0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
i0 = &****t0.p.i4; /* { dg-bogus "may result in an unaligned
pointer value" } */
> Otherwise the patch looks good.
>
> Though you might throw in a few test lines with the intermixed casts and
> compound exprs multiple times (why you've added correctly the loop in
> there).
>
So I've added one more, now have the following:
i1 = (&t0.c, (int*) 0); /* { dg-bogus "may result in an unaligned
pointer value" } */
i1 = (0, (int*) &t0.c); /* { dg-warning "may result in an unaligned
pointer value" } */
i1 = (int*) (0, &t0.c); /* { dg-warning "may result in an unaligned
pointer value" } */
i1 = (0, (int*)(0, &t0.c));/* { dg-warning "may result in an unaligned
pointer value" } */
i1 = (int*)(0, 1, (void*)(2, 3, (int*)(4, 5, &t0.c)));/* { dg-warning "may
result in an unaligned pointer value" } */
Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?
Thanks
Bernd.
2019-01-25 Bernd Edlinger <bernd.edlin...@hotmail.de>
* c-warn.c (check_address_or_pointer_of_packed_member): Handle the case
when rhs is of array type correctly. Fix handling of nested structures.
Fix handling of indirect_ref together with nop_expr and/or addr_expr.
(check_and_warn_address_or_pointer_of_packed_member): Fix handling of
type casts within nested compound expressions.
testsuite:
2019-01-25 Bernd Edlinger <bernd.edlin...@hotmail.de>
* c-c++-common/Waddress-of-packed-member-1.c: Extended test case.
* c-c++-common/Waddress-of-packed-member-2.c: New test case.
Index: gcc/c-family/c-warn.c
===================================================================
--- gcc/c-family/c-warn.c (revision 268195)
+++ gcc/c-family/c-warn.c (working copy)
@@ -2725,14 +2725,19 @@ static tree
check_address_or_pointer_of_packed_member (tree type, tree rhs)
{
bool rvalue = true;
+ bool indirect = false;
if (INDIRECT_REF_P (rhs))
- rhs = TREE_OPERAND (rhs, 0);
+ {
+ rhs = TREE_OPERAND (rhs, 0);
+ STRIP_NOPS (rhs);
+ indirect = true;
+ }
if (TREE_CODE (rhs) == ADDR_EXPR)
{
rhs = TREE_OPERAND (rhs, 0);
- rvalue = false;
+ rvalue = indirect;
}
if (!POINTER_TYPE_P (type))
@@ -2796,6 +2801,10 @@ check_address_or_pointer_of_packed_member (tree ty
if (context)
break;
}
+ if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
+ rvalue = false;
+ if (rvalue)
+ return NULL_TREE;
rhs = TREE_OPERAND (rhs, 0);
}
@@ -2811,15 +2820,19 @@ check_address_or_pointer_of_packed_member (tree ty
static void
check_and_warn_address_or_pointer_of_packed_member (tree type, tree rhs)
{
- bool nop_p;
+ bool nop_p = false;
+ tree orig_rhs;
- while (TREE_CODE (rhs) == COMPOUND_EXPR)
- rhs = TREE_OPERAND (rhs, 1);
+ do
+ {
+ while (TREE_CODE (rhs) == COMPOUND_EXPR)
+ rhs = TREE_OPERAND (rhs, 1);
+ orig_rhs = rhs;
+ STRIP_NOPS (rhs);
+ nop_p |= orig_rhs != rhs;
+ }
+ while (orig_rhs != rhs);
- tree orig_rhs = rhs;
- STRIP_NOPS (rhs);
- nop_p = orig_rhs != rhs;
-
if (TREE_CODE (rhs) == COND_EXPR)
{
/* Check the THEN path. */
Index: gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c
===================================================================
--- gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c (revision 268195)
+++ gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c (working copy)
@@ -6,6 +6,8 @@ struct t {
int b;
int *c;
int d[10];
+ int *e[1];
+ _Complex float f;
} __attribute__((packed));
struct t t0;
@@ -17,6 +19,8 @@ struct t *bar();
struct t (*baz())[10];
struct t (*bazz())[10][10];
int *i1;
+int **i2;
+float f0, *f1;
__UINTPTR_TYPE__ u1;
__UINTPTR_TYPE__ baa();
@@ -40,6 +44,14 @@ void foo (void)
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" } */
+ i1 = t10[0].e[0]; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i1 = *&t0.c; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i1 = *&*&t0.c; /* { dg-bogus "may result in an unaligned pointer value" } */
+ f0 = __real__ t0.f; /* { dg-bogus "may result in an unaligned pointer value" } */
+ f0 = __imag__ t0.f; /* { dg-bogus "may result in an unaligned pointer value" } */
+ f0 = *&__real__ t0.f; /* { dg-bogus "may result in an unaligned pointer value" } */
+ f0 = *&__imag__ t0.f; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i1 = (&t0.c, (int*) 0); /* { 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" } */
@@ -52,4 +64,16 @@ void foo (void)
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" } */
+ i1 = (int*) &t10[0].e[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i1 = (int*) t10[0].e; /* { dg-warning "may result in an unaligned pointer value" } */
+ i2 = &t10[0].e[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i2 = t10[0].e; /* { dg-warning "may result in an unaligned pointer value" } */
+ i2 = &*&t0.c; /* { dg-warning "may result in an unaligned pointer value" } */
+ i2 = &*&*&t0.c; /* { dg-warning "may result in an unaligned pointer value" } */
+ f1 = &__real__ t0.f; /* { dg-warning "may result in an unaligned pointer value" } */
+ f1 = &__imag__ t0.f; /* { dg-warning "may result in an unaligned pointer value" } */
+ i1 = (0, (int*) &t0.c); /* { dg-warning "may result in an unaligned pointer value" } */
+ i1 = (int*) (0, &t0.c); /* { dg-warning "may result in an unaligned pointer value" } */
+ i1 = (0, (int*)(0, &t0.c));/* { dg-warning "may result in an unaligned pointer value" } */
+ i1 = (int*)(0, 1, (void*)(2, 3, (int*)(4, 5, &t0.c)));/* { dg-warning "may result in an unaligned pointer value" } */
}
Index: gcc/testsuite/c-c++-common/Waddress-of-packed-member-2.c
===================================================================
--- gcc/testsuite/c-c++-common/Waddress-of-packed-member-2.c (revision 0)
+++ gcc/testsuite/c-c++-common/Waddress-of-packed-member-2.c (working copy)
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-Waddress-of-packed-member" } */
+
+struct r {
+ int a[10];
+ int b[10][10];
+ int ****i4;
+};
+
+struct s {
+ char c;
+ struct r p;
+} __attribute__((packed));
+
+struct t {
+ char c;
+ struct r p __attribute__((packed));
+ struct r u;
+};
+
+struct s s0;
+struct t t0;
+int *i0;
+
+void foo (void)
+{
+ i0 = s0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = t0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = s0.p.b[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = t0.p.b[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &s0.p.a[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &t0.p.a[0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &s0.p.b[0][0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &t0.p.b[0][0]; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = *s0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = *t0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &**s0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &**t0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = **&s0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = **&t0.p.b; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &*s0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = &*t0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = *&s0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = *&t0.p.a; /* { dg-warning "may result in an unaligned pointer value" } */
+ i0 = t0.u.a; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = t0.u.b[0]; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &t0.u.a[0]; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &t0.u.b[0][0]; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = *t0.u.b; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &*t0.u.a; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &**t0.u.b; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = ***s0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = ***t0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = ****&s0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = ****&t0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &****s0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+ i0 = &****t0.p.i4; /* { dg-bogus "may result in an unaligned pointer value" } */
+}