public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Refine -Waddress-of-packed-member once more
@ 2019-01-22 14:10 Bernd Edlinger
  2019-01-22 14:49 ` H.J. Lu
  2019-01-23 15:28 ` Jakub Jelinek
  0 siblings, 2 replies; 8+ messages in thread
From: Bernd Edlinger @ 2019-01-22 14:10 UTC (permalink / raw)
  To: gcc-patches, Richard Biener, Jakub Jelinek, Jason Merrill, H.J. Lu

[-- Attachment #1: Type: text/plain, Size: 813 bytes --]

Hi,

unfortunately there are some more issues with -Waddress-of-packed-member, that show that my previous
patch was not yet complete.

That is a bogus warning, in C and C++ (see addition in test case 1), and a couple of missing warnings
in C++ (test case 2).

The latter warning regressions were accidentally introduced by my previous patch, sorry.

As a side note, the generic tree for an expression like struct.array is folded differently by
C and C++ FE.  While C folds that to &struct.array, C++ folds it to struct.array, without the
ADDR_EXPR.  That might help to explain why this needs to be done in this slightly confusing way.


Fixed the warning regression, and added some more test cases.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-fix-packed-warning-v3.diff --]
[-- Type: text/x-patch; name="patch-fix-packed-warning-v3.diff", Size: 4238 bytes --]

2019-01-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR c/88928
	* 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.

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

	PR c/88928
	* 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 268119)
+++ gcc/c-family/c-warn.c	(working copy)
@@ -2796,6 +2796,10 @@ check_address_or_pointer_of_packed_membe
 	  if (context)
 	    break;
 	}
+      if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
+	rvalue = false;
+      if (rvalue)
+	return NULL_TREE;
       rhs = TREE_OPERAND (rhs, 0);
     }
 
Index: gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c
===================================================================
--- gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c	(revision 268119)
+++ gcc/testsuite/c-c++-common/Waddress-of-packed-member-1.c	(working copy)
@@ -6,6 +6,7 @@ struct t {
   int b;
   int *c;
   int d[10];
+  int *e[1];
 } __attribute__((packed));
 
 struct t t0;
@@ -40,6 +41,7 @@ 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" } */
   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 +54,6 @@ 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" } */
 }
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,38 @@
+/* { dg-do compile } */
+/* { dg-options "-Waddress-of-packed-member" } */
+
+struct r {
+  int a[10];
+  int b[10][10];
+};
+
+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 = 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" } */
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-22 14:10 [PATCH] Refine -Waddress-of-packed-member once more Bernd Edlinger
@ 2019-01-22 14:49 ` H.J. Lu
  2019-01-23 15:28 ` Jakub Jelinek
  1 sibling, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2019-01-22 14:49 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Jakub Jelinek, Jason Merrill

On Tue, Jan 22, 2019 at 6:10 AM Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
>
> Hi,
>
> unfortunately there are some more issues with -Waddress-of-packed-member, that show that my previous
> patch was not yet complete.
>
> That is a bogus warning, in C and C++ (see addition in test case 1), and a couple of missing warnings
> in C++ (test case 2).
>
> The latter warning regressions were accidentally introduced by my previous patch, sorry.
>
> As a side note, the generic tree for an expression like struct.array is folded differently by
> C and C++ FE.  While C folds that to &struct.array, C++ folds it to struct.array, without the
> ADDR_EXPR.  That might help to explain why this needs to be done in this slightly confusing way.
>
>
> Fixed the warning regression, and added some more test cases.

While working on it, I noticed that clang didn't warn for many cases.
Is that still true today?

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-22 14:10 [PATCH] Refine -Waddress-of-packed-member once more Bernd Edlinger
  2019-01-22 14:49 ` H.J. Lu
@ 2019-01-23 15:28 ` Jakub Jelinek
  2019-01-23 17:57   ` Bernd Edlinger
  2019-01-24  7:18   ` Bernd Edlinger
  1 sibling, 2 replies; 8+ messages in thread
From: Jakub Jelinek @ 2019-01-23 15:28 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

On Tue, Jan 22, 2019 at 02:10:38PM +0000, Bernd Edlinger wrote:
> --- gcc/c-family/c-warn.c	(revision 268119)
> +++ gcc/c-family/c-warn.c	(working copy)
> @@ -2796,6 +2796,10 @@ check_address_or_pointer_of_packed_membe
>  	  if (context)
>  	    break;
>  	}
> +      if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
> +	rvalue = false;
> +      if (rvalue)
> +	return NULL_TREE;

That looks like ARRAY_REF specific stuff, isn't it?  We have various other
handled components, does e.g. REALPART_EXPR/IMAGPART_EXPR need that?
What about VIEW_CONVERT_EXPR?  Or is that something you want to do for
all of them?  In any case, there should be testcases with _Complex and
__real__/__imag__, address of that as well as value.

> @@ -52,4 +54,6 @@ 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" } */

Why not also i1 = &t10[0].e[0];
and i1 = t10[0].e; tests?

