Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-13 Thread Martin Sebor via Gcc-patches

On 10/13/20 3:46 AM, Christophe Lyon wrote:

On Tue, 29 Sep 2020 at 00:02, Martin Sebor via Gcc-patches
 wrote:


On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html

(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-bitmap *visited, const vr_values *rvals /* =
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap
*visited,
+const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

  >...

You change some failure cases in compute_objsize to return
success with a maximum range, while others continue to return
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a
constant.
Recently, I have enhanced it to return a range to improve warnings
for
allocated objects.  With that, a failure can be turned into
success by
having the function set the range to that of the largest object.
That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

void f (int n)
{
  char a[n];
  new (a - 1) int ();
}

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have
more churn than to leave the function half-updated.  That can be a
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
tree last_type = TREE_TYPE (last);
if (TREE_CODE (last_type) != ARRAY_TYPE
|| TYPE_SIZE (last_type))
-return size;
+return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

 Returns the size of the object

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-13 Thread Christophe Lyon via Gcc-patches
On Tue, 29 Sep 2020 at 00:02, Martin Sebor via Gcc-patches
 wrote:
>
> On 9/25/20 11:17 PM, Jason Merrill wrote:
> > On 9/22/20 4:05 PM, Martin Sebor wrote:
> >> The rebased and retested patches are attached.
> >>
> >> On 9/21/20 3:17 PM, Martin Sebor wrote:
> >>> Ping:
> >>> https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html
> >>>
> >>> (I'm working on rebasing the patch on top of the latest trunk which
> >>> has changed some of the same code but it'd be helpful to get a go-
> >>> ahead on substance the changes.  I don't expect the rebase to
> >>> require any substantive modifications.)
> >>>
> >>> Martin
> >>>
> >>> On 9/14/20 4:01 PM, Martin Sebor wrote:
>  On 9/4/20 11:14 AM, Jason Merrill wrote:
> > On 9/3/20 2:44 PM, Martin Sebor wrote:
> >> On 9/1/20 1:22 PM, Jason Merrill wrote:
> >>> On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
>  -Wplacement-new handles array indices and pointer offsets the same:
>  by adjusting them by the size of the element.  That's correct for
>  the latter but wrong for the former, causing false positives when
>  the element size is greater than one.
> 
>  In addition, the warning doesn't even attempt to handle arrays of
>  arrays.  I'm not sure if I forgot or if I simply didn't think of
>  it.
> 
>  The attached patch corrects these oversights by replacing most
>  of the -Wplacement-new code with a call to compute_objsize which
>  handles all this correctly (plus more), and is also better tested.
>  But even compute_objsize has bugs: it trips up while converting
>  wide_int to offset_int for some pointer offset ranges.  Since
>  handling the C++ IL required changes in this area the patch also
>  fixes that.
> 
>  For review purposes, the patch affects just the middle end.
>  The C++ diff pretty much just removes code from the front end.
> >>>
> >>> The C++ changes are OK.
> >>
> >> Thank you for looking at the rest as well.
> >>
> >>>
>  -compute_objsize (tree ptr, int ostype, access_ref *pref,
>  -bitmap *visited, const vr_values *rvals /* =
>  NULL */)
>  +compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap
>  *visited,
>  +const vr_values *rvals)
> >>>
> >>> This reformatting seems unnecessary, and I prefer to keep the
> >>> comment about the default argument.
> >>
> >> This overload doesn't take a default argument.  (There was a stray
> >> declaration of a similar function at the top of the file that had
> >> one.  I've removed it.)
> >
> > Ah, true.
> >
>  -  if (!size || TREE_CODE (size) != INTEGER_CST)
>  -   return false;
> >>>  >...
> >>>
> >>> You change some failure cases in compute_objsize to return
> >>> success with a maximum range, while others continue to return
> >>> failure. This needs commentary about the design rationale.
> >>
> >> This is too much for a comment in the code but the background is
> >> this: compute_objsize initially returned the object size as a
> >> constant.
> >> Recently, I have enhanced it to return a range to improve warnings
> >> for
> >> allocated objects.  With that, a failure can be turned into
> >> success by
> >> having the function set the range to that of the largest object.
> >> That
> >> should simplify the function's callers and could even improve
> >> the detection of some invalid accesses.  Once this change is made
> >> it might even be possible to change its return type to void.
> >>
> >> The change that caught your eye is necessary to make the function
> >> a drop-in replacement for the C++ front end code which makes this
> >> same assumption.  Without it, a number of test cases that exercise
> >> VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:
> >>
> >>void f (int n)
> >>{
> >>  char a[n];
> >>  new (a - 1) int ();
> >>}
> >>
> >> Changing any of the other places isn't necessary for existing tests
> >> to pass (and I didn't want to introduce too much churn).  But I do
> >> want to change the rest of the function along the same lines at some
> >> point.
> >
> > Please do change the other places to be consistent; better to have
> > more churn than to leave the function half-updated.  That can be a
> > separate patch if you prefer, but let's do it now rather than later.
> 
>  I've made most of these changes in the other patch (also attached).
>  I'm quite happy with the result but it turned out to be a lot more
>  work than either of us expected, mostly due to the amount of testing.
> 
>  I've left a couple of failing cases in place mainly as

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-12 Thread Martin Sebor via Gcc-patches

On 10/11/20 9:44 PM, Jason Merrill wrote:

On 10/11/20 6:45 PM, Martin Sebor wrote:

On 10/9/20 9:13 AM, Jason Merrill wrote:

On 10/9/20 10:51 AM, Martin Sebor wrote:

On 10/8/20 1:40 PM, Jason Merrill wrote:

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the 
comments with the definition as well as the in-class 
declaration.


Only one access_ref member function is defined 
out-of-line: offset_bounded().  I've adjusted the comment 
and copied it above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded 
in the new patch?


There is a comment in the latest patch.

...
The goal of conditionals is to avoid overwhelming the user 
with

excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked 
and
renamed the get_range function to get_offset_range to do a 
better

job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still 
returns true iff either the range is a single value or one of the 
bounds are unrepresentable in ptrdiff_t.  I'm still unclear how 
this corresponds to "Return true if OFFRNG is bounded to a 
subrange of possible offset values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= 
wi::to_offset (max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= 
wi::to_offset (max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 







Ah, yes, there are two patches in that email; the first introduces 
the broken offset_bounded, and the second one fixes it without 
mentioning that in the ChangeLog.  How about moving the fix to the 
first patch?


Sure, I can do that.  Anything else or is the final version okay
to commit with this adjustment?


OK with that adjustment.


I've done more testing and found a bug in the second patch: adding
an offset in an inverted range to an existing offset range isn't as
simple as adding up the bounds because they mean different things:
like an anti-range, an inverted range is a union of two subranges.
Instead, the upper bound needs to be extended to PTRDIFF_MAX because
that is the maximum being added, and the lower bound either reset to
zero if the absolute value of the maximum being added is less than
it, or incremented by the absolute value otherwise.

For example, given:

   char a[8];
   char *pa = a;
   char *p1 = pa + i;   // i's range is [3, 5]
   char *p2 = p1 + j;   // j's range is [1, -4]

the range of p2's offset isn't [4, 1] but [4, PTRDIFF_MAX] (or more
precisely [4, 8] if we assume it's valid).  But the range of p3's
valid offset in this last pointer

   char *p3 = p2 + k;   // k's range is [5, -4]

is all of [0, PTRDIFF_MAX] (or, more accurately, [0, 8]).

This may seem obvious but it took me a while at first to wrap my head
around.


It makes sense, but doesn't seem obvious; a bit more comment might be nice.


I just now noticed this suggestion, after pushing both patches.
I'll keep it in mind and add something later.




I've tweaked access_ref::add_offset in the patch to handle this
correctly.  The function now ensures that every offset is in
a regular range (and not an inverted one).  That in turn simplifies
access_ref::size_remaining.  Since an inverted range is the same as
an anti-range, there's no reason to exclude the latter anymore(*).
The diff on top of the approved patch is attached.

I've retested this new revision of the patch with Glibc and GDB/
Binutils, (the latter fails due to PR 97360), and the Linux kernel.

Please let me know if you have any questions or concerns with
this change.  If not, I'd like to commit it sometime tomorrow.

Martin

[*] I was curious how often these inverted ranges/anti-ranges come
up in pointer arithmetic to see if handling them is worthwhile.  I
instrumented GCC to print them in get_range() on master where they
are only looked at in calls to built-in functions, and in another
patch I'm working on where they are looked at for every pointer
addition.  They accoun

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-11 Thread Jason Merrill via Gcc-patches

On 10/11/20 6:45 PM, Martin Sebor wrote:

On 10/9/20 9:13 AM, Jason Merrill wrote:

On 10/9/20 10:51 AM, Martin Sebor wrote:

On 10/8/20 1:40 PM, Jason Merrill wrote:

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the 
comments with the definition as well as the in-class 
declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it 
above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded 
in the new patch?


There is a comment in the latest patch.

...
The goal of conditionals is to avoid overwhelming the user 
with

excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a 
better

job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns 
true iff either the range is a single value or one of the bounds 
are unrepresentable in ptrdiff_t.  I'm still unclear how this 
corresponds to "Return true if OFFRNG is bounded to a subrange of 
possible offset values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= 
wi::to_offset (max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= 
wi::to_offset (max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 






Ah, yes, there are two patches in that email; the first introduces 
the broken offset_bounded, and the second one fixes it without 
mentioning that in the ChangeLog.  How about moving the fix to the 
first patch?


Sure, I can do that.  Anything else or is the final version okay
to commit with this adjustment?


OK with that adjustment.


I've done more testing and found a bug in the second patch: adding
an offset in an inverted range to an existing offset range isn't as
simple as adding up the bounds because they mean different things:
like an anti-range, an inverted range is a union of two subranges.
Instead, the upper bound needs to be extended to PTRDIFF_MAX because
that is the maximum being added, and the lower bound either reset to
zero if the absolute value of the maximum being added is less than
it, or incremented by the absolute value otherwise.

For example, given:

   char a[8];
   char *pa = a;
   char *p1 = pa + i;   // i's range is [3, 5]
   char *p2 = p1 + j;   // j's range is [1, -4]

the range of p2's offset isn't [4, 1] but [4, PTRDIFF_MAX] (or more
precisely [4, 8] if we assume it's valid).  But the range of p3's
valid offset in this last pointer

   char *p3 = p2 + k;   // k's range is [5, -4]

is all of [0, PTRDIFF_MAX] (or, more accurately, [0, 8]).

This may seem obvious but it took me a while at first to wrap my head
around.


It makes sense, but doesn't seem obvious; a bit more comment might be nice.


I've tweaked access_ref::add_offset in the patch to handle this
correctly.  The function now ensures that every offset is in
a regular range (and not an inverted one).  That in turn simplifies
access_ref::size_remaining.  Since an inverted range is the same as
an anti-range, there's no reason to exclude the latter anymore(*).
The diff on top of the approved patch is attached.

I've retested this new revision of the patch with Glibc and GDB/
Binutils, (the latter fails due to PR 97360), and the Linux kernel.

Please let me know if you have any questions or concerns with
this change.  If not, I'd like to commit it sometime tomorrow.

Martin

[*] I was curious how often these inverted ranges/anti-ranges come
up in pointer arithmetic to see if handling them is worthwhile.  I
instrumented GCC to print them in get_range() on master where they
are only looked at in calls to built-in functions, and in another
patch I'm working on where they are looked at for every pointer
addition.  They account for 16% to 23% (GCC and Glibc, respectively)
and 22% to 32% (Glibc and GCC).  The detailed results are below.

GCC
   Builtin pointer arithmetic:
     kind  

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-11 Thread Martin Sebor via Gcc-patches

On 10/9/20 9:13 AM, Jason Merrill wrote:

On 10/9/20 10:51 AM, Martin Sebor wrote:

On 10/8/20 1:40 PM, Jason Merrill wrote:

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the 
comments with the definition as well as the in-class 
declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it 
above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded 
in the new patch?


There is a comment in the latest patch.

...

The goal of conditionals is to avoid overwhelming the user with
excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a 
better

job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns 
true iff either the range is a single value or one of the bounds 
are unrepresentable in ptrdiff_t.  I'm still unclear how this 
corresponds to "Return true if OFFRNG is bounded to a subrange of 
possible offset values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= 
wi::to_offset (max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= 
wi::to_offset (max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 





Ah, yes, there are two patches in that email; the first introduces 
the broken offset_bounded, and the second one fixes it without 
mentioning that in the ChangeLog.  How about moving the fix to the 
first patch?


Sure, I can do that.  Anything else or is the final version okay
to commit with this adjustment?


OK with that adjustment.


I've done more testing and found a bug in the second patch: adding
an offset in an inverted range to an existing offset range isn't as
simple as adding up the bounds because they mean different things:
like an anti-range, an inverted range is a union of two subranges.
Instead, the upper bound needs to be extended to PTRDIFF_MAX because
that is the maximum being added, and the lower bound either reset to
zero if the absolute value of the maximum being added is less than
it, or incremented by the absolute value otherwise.

For example, given:

  char a[8];
  char *pa = a;
  char *p1 = pa + i;   // i's range is [3, 5]
  char *p2 = p1 + j;   // j's range is [1, -4]

the range of p2's offset isn't [4, 1] but [4, PTRDIFF_MAX] (or more
precisely [4, 8] if we assume it's valid).  But the range of p3's
valid offset in this last pointer

  char *p3 = p2 + k;   // k's range is [5, -4]

is all of [0, PTRDIFF_MAX] (or, more accurately, [0, 8]).

This may seem obvious but it took me a while at first to wrap my head
around.

I've tweaked access_ref::add_offset in the patch to handle this
correctly.  The function now ensures that every offset is in
a regular range (and not an inverted one).  That in turn simplifies
access_ref::size_remaining.  Since an inverted range is the same as
an anti-range, there's no reason to exclude the latter anymore(*).
The diff on top of the approved patch is attached.

I've retested this new revision of the patch with Glibc and GDB/
Binutils, (the latter fails due to PR 97360), and the Linux kernel.

Please let me know if you have any questions or concerns with
this change.  If not, I'd like to commit it sometime tomorrow.

Martin

[*] I was curious how often these inverted ranges/anti-ranges come
up in pointer arithmetic to see if handling them is worthwhile.  I
instrumented GCC to print them in get_range() on master where they
are only looked at in calls to built-in functions, and in another
patch I'm working on where they are looked at for every pointer
addition.  They account for 16% to 23% (GCC and Glibc, respectively)
and 22% to 32% (Glibc and GCC).  The detailed results are below.

GCC
  Builtin pointer arithmetic:
kind ordinary  inverted
RANGE636 (38%) 150 ( 9%)
ANTI_RANGE28 ( 1%)  99 ( 6%)
VARYING  7

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-09 Thread Jason Merrill via Gcc-patches

On 10/9/20 10:51 AM, Martin Sebor wrote:

On 10/8/20 1:40 PM, Jason Merrill wrote:

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the 
comments with the definition as well as the in-class 
declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded in 
the new patch?


There is a comment in the latest patch.

...

The goal of conditionals is to avoid overwhelming the user with
excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a 
better

job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns 
true iff either the range is a single value or one of the bounds are 
unrepresentable in ptrdiff_t.  I'm still unclear how this 
corresponds to "Return true if OFFRNG is bounded to a subrange of 
possible offset values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= 
wi::to_offset (max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= 
wi::to_offset (max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 




Ah, yes, there are two patches in that email; the first introduces the 
broken offset_bounded, and the second one fixes it without mentioning 
that in the ChangeLog.  How about moving the fix to the first patch?


Sure, I can do that.  Anything else or is the final version okay
to commit with this adjustment?


OK with that adjustment.

Jason



Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-09 Thread Martin Sebor via Gcc-patches

On 10/8/20 1:40 PM, Jason Merrill wrote:

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the comments 
with the definition as well as the in-class declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded in 
the new patch?


There is a comment in the latest patch.

...

The goal of conditionals is to avoid overwhelming the user with
excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a better
job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns 
true iff either the range is a single value or one of the bounds are 
unrepresentable in ptrdiff_t.  I'm still unclear how this corresponds 
to "Return true if OFFRNG is bounded to a subrange of possible offset 
values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= 
wi::to_offset (max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= 
wi::to_offset (max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 



Ah, yes, there are two patches in that email; the first introduces the 
broken offset_bounded, and the second one fixes it without mentioning 
that in the ChangeLog.  How about moving the fix to the first patch?


Sure, I can do that.  Anything else or is the final version okay
to commit with this adjustment?

Martin




Jason





Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-08 Thread Jason Merrill via Gcc-patches

On 10/8/20 3:18 PM, Martin Sebor wrote:

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the comments 
with the definition as well as the in-class declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
    argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded in 
the new patch?


There is a comment in the latest patch.

...

The goal of conditionals is to avoid overwhelming the user with
excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a better
job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns 
true iff either the range is a single value or one of the bounds are 
unrepresentable in ptrdiff_t.  I'm still unclear how this corresponds 
to "Return true if OFFRNG is bounded to a subrange of possible offset 
values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
  bool
  access_ref::offset_bounded () const
  {
-  if (offrng[0] == offrng[1])
-    return false;
-
    tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
    tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= wi::to_offset 
(max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset 
(max);

  }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin 


Ah, yes, there are two patches in that email; the first introduces the 
broken offset_bounded, and the second one fixes it without mentioning 
that in the ChangeLog.  How about moving the fix to the first patch?


Jason



Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-08 Thread Martin Sebor via Gcc-patches

On 10/7/20 3:01 PM, Jason Merrill wrote:

On 10/7/20 4:11 PM, Martin Sebor wrote:

...

For the various member functions, please include the comments 
with the definition as well as the in-class declaration.


Only one access_ref member function is defined out-of-line: 
offset_bounded().  I've adjusted the comment and copied it above

the function definition.


And size_remaining, as quoted above?


I have this in my tree:

/* Return the maximum amount of space remaining and if non-null, set
   argument to the minimum.  */

I'll add it when I commit the patch.



I also don't see a comment above the definition of offset_bounded in the 
new patch?


There is a comment in the latest patch.

...

The goal of conditionals is to avoid overwhelming the user with
excessive numbers that may not be meaningful or even relevant
to the warning.  I've corrected the function body, tweaked and
renamed the get_range function to get_offset_range to do a better
job of extracting ranges from the types of some nonconstant
expressions the front end passes it, and added a new test for
all this.  Attached is the new revision.


offset_bounded looks unchanged in the new patch.  It still returns true 
iff either the range is a single value or one of the bounds are 
unrepresentable in ptrdiff_t.  I'm still unclear how this corresponds to 
"Return true if OFFRNG is bounded to a subrange of possible offset values."


I don't think you're looking at the latest patch.  It has this:

+/* Return true if OFFRNG is bounded to a subrange of offset values
+   valid for the largest possible object.  */
+
 bool
 access_ref::offset_bounded () const
 {
-  if (offrng[0] == offrng[1])
-return false;
-
   tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
   tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
-  return offrng[0] <= wi::to_offset (min) || offrng[1] >= wi::to_offset 
(max);
+  return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset 
(max);

 }

Here's a link to it in the archive:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html
https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200928/9026783a/attachment-0003.bin

Is this version okay to commit?

Martin



It still looks like the middle case is unreachable: if offrng[0] == 
offrng[1], offset_bounded returns false, so we don't get as far as 
testing it for the middle case.


Jason





Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Jason Merrill via Gcc-patches

On 10/7/20 4:11 PM, Martin Sebor wrote:

On 10/7/20 1:28 PM, Jason Merrill wrote:

On 10/7/20 11:19 AM, Martin Sebor wrote:

On 10/7/20 9:07 AM, Jason Merrill wrote:

On 10/7/20 10:42 AM, Martin Sebor wrote:

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html 



(I'm working on rebasing the patch on top of the latest trunk 
which
has changed some of the same code but it'd be helpful to get a 
go-

ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets 
the same:
by adjusting them by the size of the element.  That's 
correct for
the latter but wrong for the former, causing false 
positives when

the element size is greater than one.

In addition, the warning doesn't even attempt to handle 
arrays of
arrays.  I'm not sure if I forgot or if I simply didn't 
think of

it.

The attached patch corrects these oversights by replacing 
most
of the -Wplacement-new code with a call to 
compute_objsize which
handles all this correctly (plus more), and is also 
better tested.
But even compute_objsize has bugs: it trips up while 
converting
wide_int to offset_int for some pointer offset ranges.  
Since
handling the C++ IL required changes in this area the 
patch also

fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front 
end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals 
/* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep 
the comment about the default argument.


This overload doesn't take a default argument.  (There was 
a stray
declaration of a similar function at the top of the file 
that had

one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to 
return failure. This needs commentary about the design 
rationale.


This is too much for a comment in the code but the 
background is
this: compute_objsize initially returned the object size as 
a constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest 
object. That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change 
is made

it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the 
function
a drop-in replacement for the C++ front end code which 
makes this
same assumption.  Without it, a number of test cases that 
exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For 
example:


   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for 
existing tests
to pass (and I didn't want to introduce too much churn). 
But I do
want to change the rest of the function along the same 
lines at some

point.


Please do change the other places to be consistent; better 
to have more churn than to leave the function half-updated. 
That can be a separate patch if you prefer, but let's do it 
now rather than later.


I've made most of these changes in the other patch (also 
attached).
I'm quite happy with the result but it turned out to be a lot 
more
work than either of us expected, mostly due to the amount of 
testing.


I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the 
caller

to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think 
it's necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful 
but

I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return s

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Martin Sebor via Gcc-patches

On 10/7/20 1:28 PM, Jason Merrill wrote:

On 10/7/20 11:19 AM, Martin Sebor wrote:

On 10/7/20 9:07 AM, Jason Merrill wrote:

On 10/7/20 10:42 AM, Martin Sebor wrote:

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html 



(I'm working on rebasing the patch on top of the latest trunk 
which

has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets 
the same:
by adjusting them by the size of the element.  That's 
correct for
the latter but wrong for the former, causing false 
positives when

the element size is greater than one.

In addition, the warning doesn't even attempt to handle 
arrays of
arrays.  I'm not sure if I forgot or if I simply didn't 
think of

it.

The attached patch corrects these oversights by replacing 
most
of the -Wplacement-new code with a call to compute_objsize 
which
handles all this correctly (plus more), and is also better 
tested.
But even compute_objsize has bugs: it trips up while 
converting

wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the 
patch also

fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front 
end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals 
/* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep 
the comment about the default argument.


This overload doesn't take a default argument.  (There was a 
stray
declaration of a similar function at the top of the file 
that had

one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to 
return failure. This needs commentary about the design 
rationale.


This is too much for a comment in the code but the 
background is
this: compute_objsize initially returned the object size as 
a constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest 
object. That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is 
made

it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the 
function
a drop-in replacement for the C++ front end code which makes 
this
same assumption.  Without it, a number of test cases that 
exercise

VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for 
existing tests
to pass (and I didn't want to introduce too much churn).  
But I do
want to change the rest of the function along the same lines 
at some

point.


Please do change the other places to be consistent; better to 
have more churn than to leave the function half-updated.  
That can be a separate patch if you prefer, but let's do it 
now rather than later.


I've made most of these changes in the other patch (also 
attached).
I'm quite happy with the result but it turned out to be a lot 
more
work than either of us expected, mostly due to the amount of 
testing.


I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the 
caller

to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think 
it's necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UN

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Jason Merrill via Gcc-patches

On 10/7/20 11:19 AM, Martin Sebor wrote:

On 10/7/20 9:07 AM, Jason Merrill wrote:

On 10/7/20 10:42 AM, Martin Sebor wrote:

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html 



(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets 
the same:
by adjusting them by the size of the element.  That's 
correct for
the latter but wrong for the former, causing false 
positives when

the element size is greater than one.

In addition, the warning doesn't even attempt to handle 
arrays of
arrays.  I'm not sure if I forgot or if I simply didn't 
think of

it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize 
which
handles all this correctly (plus more), and is also better 
tested.
But even compute_objsize has bugs: it trips up while 
converting

wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch 
also

fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* 
= NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep 
the comment about the default argument.


This overload doesn't take a default argument.  (There was a 
stray
declaration of a similar function at the top of the file that 
had

one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to 
return failure. This needs commentary about the design 
rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest 
object. That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is 
made

it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the 
function
a drop-in replacement for the C++ front end code which makes 
this
same assumption.  Without it, a number of test cases that 
exercise

VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing 
tests
to pass (and I didn't want to introduce too much churn).  But 
I do
want to change the rest of the function along the same lines 
at some

point.


Please do change the other places to be consistent; better to 
have more churn than to leave the function half-updated.  That 
can be a separate patch if you prefer, but let's do it now 
rather than later.


I've made most of these changes in the other patch (also 
attached).

I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of 
testing.


I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think 
it's necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the com

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Martin Sebor via Gcc-patches

On 10/7/20 9:07 AM, Jason Merrill wrote:

On 10/7/20 10:42 AM, Martin Sebor wrote:

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets 
the same:
by adjusting them by the size of the element.  That's 
correct for
the latter but wrong for the former, causing false positives 
when

the element size is greater than one.

In addition, the warning doesn't even attempt to handle 
arrays of
arrays.  I'm not sure if I forgot or if I simply didn't 
think of

it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize 
which
handles all this correctly (plus more), and is also better 
tested.

But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch 
also

fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* 
= NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a 
stray

declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest 
object. That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that 
exercise

VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing 
tests
to pass (and I didn't want to introduce too much churn).  But 
I do
want to change the rest of the function along the same lines 
at some

point.


Please do change the other places to be consistent; better to 
have more churn than to leave the function half-updated.  That 
can be a separate patch if you prefer, but let's do it now 
rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of 
testing.


I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think 
it's necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) 

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Jason Merrill via Gcc-patches

On 10/7/20 10:42 AM, Martin Sebor wrote:

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets the 
same:
by adjusting them by the size of the element.  That's correct 
for
the latter but wrong for the former, causing false positives 
when

the element size is greater than one.

In addition, the warning doesn't even attempt to handle 
arrays of

arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better 
tested.

But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest 
object. That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing 
tests

to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at 
some

point.


Please do change the other places to be consistent; better to 
have more churn than to leave the function half-updated.  That 
can be a separate patch if you prefer, but let's do it now 
rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of 
testing.


I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Martin Sebor via Gcc-patches

On 10/7/20 8:26 AM, Jason Merrill wrote:

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets the 
same:

by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better 
tested.

But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest object. 
That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at 
some

point.


Please do change the other places to be consistent; better to 
have more churn than to leave the function half-updated.  That 
can be a separate patch if you prefer, but let's do it now rather 
than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL 

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-07 Thread Jason Merrill via Gcc-patches

On 9/28/20 6:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets the 
same:

by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest object. 
That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either ha

[PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-10-05 Thread Martin Sebor via Gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-September/555019.html

On 9/28/20 4:01 PM, Martin Sebor wrote:

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:
-Wplacement-new handles array indices and pointer offsets the 
same:

by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, 
bitmap *visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve 
warnings for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest object. 
That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of t

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-28 Thread Martin Sebor via Gcc-patches

On 9/25/20 11:17 PM, Jason Merrill wrote:

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return 
success with a maximum range, while others continue to return 
failure. This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.
Recently, I have enhanced it to return a range to improve warnings 
for
allocated objects.  With that, a failure can be turned into 
success by
having the function set the range to that of the largest object.  
That

should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its s

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-25 Thread Jason Merrill via Gcc-patches

On 9/22/20 4:05 PM, Martin Sebor wrote:

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:
Ping: 
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html


(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = 
NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success 
with a maximum range, while others continue to return failure. 
This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a 
constant.

Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its size, ...


OK, I see it now.


It handles a nu

Re: [PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-22 Thread Martin Sebor via Gcc-patches

The rebased and retested patches are attached.

On 9/21/20 3:17 PM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html

(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = NULL 
*/)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success 
with a maximum range, while others continue to return failure.  
This needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a constant.
Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its size, ...


OK, I see it now.


It handles a number of cases in Wplacement-new-size.C fail

[PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-21 Thread Martin Sebor via Gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553906.html

(I'm working on rebasing the patch on top of the latest trunk which
has changed some of the same code but it'd be helpful to get a go-
ahead on substance the changes.  I don't expect the rebase to
require any substantive modifications.)

Martin

On 9/14/20 4:01 PM, Martin Sebor wrote:

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the 
comment about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success 
with a maximum range, while others continue to return failure.  This 
needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a constant.
Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have 
more churn than to leave the function half-updated.  That can be a 
separate patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its size, ...


OK, I see it now.


It handles a number of cases in Wplacement-new-size.C fail that
construct a larger object in an extern declaration of a template,
like this:

   tem

Re: [PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-14 Thread Martin Sebor via Gcc-patches

On 9/4/20 11:14 AM, Jason Merrill wrote:

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the comment 
about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success 
with a maximum range, while others continue to return failure.  This 
needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a constant.
Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
 char a[n];
 new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have more 
churn than to leave the function half-updated.  That can be a separate 
patch if you prefer, but let's do it now rather than later.


I've made most of these changes in the other patch (also attached).
I'm quite happy with the result but it turned out to be a lot more
work than either of us expected, mostly due to the amount of testing.

I've left a couple of failing cases in place mainly as reminders
to handle them better (which means I also didn't change the caller
to avoid testing for failures).  I've also added TODO notes with
reminders to handle some of the new codes more completely.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its size, ...


OK, I see it now.


It handles a number of cases in Wplacement-new-size.C fail that
construct a larger object in an extern declaration of a template,
like this:

   template  struct S { char c; };
   extern S s;

   void f ()
   {
 new (&s) int ();
   }

I don't know why DECL_SIZE isn't set here (I don't think it can
be anything but equal to TYPE_SIZE, can it?) and other than struct
objects with a flexible array member where this identity doesn't
hold I can't think of others.  Am I missing something?


Good question.  The

Re: [PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-04 Thread Jason Merrill via Gcc-patches

On 9/3/20 2:44 PM, Martin Sebor wrote:

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the comment 
about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)


Ah, true.


-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success 
with a maximum range, while others continue to return failure.  This 
needs commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a constant.
Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

   void f (int n)
   {
     char a[n];
     new (a - 1) int ();
   }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.


Please do change the other places to be consistent; better to have more 
churn than to leave the function half-updated.  That can be a separate 
patch if you prefer, but let's do it now rather than later.



+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's 
necessary to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

    Returns the size of the object designated by DECL considering
    its initializer if it either has one or if it would not affect
    its size, ...


OK, I see it now.


It handles a number of cases in Wplacement-new-size.C fail that
construct a larger object in an extern declaration of a template,
like this:

   template  struct S { char c; };
   extern S s;

   void f ()
   {
     new (&s) int ();
   }

I don't know why DECL_SIZE isn't set here (I don't think it can
be anything but equal to TYPE_SIZE, can it?) and other than struct
objects with a flexible array member where this identity doesn't
hold I can't think of others.  Am I missing something?


Good question.  The attached patch should fix that, so you shouldn't 
need the change to decl_init_size:


commit 95c284379d67efb79a30273236fd6769a12f3031
Author: Jason Merrill 
Date:   Fri Sep 4 12:14:19 2020 -0400

layout

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 31d68745844..f6ca51ad8ba 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -17444,10 +17444,10 @@ complete_vars (tree type)
 	  && (TYPE_MAIN_VARIANT (strip_array_types (type))
 		  == iv->incomplete_type))
 	{
-	  /* Complete the type 

Re: [PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-03 Thread Martin Sebor via Gcc-patches

On 9/1/20 1:22 PM, Jason Merrill wrote:

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


Thank you for looking at the rest as well.




-compute_objsize (tree ptr, int ostype, access_ref *pref,
-    bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap 
*visited,

+    const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the comment 
about the default argument.


This overload doesn't take a default argument.  (There was a stray
declaration of a similar function at the top of the file that had
one.  I've removed it.)




-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

 >...

You change some failure cases in compute_objsize to return success with 
a maximum range, while others continue to return failure.  This needs 
commentary about the design rationale.


This is too much for a comment in the code but the background is
this: compute_objsize initially returned the object size as a constant.
Recently, I have enhanced it to return a range to improve warnings for
allocated objects.  With that, a failure can be turned into success by
having the function set the range to that of the largest object.  That
should simplify the function's callers and could even improve
the detection of some invalid accesses.  Once this change is made
it might even be possible to change its return type to void.

The change that caught your eye is necessary to make the function
a drop-in replacement for the C++ front end code which makes this
same assumption.  Without it, a number of test cases that exercise
VLAs fail in g++.dg/warn/Wplacement-new-size-5.C.  For example:

  void f (int n)
  {
char a[n];
new (a - 1) int ();
  }

Changing any of the other places isn't necessary for existing tests
to pass (and I didn't want to introduce too much churn).  But I do
want to change the rest of the function along the same lines at some
point.

I've tweaked the comment a little bit without going into all this
detail.




+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's necessary 
to initialize it at the declaration.


I find initializing pass-by-pointer local variables helpful but
I don't insist on it.




@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-    return size;
+    return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.


By my reading (and writing) the change is covered by the first
sentence:

   Returns the size of the object designated by DECL considering
   its initializer if it either has one or if it would not affect
   its size, ...

It handles a number of cases in Wplacement-new-size.C fail that
construct a larger object in an extern declaration of a template,
like this:

  template  struct S { char c; };
  extern S s;

  void f ()
  {
new (&s) int ();
  }

I don't know why DECL_SIZE isn't set here (I don't think it can
be anything but equal to TYPE_SIZE, can it?) and other than struct
objects with a flexible array member where this identity doesn't
hold I can't think of others.  Am I missing something?

Attached is an updated patch rebased on top of the current trunk
and retested on x86_64-linux + by building Glibc.

Martin
Correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

Resolves:
PR c++/96511 - Incorrect -Wplacement-new on POINTER_PLUS into an array with 4-byte elements
PR middle-end/96384 - bogus -Wstringop-overflow= storing into multidimensional array with index in range

gcc/ChangeLog:

	PR c++/96511
	PR middle-end/96384
	* builtins.c (get_range): Return full range of type when neither
	value nor its range is available.  Fail for ranges inverted due
	to the signedness of offsets.
	(compute_objsize): Handle more special array members.  Handle
	POINTER_PLUS_EXPR and VIEW_CONVERT_EXPR that come u

Re: [PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-09-01 Thread Jason Merrill via Gcc-patches

On 8/11/20 12:19 PM, Martin Sebor via Gcc-patches wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.


The C++ changes are OK.


-compute_objsize (tree ptr, int ostype, access_ref *pref,
-bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
+const vr_values *rvals)


This reformatting seems unnecessary, and I prefer to keep the comment 
about the default argument.



-  if (!size || TREE_CODE (size) != INTEGER_CST)
-   return false;

>...

You change some failure cases in compute_objsize to return success with 
a maximum range, while others continue to return failure.  This needs 
commentary about the design rationale.



+  special_array_member sam{ };


sam is always set by component_ref_size, so I don't think it's necessary 
to initialize it at the declaration.



@@ -187,7 +187,7 @@ decl_init_size (tree decl, bool min)
   tree last_type = TREE_TYPE (last);
   if (TREE_CODE (last_type) != ARRAY_TYPE
   || TYPE_SIZE (last_type))
-return size;
+return size ? size : TYPE_SIZE_UNIT (type);


This change seems to violate the comment for the function.

Jason



[PING 2][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-08-28 Thread Martin Sebor via Gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551783.html

On 8/19/20 9:00 AM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551783.html

On 8/11/20 10:19 AM, Martin Sebor wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.

Tested on x86_64-linux plus by building the latest Glibc and
confirming no new warnings.

Martin






[PING][PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-08-19 Thread Martin Sebor via Gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551783.html

On 8/11/20 10:19 AM, Martin Sebor wrote:

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.

Tested on x86_64-linux plus by building the latest Glibc and
confirming no new warnings.

Martin




[PATCH] correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

2020-08-11 Thread Martin Sebor via Gcc-patches

-Wplacement-new handles array indices and pointer offsets the same:
by adjusting them by the size of the element.  That's correct for
the latter but wrong for the former, causing false positives when
the element size is greater than one.

In addition, the warning doesn't even attempt to handle arrays of
arrays.  I'm not sure if I forgot or if I simply didn't think of
it.

The attached patch corrects these oversights by replacing most
of the -Wplacement-new code with a call to compute_objsize which
handles all this correctly (plus more), and is also better tested.
But even compute_objsize has bugs: it trips up while converting
wide_int to offset_int for some pointer offset ranges.  Since
handling the C++ IL required changes in this area the patch also
fixes that.

For review purposes, the patch affects just the middle end.
The C++ diff pretty much just removes code from the front end.

Tested on x86_64-linux plus by building the latest Glibc and
confirming no new warnings.

Martin
Correct handling of indices into arrays with elements larger than 1 (PR c++/96511)

Resolves:
PR c++/96511 - Incorrect -Wplacement-new on POINTER_PLUS into an array with 4-byte elements
PR middle-end/96561 - missing warning for buffer overflow with negative offset
PR middle-end/96384 - bogus -Wstringop-overflow= storing into multidimensional array with index in range

gcc/ChangeLog:

	PR c++/96511
	PR middle-end/96384
	* builtins.c (get_range): Return full range of type when neither
	value nor its range is available.  Fail for ranges inverted due
	to the signedness of offsets.
	(compute_objsize): Handle more special array members.  Handle
	POINTER_PLUS_EXPR and VIEW_CONVERT_EXPR that come up in front end
	code.
	(access_ref::offset_bounded): Define new member function.
	* builtins.h (access_ref::eval): New data member.
	(access_ref::offset_bounded): New member function.
	(access_ref::offset_zero): New member function.
	(compute_objsize): Declare a new overload.
	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Use
	enum special_array_member.
	* tree-object-size.c (decl_init_size): Return the size of the structure
	type if the decl size is null.
	* tree.c (component_ref_size): Use special_array_member.
	* tree.h (special_array_member): Define a new type.
	(component_ref_size): Change signature/	

gcc/cp/ChangeLog:

	PR c++/96511
	PR middle-end/96384
	* init.c (warn_placement_new_too_small): Call builtin_objsize instead
	of duplicating what it does.

gcc/testsuite/ChangeLog:

	PR c++/96511
	PR middle-end/96384
	* g++.dg/warn/Wplacement-new-size-1.C: Relax warnings.
	* g++.dg/warn/Wplacement-new-size-2.C: Same.
	* g++.dg/warn/Wplacement-new-size-6.C: Same.
	* g++.dg/warn/Wplacement-new-size-7.C: New test.
	* gcc.dg/Wstringop-overflow-40.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index beb56e06d8a..4f34a99c2f9 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3977,13 +3977,32 @@ static bool
 get_range (tree x, signop sgn, offset_int r[2],
 	   const vr_values *rvals /* = NULL */)
 {
+  tree type = TREE_TYPE (x);
+  if (TREE_CODE (x) != INTEGER_CST
+  && TREE_CODE (x) != SSA_NAME)
+{
+  if (TYPE_UNSIGNED (type))
+	{
+	  if (sgn == SIGNED)
+	type = signed_type_for (type);
+	}
+  else if (sgn == UNSIGNED)
+	type = unsigned_type_for (type);
+
+  r[0] = wi::to_offset (TYPE_MIN_VALUE (type));
+  r[1] = wi::to_offset (TYPE_MAX_VALUE (type));
+  return x;
+}
+
   wide_int wr[2];
   if (!get_range (x, wr, rvals))
 return false;
 
   r[0] = offset_int::from (wr[0], sgn);
   r[1] = offset_int::from (wr[1], sgn);
-  return true;
+  /* Succeed only for valid ranges (pointer offsets are represented
+ as unsigned despite taking on "negative" values).  */
+  return r[0] <= r[1];
 }
 
 /* Helper to compute the size of the object referenced by the PTR
@@ -4001,9 +4020,11 @@ get_range (tree x, signop sgn, offset_int r[2],
to influence code generation or optimization.  */
 
 static bool
-compute_objsize (tree ptr, int ostype, access_ref *pref,
-		 bitmap *visited, const vr_values *rvals /* = NULL */)
+compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
+		 const vr_values *rvals)
 {
+  STRIP_NOPS (ptr);
+
   const bool addr = TREE_CODE (ptr) == ADDR_EXPR;
   if (addr)
 ptr = TREE_OPERAND (ptr, 0);
@@ -4015,12 +4036,15 @@ compute_objsize (tree ptr, int ostype, access_ref *pref,
   if (!addr && POINTER_TYPE_P (TREE_TYPE (ptr)))
 	return false;
 
-  tree size = decl_init_size (ptr, false);
-  if (!size || TREE_CODE (size) != INTEGER_CST)
-	return false;
-
   pref->ref = ptr;
-  pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size);
+  if (tree size = decl_init_size (ptr, false))
+	if (TREE_CODE (size) == INTEGER_CST)
+	  {
+	pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size);
+	return true;
+	  }
+  pref->sizrng[0] = 0;
+  pref->sizrng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
   r