Unrelated to this patch, I'm worried e.g. about
  if (INDIRECT_REF_P (rhs))
    rhs = TREE_OPERAND (rhs, 0);
   
at the start of the check_address_or_pointer_of_packed_member
function, what if we have:
  i1 = *&t0.c;
Do we want to warn when in the end we don't care if the address is unaligned
or not, this is folded eventually into t0.c.

Plus as I said earlier to H.J., I think
  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;
should be really:
  bool nop_p;
  tree orig_rhs = rhs;
  STRIP_NOPS (rhs);
  nop_p = orig_rhs != rhs;

  while (TREE_CODE (rhs) == COMPOUND_EXPR)
    rhs = TREE_OPERAND (rhs, 1);

  orig_rhs = rhs;
  STRIP_NOPS (rhs);
  nop_p |= orig_rhs != rhs;

or similar, because if there are casts around COMPOUND_EXPR, it doesn't than
look through those COMPOUND_EXPRs, and if e.g. in the COMPOUND_EXPR rhs
there is then COND_EXPR or similar, it should handle that case.

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-23 15:28 ` Jakub Jelinek
@ 2019-01-23 17:57   ` Bernd Edlinger
  2019-01-24  7:18   ` Bernd Edlinger
  1 sibling, 0 replies; 8+ messages in thread
From: Bernd Edlinger @ 2019-01-23 17:57 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

On 1/23/19 4:22 PM, Jakub Jelinek wrote:
> On Tue, Jan 22, 2019 at 02:10:38PM +0000, Bernd Edlinger wrote:
>> --- gcc/c-family/c-warn.c	(revision 268119)
>> +++ gcc/c-family/c-warn.c	(working copy)
>> @@ -2796,6 +2796,10 @@ check_address_or_pointer_of_packed_membe
>>  	  if (context)
>>  	    break;
>>  	}
>> +      if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
>> +	rvalue = false;
>> +      if (rvalue)
>> +	return NULL_TREE;
> 
> That looks like ARRAY_REF specific stuff, isn't it?  We have various other
> handled components, does e.g. REALPART_EXPR/IMAGPART_EXPR need that?
> What about VIEW_CONVERT_EXPR?  Or is that something you want to do for
> all of them?  In any case, there should be testcases with _Complex and
> __real__/__imag__, address of that as well as value.
> 

Okay, my guess it it will work with _Complex, but test cases would be
straight forward, and no reason not to have at least a few.

I have no idea what test case would be needed for VIEW_CONVERT_EXPR.

>> @@ -52,4 +54,6 @@ 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" } */
> 
> Why not also i1 = &t10[0].e[0];
> and i1 = t10[0].e; tests?
> 

I will add that.

> Unrelated to this patch, I'm worried e.g. about
>   if (INDIRECT_REF_P (rhs))
>     rhs = TREE_OPERAND (rhs, 0);
>    
> at the start of the check_address_or_pointer_of_packed_member
> function, what if we have:
>   i1 = *&t0.c;
> Do we want to warn when in the end we don't care if the address is unaligned
> or not, this is folded eventually into t0.c.
> 

Porbably not. I tried your example, and find currently this is inconsistent
between C and C++, C folds *& away, before the warning, and C++ does not and
gets a warning.  I feel like I want to fix that too.

As a side note, your *&t0.c has a VIEW_CONVERT_EXPR in C++ but not in C:

Breakpoint 1, check_address_or_pointer_of_packed_member (type=0x7ffff6eef9d8, 
    rhs=0x7ffff702d760) at ../../gcc-trunk/gcc/c-family/c-warn.c:2727
2727	  bool rvalue = true;
(gdb) call debug(rhs)
*&VIEW_CONVERT_EXPR<struct t>(t0).c

... but it does not affect the warning.


> Plus as I said earlier to H.J., I think
>   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;
> should be really:
>   bool nop_p;
>   tree orig_rhs = rhs;
>   STRIP_NOPS (rhs);
>   nop_p = orig_rhs != rhs;
> 
>   while (TREE_CODE (rhs) == COMPOUND_EXPR)
>     rhs = TREE_OPERAND (rhs, 1);
> 
>   orig_rhs = rhs;
>   STRIP_NOPS (rhs);
>   nop_p |= orig_rhs != rhs;
> 
> or similar, because if there are casts around COMPOUND_EXPR, it doesn't than
> look through those COMPOUND_EXPRs, and if e.g. in the COMPOUND_EXPR rhs
> there is then COND_EXPR or similar, it should handle that case.
> 

Ah, yes.  That was not on my radar.

So this works in C and C++:
i1 = (0, (int*)&t0.c);

But this is again inconsistent between C and C++:
i1 = (int*) (0, &t0.c);

C gets a warning, and C++ no warning.

I agree and see that consistency betwenn C and C++ as important goal.
So, I will try to fix that as well.


Bernd.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-23 15:28 ` Jakub Jelinek
  2019-01-23 17:57   ` Bernd Edlinger
@ 2019-01-24  7:18   ` Bernd Edlinger
  2019-01-24  7:27     ` Jakub Jelinek
  1 sibling, 1 reply; 8+ messages in thread
From: Bernd Edlinger @ 2019-01-24  7:18 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

[-- Attachment #1: Type: text/plain, Size: 2667 bytes --]

On 1/23/19 4:22 PM, Jakub Jelinek wrote:
> On Tue, Jan 22, 2019 at 02:10:38PM +0000, Bernd Edlinger wrote:
>> --- gcc/c-family/c-warn.c	(revision 268119)
>> +++ gcc/c-family/c-warn.c	(working copy)
>> @@ -2796,6 +2796,10 @@ check_address_or_pointer_of_packed_membe
>>  	  if (context)
>>  	    break;
>>  	}
>> +      if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
>> +	rvalue = false;
>> +      if (rvalue)
>> +	return NULL_TREE;
> 
> That looks like ARRAY_REF specific stuff, isn't it?  We have various other
> handled components, does e.g. REALPART_EXPR/IMAGPART_EXPR need that?
> What about VIEW_CONVERT_EXPR?  Or is that something you want to do for
> all of them?  In any case, there should be testcases with _Complex and
> __real__/__imag__, address of that as well as value.
> 
>> @@ -52,4 +54,6 @@ 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" } */
> 
> Why not also i1 = &t10[0].e[0];
> and i1 = t10[0].e; tests?
> 
> Unrelated to this patch, I'm worried e.g. about
>   if (INDIRECT_REF_P (rhs))
>     rhs = TREE_OPERAND (rhs, 0);
>    
> at the start of the check_address_or_pointer_of_packed_member
> function, what if we have:
>   i1 = *&t0.c;
> Do we want to warn when in the end we don't care if the address is unaligned
> or not, this is folded eventually into t0.c.
> 
> Plus as I said earlier to H.J., I think
>   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;
> should be really:
>   bool nop_p;
>   tree orig_rhs = rhs;
>   STRIP_NOPS (rhs);
>   nop_p = orig_rhs != rhs;
> 
>   while (TREE_CODE (rhs) == COMPOUND_EXPR)
>     rhs = TREE_OPERAND (rhs, 1);
> 
>   orig_rhs = rhs;
>   STRIP_NOPS (rhs);
>   nop_p |= orig_rhs != rhs;
> 
> or similar, because if there are casts around COMPOUND_EXPR, it doesn't than
> look through those COMPOUND_EXPRs, and if e.g. in the COMPOUND_EXPR rhs
> there is then COND_EXPR or similar, it should handle that case.
> 

Okay, I updated the patch to address your comments.

Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-fix-packed-warning-v4.diff --]
[-- Type: text/x-patch; name="patch-fix-packed-warning-v4.diff", Size: 6462 bytes --]

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,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;
     }
 
   if (!POINTER_TYPE_P (type))
@@ -2796,6 +2800,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 +2819,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,13 @@ 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" } */
+  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 +63,14 @@ 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" } */
+  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" } */
 }
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,38 @@
+/* { dg-do compile } */
+/* { dg-options "-Waddress-of-packed-member" } */
+
+struct r {
+  int a[10];
+  int b[10][10];
+};
+
+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 = 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" } */
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-24  7:18   ` Bernd Edlinger
@ 2019-01-24  7:27     ` Jakub Jelinek
  2019-01-25  7:11       ` Bernd Edlinger
  0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2019-01-24  7:27 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

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.

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).

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-24  7:27     ` Jakub Jelinek
@ 2019-01-25  7:11       ` Bernd Edlinger
  2019-01-28  7:59         ` Jakub Jelinek
  0 siblings, 1 reply; 8+ messages in thread
From: Bernd Edlinger @ 2019-01-25  7:11 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

[-- Attachment #1: Type: text/plain, Size: 3839 bytes --]

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.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-fix-packed-warning-v5.diff --]
[-- Type: text/x-patch; name="patch-fix-packed-warning-v5.diff", Size: 9190 bytes --]

2019-01-25  Bernd Edlinger  <bernd.edlinger@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.edlinger@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" } */
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Refine -Waddress-of-packed-member once more
  2019-01-25  7:11       ` Bernd Edlinger
@ 2019-01-28  7:59         ` Jakub Jelinek
  0 siblings, 0 replies; 8+ messages in thread
From: Jakub Jelinek @ 2019-01-28  7:59 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Jason Merrill, H.J. Lu

On Fri, Jan 25, 2019 at 06:36:53AM +0000, Bernd Edlinger wrote:
> 2019-01-25  Bernd Edlinger  <bernd.edlinger@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.edlinger@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.

Ok, thanks.

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-01-28  7:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-22 14:10 [PATCH] Refine -Waddress-of-packed-member once more Bernd Edlinger
2019-01-22 14:49 ` H.J. Lu
2019-01-23 15:28 ` Jakub Jelinek
2019-01-23 17:57   ` Bernd Edlinger
2019-01-24  7:18   ` Bernd Edlinger
2019-01-24  7:27     ` Jakub Jelinek
2019-01-25  7:11       ` Bernd Edlinger
2019-01-28  7:59         ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).