Re: [RFC] how to handle the combination of -fstrict-flex-arrays + -Warray-bounds

2022-10-22 Thread Martin Sebor via Gcc-patches

On 10/21/22 09:29, Qing Zhao wrote:

Hi,

(FAM below refers to Flexible Array Members):

I need inputs on  how to handle the combination of -fstrict-flex-arrays + 
-Warray-bounds.

Our initial goal is to update -Warray-bounds with multiple levels of 
-fstrict-flex-arrays=N
to issue warnings according to the different levels of “N”.
However, after detailed study, I found that this goal was very hard to be 
achieved.

1. -fstrict-flex-arrays and its levels

The new option -fstrict-flex-arrays has 4 levels:

level   trailing arrays
 treated as FAM

   0 [],[0],[1],[n] the default without option
   1 [],[0],[1]
   2 [],[0]
   3 [] the default when option specified 
without value

2. -Warray-bounds and its levels

The option -Warray-bounds currently has 2 levels:

level   trailing arrays
 treated as FAM

   1 [],[0],[1]  the default when option specified 
without value
   2 [] 

i.e,
When -Warray-bounds=1, it treats [],[0],[1] as FAM, the same level as 
-fstrict-flex-arrays=1;
When -Warray-bounds=2, it only treat [] as FAM, the same level as 
-fstrict-flex-arrays=3;

3. How to handle the combination of  -fstrict-flex-arrays and -Warray-bounds?

Question 1:  when -fstrict-flex-arrays does not present, the default is 
-strict-flex-arrays=0,
 which treats [],[0],[1],[n] as FAM, so should we update 
the default behavior
 of -Warray-bounds to treat any trailing array [n] as FAMs?

My immediate answer to Q1 is NO, we shouldn’t, that will be a big regression on 
-Warray-bounds, right?


Yes, it would disable -Warray-bounds in the cases where it warns
for past-the-end accesses to trailing arrays with two or more
elements.  Diagnosing those has historically (i.e., before recent
changes) been a design goal.



Question 2:  when -fstrict-flex-arrays=N1 and -Warray-bounds=N2 present at the 
same time,
  Which one has higher priority? N1 or N2?

-fstrict-flex-arrays=N1 controls how the compiler code generation treats the 
trailing arrays as FAMs, it seems
reasonable to give higher priority to N1,


I tend to agree.  In other words, set N2' = min(N1, N2).


However, then should we completely disable the level of -Warray-bounds
N2 under such situation?

I really don’t know what’s the best way to handle the conflict  between N1 and 
N2.

Can we completely cancel the 2 levels of -Warray-bounds, and always honor the 
level of -fstrict-flex-arrays?

Any comments or suggestion will be helpful.


The recent -fstrict-flex-array changes aside, IIRC, there's only
a subtle distinction between the two -Warray-bounds levels (since
level 1 started warning on a number of instances that only level
2 used to diagnose a few releases ago).  I think that subset of
level 2 could be merged into level 1 without increasing the rate
of false positives.  Then level 2 could be assigned a new set of
potential problems to detect (such as past-the-end accesses to
trailing one-element arrays).

Martin


Re: [GCC13][Patch][V4][PATCH 1/2] Add a new option -fstrict-flex-arrays[=n] and new attribute strict_flex_arrays

2022-09-30 Thread Martin Sebor via Gcc-patches

On 9/28/22 13:17, Qing Zhao wrote:

Hi, Martin,

Thanks for the comments. And sorry for my late reply till now (I just came back 
home from LPC, GNU Cauldron and then a one-week vacation after that…)


On Sep 12, 2022, at 12:42 PM, Martin Sebor  wrote:

On 9/6/22 18:28, Qing Zhao wrote:

Add the following new option -fstrict-flex-arrays[=n] and a corresponding
attribute strict_flex_arrays to GCC:
'-fstrict-flex-arrays'
  Treat the trailing array of a structure as a flexible array member
  in a stricter way.


A minor problem with this phrasing was pointed out in the review
of the Clang option: https://reviews.llvm.org/D126864#inline-1282716
It would be good to avoid it here.

Yes, I agree.


  (I think qualifying the sentence
by adding "for the purposes of accessing the elements of such arrays"
might be one way to do it).


How about:

'-fstrict-flex-arrays’
  Treat the trailing array of a structure as a variable-length array
   in a stricter way.
?


I don't think talking about variable length arrays in this context
would be appropriate (they're a different thing).  The concern in
the review above was that the a in something like

  struct { int n, a[1]; } s;

is treated as a flexible array member only for the purposes of
accessing a's elements, but not also in a sizeof expression, for
instance.  sizeof s.a is 1 regardless of the -fstrict-flex-arrays
argument, but if s.a were considered a flexible array member then
sizeof s.a would a constraint violation.  Similarly, if s.a were
treated as a FAM the definition of s would pedantically speaking
be invalid, and s's size would be equal to sizeof (int) because
GCC accepts the defintion but adds no padding.

One way to avoid implying that might be qualifying the description
with what I suggested above:

  Control when to treat the trailing array of a structure as
  a flexible array member for the purposes of accessing
  the elements of such an array.

But I'm sure there are better ways to put it.

In addition, it should probably also be made clear whether this
stays the same when an object of such a structure is itself
a subobject of another aggregate (array or struct).  E.g.,

  struct A { int n, a[1]; };
  struct A a[2];   // is a.a treated as a FAM?
  struct B { struct A a; } b;  // is b.a.a treated as a FAM?
  struct C { struct A a; int i; } c;   // how about c.a.a?

Finally, and with the caveat that I haven't been very close
attention to the GCC patches so this may not be an issue, but I have
the impression that the decision in Clang is to let -Warray-bounds
trigger (at least somewhat) independently of -fstrict-flex-arrays.
The goal is to make it possible to diagnose misuses without causing
runtime errors.  This has also been the historical GCC behavior that
I think it should be maintained going forward.

Martin






The positive form is equivalent to
  '-fstrict-flex-arrays=3', which is the strictest.  A trailing array
  is treated as a flexible array member only when it is declared as a
  flexible array member per C99 standard onwards.  The negative form
  is equivalent to '-fstrict-flex-arrays=0', which is the least
  strict.  All trailing arrays of structures are treated as flexible
  array members.
'-fstrict-flex-arrays=LEVEL'
  Treat the trailing array of a structure as a flexible array member
  in a stricter way.  The value of LEVEL controls the level of
  strictness.
  The possible values of LEVEL are the same as for the
  'strict_flex_arrays' attribute (*note Variable Attributes::).
  You can control this behavior for a specific trailing array field
  of a structure by using the variable attribute 'strict_flex_arrays'
  attribute (*note Variable Attributes::).
'strict_flex_arrays (LEVEL)'
  The 'strict_flex_arrays' attribute should be attached to the
  trailing array field of a structure.  It specifies the level of
  strictness of treating the trailing array field of a structure as a
  flexible array member.  LEVEL must be an integer betwen 0 to 3.



Since the attribute applies to just a single array declaration it
seems that its name should be strict_flex_array (i.e., singular,
without the trailing 's').


Will make the change as you suggested.

Thanks.

Qing


Martin


  LEVEL=0 is the least strict level, all trailing arrays of
  structures are treated as flexible array members.  LEVEL=3 is the
  strictest level, only when the trailing array is declared as a
  flexible array member per C99 standard onwards ('[]'), it is
  treated as a flexible array member.
  There are two more levels in between 0 and 3, which are provided to
  support older codes that use GCC zero-length array extension
  ('[0]') or one-size array as flexible array member ('[1]'): When
  LEVEL is 1, the trailing array is treated as a flexible array
  member when it is declared as either '[]', '[0]', or '[1]'; When
  

Re: [GCC13][Patch][V4][PATCH 1/2] Add a new option -fstrict-flex-arrays[=n] and new attribute strict_flex_arrays

2022-09-12 Thread Martin Sebor via Gcc-patches

On 9/6/22 18:28, Qing Zhao wrote:

Add the following new option -fstrict-flex-arrays[=n] and a corresponding
attribute strict_flex_arrays to GCC:

'-fstrict-flex-arrays'
  Treat the trailing array of a structure as a flexible array member
  in a stricter way.


A minor problem with this phrasing was pointed out in the review
of the Clang option: https://reviews.llvm.org/D126864#inline-1282716
It would be good to avoid it here.  (I think qualifying the sentence
by adding "for the purposes of accessing the elements of such arrays"
might be one way to do it).


 The positive form is equivalent to
  '-fstrict-flex-arrays=3', which is the strictest.  A trailing array
  is treated as a flexible array member only when it is declared as a
  flexible array member per C99 standard onwards.  The negative form
  is equivalent to '-fstrict-flex-arrays=0', which is the least
  strict.  All trailing arrays of structures are treated as flexible
  array members.

'-fstrict-flex-arrays=LEVEL'
  Treat the trailing array of a structure as a flexible array member
  in a stricter way.  The value of LEVEL controls the level of
  strictness.

  The possible values of LEVEL are the same as for the
  'strict_flex_arrays' attribute (*note Variable Attributes::).

  You can control this behavior for a specific trailing array field
  of a structure by using the variable attribute 'strict_flex_arrays'
  attribute (*note Variable Attributes::).

'strict_flex_arrays (LEVEL)'
  The 'strict_flex_arrays' attribute should be attached to the
  trailing array field of a structure.  It specifies the level of
  strictness of treating the trailing array field of a structure as a
  flexible array member.  LEVEL must be an integer betwen 0 to 3.



Since the attribute applies to just a single array declaration it
seems that its name should be strict_flex_array (i.e., singular,
without the trailing 's').

Martin



  LEVEL=0 is the least strict level, all trailing arrays of
  structures are treated as flexible array members.  LEVEL=3 is the
  strictest level, only when the trailing array is declared as a
  flexible array member per C99 standard onwards ('[]'), it is
  treated as a flexible array member.

  There are two more levels in between 0 and 3, which are provided to
  support older codes that use GCC zero-length array extension
  ('[0]') or one-size array as flexible array member ('[1]'): When
  LEVEL is 1, the trailing array is treated as a flexible array
  member when it is declared as either '[]', '[0]', or '[1]'; When
  LEVEL is 2, the trailing array is treated as a flexible array
  member when it is declared as either '[]', or '[0]'.

  This attribute can be used with or without the
  '-fstrict-flex-arrays'.  When both the attribute and the option
  present at the same time, the level of the strictness for the
  specific trailing array field is determined by the attribute.

gcc/c-family/ChangeLog:

* c-attribs.cc (handle_strict_flex_arrays_attribute): New function.
(c_common_attribute_table): New item for strict_flex_arrays.
* c.opt: (fstrict-flex-arrays): New option.
(fstrict-flex-arrays=): New option.

gcc/c/ChangeLog:

* c-decl.cc (flexible_array_member_type_p): New function.
(one_element_array_type_p): Likewise.
(zero_length_array_type_p): Likewise.
(add_flexible_array_elts_to_size): Call new utility
routine flexible_array_member_type_p.
(is_flexible_array_member_p): New function.
(finish_struct): Set the new DECL_NOT_FLEXARRAY flag.

gcc/cp/ChangeLog:

* module.cc (trees_out::core_bools): Stream out new bit
decl_not_flexarray.
(trees_in::core_bools): Stream in new bit decl_not_flexarray.

gcc/ChangeLog:

* doc/extend.texi: Document strict_flex_arrays attribute.
* doc/invoke.texi: Document -fstrict-flex-arrays[=n] option.
* print-tree.cc (print_node): Print new bit decl_not_flexarray.
* tree-core.h (struct tree_decl_common): New bit field
decl_not_flexarray.
* tree-streamer-in.cc (unpack_ts_decl_common_value_fields): Stream
in new bit decl_not_flexarray.
* tree-streamer-out.cc (pack_ts_decl_common_value_fields): Stream
out new bit decl_not_flexarray.
* tree.cc (array_at_struct_end_p): Update it with the new bit field
decl_not_flexarray.
* tree.h (DECL_NOT_FLEXARRAY): New flag.

gcc/testsuite/ChangeLog:

* g++.dg/strict-flex-array-1.C: New test.
* gcc.dg/strict-flex-array-1.c: New test.
---
  gcc/c-family/c-attribs.cc  |  47 
  gcc/c-family/c.opt |   7 ++
  gcc/c/c-decl.cc| 130 +++--
  gcc/cp/module.cc   |   2 +
  gcc/doc/extend.texi| 

Re: [GCC 13][PATCH] PR101836: Add a new option -fstrict-flex-array[=n] and use it in __builtin_object_size

2022-07-01 Thread Martin Sebor via Gcc-patches

On 7/1/22 08:01, Qing Zhao wrote:




On Jul 1, 2022, at 8:59 AM, Jakub Jelinek  wrote:

On Fri, Jul 01, 2022 at 12:55:08PM +, Qing Zhao wrote:

If so, comparing to the current implemenation to have all the checking in 
middle-end, what’s the
major benefit of moving part of the checking into FE, and leaving the other 
part in middle-end?


The point is recording early what FIELD_DECLs could be vs. can't possibly be
treated like flexible array members and just use that flag in the decisions
in the current routines in addition to what it is doing.


Okay.

Based on the discussion so far, I will do the following:

1. Add a new flag “DECL_NOT_FLEXARRAY” to FIELD_DECL;
2. In C/C++ FE, set the new flag “DECL_NOT_FLEXARRAY” for a FIELD_DECL based on 
[0], [1],
 [] and the option -fstrict-flex-array, and whether it’s the last field of 
the DECL_CONTEXT.
3. In Middle end,  Add a new utility routine is_flexible_array_member_p, which 
bases on
 DECL_NOT_FLEXARRAY + array_at_struct_end_p to decide whether the array
 reference is a real flexible array member reference.


Middle end currently is quite mess, array_at_struct_end_p, component_ref_size, 
and all the phases that
use these routines need to be updated, + new testing cases for each of the 
phases.


So, I still plan to separate the patch set into 2 parts:

   Part A:the above 1 + 2 + 3,  and use these new utilities in 
tree-object-size.cc to resolve PR101836 first.
  Then kernel can use __FORTIFY_SOURCE correctly;

   Part B:update all other phases with the new utilities + new testing 
cases + resolving regressions.

Let me know if you have any comment and suggestion.


It might be worth considering whether it should be possible to control
the "flexible array" property separately for each trailing array member
via either a #pragma or an attribute in headers that can't change
the struct layout but that need to be usable in programs compiled with
stricter -fstrict-flex-array=N settings.

Martin



Thanks a lot for all your help.

Qing



Jakub







Re: [GCC 13][PATCH] PR101836: Add a new option -fstrict-flex-array[=n] and use it in __builtin_object_size

2022-06-29 Thread Martin Sebor via Gcc-patches

On 6/28/22 13:01, Qing Zhao wrote:




On Jun 28, 2022, at 2:49 PM, Jakub Jelinek  wrote:

On Tue, Jun 28, 2022 at 06:29:01PM +, Qing Zhao wrote:




On Jun 28, 2022, at 2:22 PM, Jakub Jelinek  wrote:

On Tue, Jun 28, 2022 at 06:15:58PM +, Qing Zhao wrote:

Because the flag just tells whether some array shouldn't be treated as (poor 
man's)
flexible array member.  We still need to find out if some FIELD_DECL is to
be treated like a flexible array member, which is a minority of
COMPONENT_REFs.
struct S { int a; char b[0]; int c; } s;
struct T { int d; char e[]; };
struct U { int f; struct T g; int h; } u;
Neither s.b nor u.g.e is to be treated like flexible array member,
no matter what -fstrict-flex-array= option is used.


Then, to resolve this issue, we might need a opposite  flag DECL_IS_FLEXARRAY 
in FIELD_DECL?

The default is FALSE for all FIELD_DECL.


Doesn't matter whether it is positive or negative, you still need to analyze
it.  See the above example.  If you have struct T t; and test t.e, then it
is flexarray.  But u.g.e is not, even when the COMPONENT_REF refers to the
same FIELD_DECL.  In the t.e case e is the very last field, in the latter
case u.g.e is the last field in struct T, but struct U has the h field after


So, do you mean that the current FE analysis will not be able to decide whether 
a specific array field is at the end of the enclosing structure?
Only the middle end can decide this ?


Well, anything that analyzes it, can be in the FE or middle-end, but there
is no place to store it for later.


Then I am a little confused:

If the FE can decide wether an array field is at the end of the enclosing 
structure,  then combined with whether it’s a [0], [1] or [], and which level 
of -fstrict-flex-array,

The FE should be able to decide whether this array field is a flexible array 
member or not, then set the flag DECL_IS_FLEXARRAY (or DECL_NOT_FLEXARRAY).

The new flag is the place to store such info, right?
Do I miss anything here?


I think the problem is that there is just one FIELD_DECL for member
M of a given type T but there can be more than one instance of that
member, one in each struct that has a subobject of T as its own
member.  Whether M is or isn't a (valid) flexible array member
varies between the two instances.

Martin


Re: [GCC 13][PATCH] PR101836: Add a new option -fstrict-flex-array[=n] and use it in __builtin_object_size

2022-06-28 Thread Martin Sebor via Gcc-patches

On 6/28/22 01:16, Richard Biener wrote:

On Mon, Jun 27, 2022 at 4:20 PM Qing Zhao via Gcc-patches
 wrote:


Hi,

Per our discussion in the bug report, I came up with the following patch:

===

PR101836: Add a new option -fstrict-flex-array[=n]

Add the new option and use it in __builtin_object_size.

Treat the trailing array of a structure as a flexible array member in a
stricter way.  The value of 'n' controls the level of strictness.
'n'=0 is the least strict, all trailing arrays of structures are treated
as flexible array members; This is the default behavior of GCC without specify
this option.
'n'=3 is the strictest, only when the trailing array is declared as a
flexible array member per C99 standard onwards ([]), it is treated as a
flexible array member;
There are two more levels in between 0 and 3, which are provided to support
older codes that use GCC zero-length array extension ([0]), or one-size array as
flexible array member ([1]):
When 'n' is 1, the trailing array is treated as a flexible array member
when it is declared as either [], [0], or [1];
When 'n' is 2, the trailing array is treated as a flexible array member
when it is declared as either [], or [0].

There are other places in GCC that conservatively treat flexible array members.
A follow-up patch will make -ftrict-flex-array option to control all these
places consistently.

Bootstrapped and regression tested on both X86 and aarch64, no issues.

Any comment and suggestion?


Since this aims at the C or C++ frontends but the middle-end eventually consumes
this it would be much nicer to encode this in the types themselves.
Since the least
strict reading is the default right now it would be a flag (on the
FIELD_DECL I suppose)
like DECL_NOT_FLEXARRAY or DECL_FIXED_SIZE?  Alternatively the flag could
also be on the record type enclosing the trailing array member (but
type sharing might
make this more difficult in the end).

There's also array_at_struct_end_p which is supposed to be the main
query interface
for this (but it seems people sneaked in more variants with eventually
different semantics ... :/)


The conservative array_at_struct_end_p has historically been used
for codegen.  component_ref_size was added as a separate function
with more flexible (including stricter) semantics to implement
warnings without running the risk of interfering with codegen.

Martin



Richard.




Okay for commit to Gcc13?

thanks.

Qing

===

gcc/

PR tree-optimization/101836
* common.opt (fstrict-flex-array, fstrict-flex-array=): New options.
* doc/invoke.texi (-fstrict-flex-array, -fstrict-flex-array=): Document.
* tree-object-size.cc (addr_object_size): Call is_flexible_array_p to
check whether an array is a flexible array.
* tree.cc (special_array_member_type): New routine.
(is_flexible_array_p): New routine.
(component_ref_size): Call special_array_member_type to decide the
type of special array member.
* tree.h (enum struct special_array_member): Add is_vla, trail_flex.
(special_array_member_type): New prototype.
(is_flexible_array_p): New prototype.

gcc/testsuite/

PR tree-optimization/101836
* gcc.dg/pr101836.c: New test.
* gcc.dg/pr101836_1.c: New test.
* gcc.dg/pr101836_2.c: New test.
* gcc.dg/pr101836_3.c: New test.
* gcc.dg/pr101836_4.c: New test.
* gcc.dg/pr101836_5.c: New test.


The complete patch is:





Re: [PATCH] Do not erase warning data in gimple_set_location

2022-06-13 Thread Martin Sebor via Gcc-patches

On 6/13/22 05:15, Richard Biener wrote:

On Fri, Jun 10, 2022 at 12:58 PM Eric Botcazou via Gcc-patches
 wrote:


Hi,

gimple_set_location is mostly invoked on newly built GIMPLE statements, so
their location is UNKNOWN_LOCATION and setting it will clobber the warning
data of the passed location, if any.


Hmm, I think instead of special-casing UNKNOWN_LOCATION
what gimple_set_location should probably do is either not copy
warnings at all or union them.  Btw, gimple_set_location also
removes a previously set BLOCK (but gimple_set_block preserves
the location locus and diagnostic override).

So I'd be tempted to axe the copy_warning () completely here.  Martin,
there were
probably cases that warranted it - do you remember anything specific here?


Nothing specific, just that the assumption behind the warning group
design was that a location must exist in order to suppress a warning
(a location is one of the first things that's set early on by the FE
and it makes little sense to issue a warning without one).

There was and in all likelihood still is code sets TREE_NO_WARNING
or gimple_no_warning on new trees/statements before setting their
location.  That interferes with the design when the new tree or
statement is meant to be a replacement of another.  I fixed a few
cases like that to set the location first but didn't have a way
of finding all such instances.  My expectation was to over time
change GCC to make sure a location would always be set before
the no-warning bit, and asserting that on every call to these
routines.  Adding tests like in the patch below goes in the opposite
direction and effectively papers over the problem.  I can't think
of a way to make the suppression work completely reliably without
ensuring that a location is always set before suppressing
a warning.

Martin



Thanks,
Richard.


Tested on x86-64/Linux, OK for mainline and 12 branch?


2022-06-10  Eric Botcazou  

 * gimple.h (gimple_set_location): Do not copy warning data from
 the previous location when it is UNKNOWN_LOCATION.


2022-06-10  Eric Botcazou  

testsuite/
 * c-c++-common/nonnull-1.c: Remove XFAIL for C++.

--
Eric Botcazou






Re: [PATCH] tree-optimization/105726 - adjust array bound heuristic

2022-05-25 Thread Martin Sebor via Gcc-patches

On 5/25/22 11:19, Martin Sebor wrote:

On 5/25/22 04:49, Richard Biener wrote:

...

[*] For example, no warning is issued for the following overread:


Scratch that, there is no overread with strncpy.  When there is like
with memcpy, it is diagnosed as it should be.



struct A a;

void g (char *d)
{
   struct B *q = 
   __builtin_strncpy (d, q->a, 123);   // { dg-warning 
"-Wstringop-overread" "pr???" { xfail *-*-* } }

}




Re: [PATCH] tree-optimization/105726 - adjust array bound heuristic

2022-05-25 Thread Martin Sebor via Gcc-patches

On 5/25/22 04:49, Richard Biener wrote:

There's heuristic to detect ptr[1].a[...] out of bound accesses
reasoning that if ptr points to an array of aggregates a trailing
incomplete array has to have size zero.  The following more
thoroughly constrains the cases this applies to avoid false
positive diagnostics.


The code in the area below does look like it's missing some logic
(like what you're adding).  The whole -Wrestrict pass is messy and
could use some cleanup (sorry).  The -Warray-bounds logic should
probably be removed (-Wstringop-overflow should now catch most of
the valid instances it issues, and if it doesn't(*) it should be
enhanced).  The pass could even be moved into the access warning
pass and probably also simplified quite a bit.

For what it's worth, a simple C test case for the same bug is:

struct A
{
  int i;
  struct B { char a[1]; } b;
};

void f (char *d, struct A *p)
{
  struct B *q = >b;
  __builtin_strncpy (d, q->a, 1);   // { dg-bogus "-Warray-bounds" }
}

Martin

[*] For example, no warning is issued for the following overread:

struct A a;

void g (char *d)
{
  struct B *q = 
  __builtin_strncpy (d, q->a, 123);   // { dg-warning 
"-Wstringop-overread" "pr???" { xfail *-*-* } }

}



Bootstrapped and tested on x86_64-unknown-linux-gnu.

OK?

Thanks,
Richard.

2022-05-25  Richard Biener  

PR tree-optimization/105726
* gimple-ssa-warn-restrict.cc (builtin_memref::set_base_and_offset):
Constrain array-of-flexarray case more.

* g++.dg/warn/Warray-bounds-27.C: New testcase.
---
  gcc/gimple-ssa-warn-restrict.cc  | 22 
  gcc/testsuite/g++.dg/warn/Warray-bounds-27.C | 16 ++
  2 files changed, 29 insertions(+), 9 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Warray-bounds-27.C

diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
index b678e806da3..734cdd7f5b4 100644
--- a/gcc/gimple-ssa-warn-restrict.cc
+++ b/gcc/gimple-ssa-warn-restrict.cc
@@ -525,7 +525,6 @@ builtin_memref::set_base_and_offset (tree expr)
  {
tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 
1));
extend_offset_range (memrefoff);
-  base = TREE_OPERAND (base, 0);
  
if (refoff != HOST_WIDE_INT_MIN

  && TREE_CODE (expr) == COMPONENT_REF)
@@ -538,14 +537,19 @@ builtin_memref::set_base_and_offset (tree expr)
 REFOFF is set to s[1].b - (char*)s.  */
  offset_int off = tree_to_shwi (memrefoff);
  refoff += off;
-   }
-
-  if (!integer_zerop (memrefoff))
-   /* A non-zero offset into an array of struct with flexible array
-  members implies that the array is empty because there is no
-  way to initialize such a member when it belongs to an array.
-  This must be some sort of a bug.  */
-   refsize = 0;
+
+ if (!integer_zerop (memrefoff)
+ && !COMPLETE_TYPE_P (TREE_TYPE (expr))
+ && multiple_of_p (sizetype, memrefoff,
+   TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
+   /* A non-zero offset into an array of struct with flexible array
+  members implies that the array is empty because there is no
+  way to initialize such a member when it belongs to an array.
+  This must be some sort of a bug.  */
+   refsize = 0;
+   }
+
+  base = TREE_OPERAND (base, 0);
  }
  
if (TREE_CODE (ref) == COMPONENT_REF)

diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-27.C 
b/gcc/testsuite/g++.dg/warn/Warray-bounds-27.C
new file mode 100644
index 000..06ce089c4b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-27.C
@@ -0,0 +1,16 @@
+// PR105726
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-options "-O2 -Warray-bounds" }
+
+#include 
+#include 
+
+struct X {
+char pad[4];
+std::array mField;
+};
+
+void encode(char* aBuffer, const X& aMessage) {
+strncpy(aBuffer, aMessage.mField.data(), 1); // { dg-bogus "bounds" }
+}




Re: [PATCH] middle-end/105604 - snprintf dianostics and non-constant sizes/offsets

2022-05-23 Thread Martin Sebor via Gcc-patches

On 5/19/22 05:39, Richard Biener wrote:

On Wed, 18 May 2022, Martin Sebor wrote:


On 5/18/22 00:26, Richard Biener wrote:

On Tue, 17 May 2022, Martin Sebor wrote:


On 5/16/22 03:16, Richard Biener wrote:

The following tries to correct get_origin_and_offset_r not handling
non-constant sizes of array elements in ARRAY_REFs and non-constant
offsets of COMPONENT_REFs.  It isn't exactly clear how such failures
should be treated in this API and existing handling isn't consistent
here either.  The following applies two different variants, treating
non-constant array sizes like non-constant array indices and
treating non-constant offsets of COMPONENT_REFs by terminating
the recursion (not sure what that means to the callers).

Basically the code failed to use component_ref_field_offset and
array_ref_element_size and instead relies on inappropriate
helpers (that shouldn't exist in the first place ...).  The code
is also not safe-guarded against overflows in the final offset/size
computations but I'm not trying to rectify that.

Martin - can you comment on how the API should handle such
situations?


It looks like the -Wrestrict warning here ignores offsets equal to
HOST_WIDE_INT_MIN so presumably setting dst_offset (via *fldoff) to
that should avoid it.  Or maybe to HWI_MAX as it does for variable
offsets.


Can you suggest wording for the function comment as to how it handles
the case when offset or size cannot be determined exactly?   The
comment currently only suggests that the caller possibly cannot
trust fldsize or off when the function returns NULL but the actual
implementation differs from that.







It also looks like the function only handles constant offsets and
sizes, and I have a vague recollection of enhancing it to work with
ranges.  That should avoid the overflow problem too.


So the correct thing is to return NULL?


No, I don't think so.  The recursive get_origin_and_offset_r() assumes
its own invocations never return null (the one place it does that should
probably be moved to the nonrecursive caller).



Is the patch OK as-is?


It's an improvement but it's not complete as the following also ICEs
(albeit somewhere else):

void* f (void);

void g (int n)
{
   struct {
 char a[n], b[];
   } *p = f ();

   __builtin_sprintf (p->b, "%s", p->a);
}

With the ICE fixed the warning triggers.  That's not ideal but it's
unavoidable given the IR (I believe I mentioned this caveat some time
back).  This is the same as for:

   struct {
 char a[8], b[8];
   } *p = f ();

   __builtin_sprintf (>b[n], "%s", p->a);

because the IR looks more or less the same for >a[n] as it is for
>b[n].


As said, I'm not sure how the caller interprets
the result and how it can distinguish the exact vs. non-exact cases
or what a "conservative" inexact answer would be.


The warning triggers in both the certain cases and the inexact
ones like the one above when an overlap cannot be ruled out.  To
differentiate the two it's phrased as "may overlap".  The handling
is in maybe_warn_overlap().



Please help properly documenting this API.


I can spend some time in the next few days to page it all in, see
if I can clean it up a bit in addition to fixing the ICEs and
improve the comment.  Let me know if you have a different
preference.


That works for me - thanks for taking it from here.

Attached is a slightly enhanced patch that fixes both of the ICEs,
improves the comments, and adds more tests.  I tested it on x86_64.
Let me know if there's something else you'd like me to do here.

MartinPR middle-end/105604 - ICE: in tree_to_shwi with vla in struct and sprintf

gcc/ChangeLog:

	PR middle-end/105604
	* gimple-ssa-sprintf.cc (set_aggregate_size_and_offset): Add comments.
	(get_origin_and_offset_r): Remove null handling.  Handle variable array
	sizes.
	(get_origin_and_offset): Handle null argument here.  Simplify.
	(alias_offset):
	* pointer-query.cc (field_at_offset): Update comment.

gcc/testsuite/ChangeLog:

	PR middle-end/105604
	* gcc.dg/Wrestrict-24.c: New test.
	* gcc.dg/Wrestrict-25.c: New test.
	* gcc.dg/Wrestrict-26.c: New test.

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index 8202129667e..6bd27302213 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -2232,8 +2232,9 @@ format_character (const directive , tree arg, pointer_query _qry)
 }
 
 /* If TYPE is an array or struct or union, increment *FLDOFF by the starting
-   offset of the member that *OFF point into and set *FLDSIZE to its size
-   in bytes and decrement *OFF by the same.  Otherwise do nothing.  */
+   offset of the member that *OFF points into if one can be determined and
+   set *FLDSIZE to its size in bytes and decrement *OFF by the same.
+   Otherwise do nothing.  */
 
 static void
 set_aggregate_size_and_offset (tree type, HOST_WIDE_INT *fldoff,
@@ -2249,9 +2250,9 @@ set_aggregate_size_and_offset (tree type, HOST_WIDE_INT *fldoff,
   if (array_elt_at_offset (type, *off, , ))
 	{
 	  

Re: [PATCH] middle-end/105604 - snprintf dianostics and non-constant sizes/offsets

2022-05-18 Thread Martin Sebor via Gcc-patches

On 5/18/22 00:26, Richard Biener wrote:

On Tue, 17 May 2022, Martin Sebor wrote:


On 5/16/22 03:16, Richard Biener wrote:

The following tries to correct get_origin_and_offset_r not handling
non-constant sizes of array elements in ARRAY_REFs and non-constant
offsets of COMPONENT_REFs.  It isn't exactly clear how such failures
should be treated in this API and existing handling isn't consistent
here either.  The following applies two different variants, treating
non-constant array sizes like non-constant array indices and
treating non-constant offsets of COMPONENT_REFs by terminating
the recursion (not sure what that means to the callers).

Basically the code failed to use component_ref_field_offset and
array_ref_element_size and instead relies on inappropriate
helpers (that shouldn't exist in the first place ...).  The code
is also not safe-guarded against overflows in the final offset/size
computations but I'm not trying to rectify that.

Martin - can you comment on how the API should handle such
situations?


It looks like the -Wrestrict warning here ignores offsets equal to
HOST_WIDE_INT_MIN so presumably setting dst_offset (via *fldoff) to
that should avoid it.  Or maybe to HWI_MAX as it does for variable
offsets.


Can you suggest wording for the function comment as to how it handles
the case when offset or size cannot be determined exactly?   The
comment currently only suggests that the caller possibly cannot
trust fldsize or off when the function returns NULL but the actual
implementation differs from that.







It also looks like the function only handles constant offsets and
sizes, and I have a vague recollection of enhancing it to work with
ranges.  That should avoid the overflow problem too.


So the correct thing is to return NULL?


No, I don't think so.  The recursive get_origin_and_offset_r() assumes
its own invocations never return null (the one place it does that should
probably be moved to the nonrecursive caller).



Is the patch OK as-is?


It's an improvement but it's not complete as the following also ICEs
(albeit somewhere else):

void* f (void);

void g (int n)
{
  struct {
char a[n], b[];
  } *p = f ();

  __builtin_sprintf (p->b, "%s", p->a);
}

With the ICE fixed the warning triggers.  That's not ideal but it's
unavoidable given the IR (I believe I mentioned this caveat some time
back).  This is the same as for:

  struct {
char a[8], b[8];
  } *p = f ();

  __builtin_sprintf (>b[n], "%s", p->a);

because the IR looks more or less the same for >a[n] as it is for
>b[n].


As said, I'm not sure how the caller interprets
the result and how it can distinguish the exact vs. non-exact cases
or what a "conservative" inexact answer would be.


The warning triggers in both the certain cases and the inexact
ones like the one above when an overlap cannot be ruled out.  To
differentiate the two it's phrased as "may overlap".  The handling
is in maybe_warn_overlap().



Please help properly documenting this API.


I can spend some time in the next few days to page it all in, see
if I can clean it up a bit in addition to fixing the ICEs and
improve the comment.  Let me know if you have a different
preference.

Martin



Thanks,
Richard.


Martin



Bootstrapped and tested on x86_64-unknown-linux-gnu.

OK for trunk and branches?

Thanks,
Richard.

2022-05-16  Richard Biener  

  PR middle-end/105604
  * gimple-ssa-sprintf.cc (get_origin_and_offset_r):
  Handle non-constant ARRAY_REF element size and non-constant
  COMPONENT_REF field offset.

* gcc.dg/torture/pr105604.c: New testcase.
---
   gcc/gimple-ssa-sprintf.cc   | 14 +++---
   gcc/testsuite/gcc.dg/torture/pr105604.c | 24 
   2 files changed, 35 insertions(+), 3 deletions(-)
   create mode 100644 gcc/testsuite/gcc.dg/torture/pr105604.c

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index c93f12f90b5..14e215ce69c 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -2312,14 +2312,16 @@ get_origin_and_offset_r (tree x, HOST_WIDE_INT
*fldoff, HOST_WIDE_INT *fldsize,
HOST_WIDE_INT idx = (tree_fits_uhwi_p (offset)
   ? tree_to_uhwi (offset) : HOST_WIDE_INT_MAX);
   +tree elsz = array_ref_element_size (x);
tree eltype = TREE_TYPE (x);
if (TREE_CODE (eltype) == INTEGER_TYPE)
  {
if (off)
  *off = idx;
  }
-   else if (idx < HOST_WIDE_INT_MAX)
- *fldoff += idx * int_size_in_bytes (eltype);
+   else if (idx < HOST_WIDE_INT_MAX
+&& tree_fits_shwi_p (elsz))
+ *fldoff += idx * tree_to_shwi (elsz);
else
  *fldoff = idx;
   @@ -2350,8 +2352,14 @@ get_origin_and_offset_r (tree x, HOST_WIDE_INT
*fldoff, HOST_WIDE_INT *fldsize,
   
   case COMPONENT_REF:

 {
+   tree foff = component_ref_field_offset (x);
tree fld = TREE_OPERAND (x, 1);
-   *fldoff += int_byte_position (fld);
+   if (!tree_fits_shwi_p (foff)
+   

Re: [PATCH] middle-end/105604 - snprintf dianostics and non-constant sizes/offsets

2022-05-17 Thread Martin Sebor via Gcc-patches

On 5/16/22 03:16, Richard Biener wrote:

The following tries to correct get_origin_and_offset_r not handling
non-constant sizes of array elements in ARRAY_REFs and non-constant
offsets of COMPONENT_REFs.  It isn't exactly clear how such failures
should be treated in this API and existing handling isn't consistent
here either.  The following applies two different variants, treating
non-constant array sizes like non-constant array indices and
treating non-constant offsets of COMPONENT_REFs by terminating
the recursion (not sure what that means to the callers).

Basically the code failed to use component_ref_field_offset and
array_ref_element_size and instead relies on inappropriate
helpers (that shouldn't exist in the first place ...).  The code
is also not safe-guarded against overflows in the final offset/size
computations but I'm not trying to rectify that.

Martin - can you comment on how the API should handle such
situations?


It looks like the -Wrestrict warning here ignores offsets equal to
HOST_WIDE_INT_MIN so presumably setting dst_offset (via *fldoff) to
that should avoid it.  Or maybe to HWI_MAX as it does for variable
offsets.

It also looks like the function only handles constant offsets and
sizes, and I have a vague recollection of enhancing it to work with
ranges.  That should avoid the overflow problem too.

Martin



Bootstrapped and tested on x86_64-unknown-linux-gnu.

OK for trunk and branches?

Thanks,
Richard.

2022-05-16  Richard Biener  

PR middle-end/105604
* gimple-ssa-sprintf.cc (get_origin_and_offset_r):
Handle non-constant ARRAY_REF element size and non-constant
COMPONENT_REF field offset.

* gcc.dg/torture/pr105604.c: New testcase.
---
  gcc/gimple-ssa-sprintf.cc   | 14 +++---
  gcc/testsuite/gcc.dg/torture/pr105604.c | 24 
  2 files changed, 35 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/gcc.dg/torture/pr105604.c

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index c93f12f90b5..14e215ce69c 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -2312,14 +2312,16 @@ get_origin_and_offset_r (tree x, HOST_WIDE_INT *fldoff, 
HOST_WIDE_INT *fldsize,
HOST_WIDE_INT idx = (tree_fits_uhwi_p (offset)
 ? tree_to_uhwi (offset) : HOST_WIDE_INT_MAX);
  
+	tree elsz = array_ref_element_size (x);

tree eltype = TREE_TYPE (x);
if (TREE_CODE (eltype) == INTEGER_TYPE)
  {
if (off)
  *off = idx;
  }
-   else if (idx < HOST_WIDE_INT_MAX)
- *fldoff += idx * int_size_in_bytes (eltype);
+   else if (idx < HOST_WIDE_INT_MAX
+&& tree_fits_shwi_p (elsz))
+ *fldoff += idx * tree_to_shwi (elsz);
else
  *fldoff = idx;
  
@@ -2350,8 +2352,14 @@ get_origin_and_offset_r (tree x, HOST_WIDE_INT *fldoff, HOST_WIDE_INT *fldsize,
  
  case COMPONENT_REF:

{
+   tree foff = component_ref_field_offset (x);
tree fld = TREE_OPERAND (x, 1);
-   *fldoff += int_byte_position (fld);
+   if (!tree_fits_shwi_p (foff)
+   || !tree_fits_shwi_p (DECL_FIELD_BIT_OFFSET (fld)))
+ return x;
+   *fldoff += (tree_to_shwi (foff)
+   + (tree_to_shwi (DECL_FIELD_BIT_OFFSET (fld))
+  / BITS_PER_UNIT));
  
  	get_origin_and_offset_r (fld, fldoff, fldsize, off);

x = TREE_OPERAND (x, 0);
diff --git a/gcc/testsuite/gcc.dg/torture/pr105604.c 
b/gcc/testsuite/gcc.dg/torture/pr105604.c
new file mode 100644
index 000..b002251df10
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr105604.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall" } */
+
+struct {
+  long users;
+  long size;
+  char *data;
+} * main_trans;
+void *main___trans_tmp_1;
+int sprintf(char *, char *, ...);
+int main() {
+  int users = 0;
+  struct {
+long users;
+long size;
+char *data;
+int links[users];
+char buf[];
+  } *trans = trans;
+  trans->data = trans->buf;
+  main___trans_tmp_1 = trans;
+  main_trans = main___trans_tmp_1;
+  sprintf(main_trans->data, "test");
+}




Re: [PATCH] tree-optimization/105175 - avoid -Wvector-operation-performance

2022-04-07 Thread Martin Sebor via Gcc-patches

On 4/7/22 00:59, Richard Biener wrote:

On Wed, 6 Apr 2022, Martin Sebor wrote:


On 4/6/22 03:23, Richard Biener wrote:

This avoids -Wvector-operation-performance diagnostics for vectorizer
produced code.  It's unfortunate the warning_at code in
tree-vect-generic.cc needs adjustments but the diagnostic suppression
code doesn't magically suppress those otherwise.


It seems like it should, as long as the statement location hasn't
changed after the suppress_diagnostic call in tree-vect-stmts.cc.


The location doesn't change.



Bootstrap / regtest running on x86_64-unknown-linux-gnu.

Martin/David - did I miss something obvious when doing the
tree-vect-generic.cc adjustment?


The only thing I can think of is that because it's not handled in
diagnostic-spec.cc, -Wvector-operation-performance is lumped in with
all other generic warnings that also aren't handled.  It means that
they are all treated as a group.  Whether or not that's what we want
for this specific warning might be something to consider.


So when I call suppress_warning (gimple *, ..) the suppress_warning_at
call constructs a nowarn_spec_t with NW_OTHER, it queries the
nowarn_map where it doesn't find anything yet, and goes on
with

   nowarn_map->put (loc, optspec);
   return true;

suppress_warning then (since supp is true anyway) goes on with

   set_no_warning_bit (stmt, supp);

which is likely what my changes to tree-vect-generic.cc in the end
key on.  When I simply invoke

warning_at (loc, OPT_Wvector_operation_performance,
"...")

I see nowhere that nowarn_spec_t::nowarn_spec_t is invoked, nor
is warning_suppressed_at.  Maybe I'm missing that being done
but I think that's by design?  It at least was surprising to me.


It's been a while so I'm hazy on the details.  I'd initially hoped
to have warning_at(loc, opt, ...) automatically disable warning opt
at loc.  It turned out that there are calls to warning_at() with
same loc and opt where we want to issue the warning (like for
distinct arguments in the same function call).  But I don't recall
trying to test warning_suppressed_at() first, before issuing
a warning.  That would make sense to me.  The only lightly POC
patch below doesn't seem to cause too much fallout:

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 73324a728fe..857d70e5d2e 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest-diagnostic.h"
 #include "opts.h"
 #include "cpplib.h"
+#include "tree.h"

 #ifdef HAVE_TERMIOS_H
 # include 
@@ -1337,6 +1338,10 @@ diagnostic_report_diagnostic (diagnostic_context 
*context,

   if (!diagnostic_enabled (context, diagnostic))
 return false;

+  if (!RESERVED_LOCATION_P (location)
+  && warning_suppressed_at (location, 
(opt_code)diagnostic->option_index))

+return false;
+
   if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
 /* Bail if the warning is not to be reported because all locations
in the inlining stack (if there is one) are in system headers.  */


Of course since we lack a warning_at (gimple *, ..) overload
or alternatively extending rich-location to cover diagnostic
suppression contexts, doing this would only work for stmts with
a location that doesn't fall back to that of the current
declaration (for UNKNOWN_LOCATION loc).


David and I discussed adding warning_at(gimple*, ...) and
warning_at(tree, ...) overloads but decided to go with a narrower
API in the initial patch and to consider extending it  later.  It
still seems like a useful feature.



So my main question was if the diagnostic suppression is supposed
to be transparently handled by warning_at (...) or whether indeed
explicit guards need to be added to each diagnostic emission.

As I'm now doing

if (!warning_suppressed_p (gsi_stmt (*gsi),
  OPT_Wvector_operation_performance))


I get to get_nowarn_spec for the stmt which will return NULL
because the no-warning bit is set (but it's always set in the
warning suppression call when done on a stmt!)

When I'm doing

   if (!warning_suppressed_at (loc,
  OPT_Wvector_operation_performance))

then it also suppresses the diagnostic but I think I'm not supposed
to call that function since it will ICE on UNKNOWN_LOCATION and it
would lack the fallback to the nowarning bit for stmts without
location.

That is - the stmt-based query looks correct to me but it will
always use the non-specific flag, at least when I suppress the
diagnostic based on the stmt?!  I think suppress_warning (gimple *,...)
should not set the no-warning bit when it succeeded in amending
the nowarn_map?

So, again, was the requirement to explicitely guard warning_at ()
calls with warning_suppressed_p () calls by design?  If it wasn't
intentional then I think we need to somehow allow to specify
a gimple * or tree as location argument to warning_at, since
we have 

Re: [PATCH] tree-optimization/105175 - avoid -Wvector-operation-performance

2022-04-06 Thread Martin Sebor via Gcc-patches

On 4/6/22 03:23, Richard Biener wrote:

This avoids -Wvector-operation-performance diagnostics for vectorizer
produced code.  It's unfortunate the warning_at code in
tree-vect-generic.cc needs adjustments but the diagnostic suppression
code doesn't magically suppress those otherwise.


It seems like it should, as long as the statement location hasn't
changed after the suppress_diagnostic call in tree-vect-stmts.cc.



Bootstrap / regtest running on x86_64-unknown-linux-gnu.

Martin/David - did I miss something obvious when doing the
tree-vect-generic.cc adjustment?


The only thing I can think of is that because it's not handled in
diagnostic-spec.cc, -Wvector-operation-performance is lumped in with
all other generic warnings that also aren't handled.  It means that
they are all treated as a group.  Whether or not that's what we want
for this specific warning might be something to consider.

Martin



Thanks,
Richard.

2022-04-06  Richard Biener  

PR tree-optimization/105175
* tree-vect-stmts.cc (vectorizable_operation): Suppress
-Wvector-operation-performance if using emulated vectors.
* tree-vect-generic.cc (expand_vector_piecewise): Do not diagnose
-Wvector-operation-performance when suppressed.
(expand_vector_parallel): Likewise.
(expand_vector_comparison): Likewise.
(expand_vector_condition): Likewise.
(lower_vec_perm): Likewise.
(expand_vector_conversion): Likewise.

* gcc.dg/pr105175.c: New testcase.
---
  gcc/testsuite/gcc.dg/pr105175.c | 16 +
  gcc/tree-vect-generic.cc| 41 ++---
  gcc/tree-vect-stmts.cc  |  2 ++
  3 files changed, 45 insertions(+), 14 deletions(-)
  create mode 100644 gcc/testsuite/gcc.dg/pr105175.c

diff --git a/gcc/testsuite/gcc.dg/pr105175.c b/gcc/testsuite/gcc.dg/pr105175.c
new file mode 100644
index 000..d8d7edb942a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr105175.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wvector-operation-performance" } */
+/* { dg-additional-options "-mno-sse" { target x86_64-*-* i?86-*-* } } */
+
+enum { QEMU_MIGRATION_COOKIE_PERSISTENT = 1 };
+struct {
+  unsigned flags;
+  unsigned flagsMandatory;
+} qemuMigrationCookieGetPersistent_mig;
+void qemuMigrationCookieGetPersistent()
+{
+  qemuMigrationCookieGetPersistent_mig.flags &=  /* { dg-bogus "will be 
expanded" } */
+  QEMU_MIGRATION_COOKIE_PERSISTENT;
+  qemuMigrationCookieGetPersistent_mig.flagsMandatory &=
+  QEMU_MIGRATION_COOKIE_PERSISTENT;
+}
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index 12a553ec8be..8b7227e8b58 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -317,8 +317,11 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, 
elem_op_func f,
int i;
location_t loc = gimple_location (gsi_stmt (*gsi));
  
-  if (nunits == 1)

-/* Do not diagnose decomposing single element vectors.  */
+  if (nunits == 1
+  || warning_suppressed_p (gsi_stmt (*gsi),
+  OPT_Wvector_operation_performance))
+/* Do not diagnose decomposing single element vectors or when
+   decomposing vectorizer produced operations.  */
  ;
else if (ret_type || !parallel_p)
  warning_at (loc, OPT_Wvector_operation_performance,
@@ -379,14 +382,16 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, 
elem_op_func f, tree type,
else
  {
/* Use a single scalar operation with a mode no wider than word_mode.  
*/
+  if (!warning_suppressed_p (gsi_stmt (*gsi),
+OPT_Wvector_operation_performance))
+   warning_at (loc, OPT_Wvector_operation_performance,
+   "vector operation will be expanded with a "
+   "single scalar operation");
scalar_int_mode mode
= int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
compute_type = lang_hooks.types.type_for_mode (mode, 1);
result = f (gsi, compute_type, a, b, bitsize_zero_node,
  TYPE_SIZE (compute_type), code, type);
-  warning_at (loc, OPT_Wvector_operation_performance,
- "vector operation will be expanded with a "
- "single scalar operation");
  }
  
return result;

@@ -487,8 +492,10 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree 
type, tree op0,
  
  	  if (TYPE_PRECISION (ret_inner_type) != 1)

ret_inner_type = build_nonstandard_integer_type (1, 1);
- warning_at (loc, OPT_Wvector_operation_performance,
- "vector operation will be expanded piecewise");
+ if (!warning_suppressed_p (gsi_stmt (*gsi),
+OPT_Wvector_operation_performance))
+   warning_at (loc, OPT_Wvector_operation_performance,
+   "vector operation will be expanded piecewise");
  for (i = 0; i < nunits;
   

Re: options: Remove 'gcc/c-family/c.opt:Wuse-after-free' option definition record (was: [PATCH v2 1/2] add -Wuse-after-free)

2022-03-29 Thread Martin Sebor via Gcc-patches

On 3/29/22 03:24, Thomas Schwinge wrote:

Hi!

On 2022-01-15T17:00:11-0700, Martin Sebor via Gcc-patches 
 wrote:

On 1/11/22 15:40, Jason Merrill wrote:

On 11/30/21 17:32, Martin Sebor via Gcc-patches wrote:

[default setting of the option]



Let's put =2 in -Wall for now.



I've adjusted [...] and pushed r12-6605 [...]


That's from commit 671a283636de75f7ed638ee6b01ed2d44361b8b6
"Add -Wuse-after-free [PR80532]":

| --- gcc/common.opt
| +++ gcc/common.opt
| [...]
| +Wuse-after-free
| +Common Var(warn_use_after_free) Warning
| +Warn for uses of pointers to deallocated strorage.
| +
| +Wuse-after-free=
| +Common Joined RejectNegative UInteger Var(warn_use_after_free) Warning 
IntegerRange(0, 3)
| +Warn for uses of pointers to deallocated strorage.
| [...]

| --- gcc/c-family/c.opt
| +++ gcc/c-family/c.opt
| [...]
| +# Defining these options here in addition to common.opt is necessary
| +# in order for the default -Wall setting of -Wuse-after-free=2 to take
| +# effect.
| +
| +Wuse-after-free
| +LangEnabledBy(C ObjC C++ LTO ObjC++)
| +; in common.opt
| +
| +Wuse-after-free=
| +LangEnabledBy(C ObjC C++ LTO ObjC++, Wall,2,0)
| +; in common.opt
| [...]

OK to push the attached "options: Remove
'gcc/c-family/c.opt:Wuse-after-free' option definition record"?


It's fine with me if it passes tests.  I remember noticing a subtle
distinction in how option aliases are sometimes treated in #pragma
GCC diagnostic but not the exact details.  I added tests to make
sure it has the expected effect without the trailing =.  See
the comment in c-c++-common/Wuse-after-free.c.

Thanks
Martin




Grüße
  Thomas


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955




Re: [PATCH v3] Document that the 'access' and 'nonnull' attributes are independent

2022-03-25 Thread Martin Sebor via Gcc-patches

On 3/25/22 12:45, David Malcolm wrote:

On Wed, 2022-03-23 at 17:52 +0100, Sebastian Huber wrote:

On 23/03/2022 17:31, Martin Sebor via Gcc-patches wrote:


The concern is that the constraints implied by atttributes access
and
nonnull are independent of each other.  I would suggest to document
that without talking about dereferencing because that's not implied
by either of them.  E.g., something like this (feel free to tweak
it
as you see fit):

Note that the @code{access} attribute doesn't imply the same
constraint as attribute @code{nonnull} (@pxref{Attribute
nonnull}).
The latter attribute should be used to annotate arguments that
must
never be null, regardless of the value of the size argument.


I would not give an advice on using the nonnull attribute here. This
attribute could have pretty dangerous effects in the function
definition
(removal of null pointer checks).



That's a fair point.

Here's a v3 of the patch, which tones down the advice, and mentions that
there are caveats when directing the reader to the "nonnull" attribute.

How does this look?


This version looks good to me.

Thanks
Martin



gcc/ChangeLog:
* doc/extend.texi (Common Function Attributes): Document that
'access' does not imply 'nonnull'.

Signed-off-by: David Malcolm 
---
  gcc/doc/extend.texi | 8 
  1 file changed, 8 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a4a25e86928..539dad7001d 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2652,6 +2652,14 @@ The mode is intended to be used as a means to help 
validate the expected
  object size, for example in functions that call @code{__builtin_object_size}.
  @xref{Object Size Checking}.
  
+Note that the @code{access} attribute merely specifies how an object

+referenced by the pointer argument can be accessed; it does not imply that
+an access @strong{will} happen.  Also, the @code{access} attribute does not
+imply the attribute @code{nonnull}; it may be appropriate to add both 
attributes
+at the declaration of a function that unconditionally manipulates a buffer via
+a pointer argument.  See the @code{nonnull} attribute for more information and
+caveats.
+
  @item alias ("@var{target}")
  @cindex @code{alias} function attribute
  The @code{alias} attribute causes the declaration to be emitted as an alias




Re: [PATCH v2] Document that the 'access' and 'nonnull' attributes are independent

2022-03-23 Thread Martin Sebor via Gcc-patches

On 3/23/22 07:01, David Malcolm wrote:

On Mon, 2022-03-14 at 16:18 -0600, Martin Sebor wrote:

On 3/9/22 14:57, David Malcolm via Gcc wrote:

On Wed, 2022-03-09 at 13:30 -0800, Andrew Pinski wrote:

On Wed, Mar 9, 2022 at 1:25 PM David Malcolm via Gcc
 wrote:


We gained __attribute__ ((access, ...)) in GCC 10:

https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html

which identifies one of the pointer/reference arguments of a
function
as being accessed according to an access-mode: read_only,
read_write,
write_only, or none.

We also have __attribute__ ((nonnull)) to indicate that a
function
argument (or all of them) must be non-NULL.

There doesn't seem to be a relationship between these in the
implementation, but it strikes me that almost anywhere that a
user
might use the "access" attribute, that parameter is probably
going
to
be required to be nonnull - though perhaps there are cases
where
APIs
check for NULL and reject them gracefully?


No, I think they are separate. The access just says these access
attributes are read only, write only, read-write or don't access
what
the pointer points to; it does not say they have to be read or
written
to.
I think it is a bad idea to connect the two ideas because you
could
have some cases where an argument is optional but is only read
from;
or is only written to (there are many in GCC sources even).


Thanks for the clarification...



Thanks,
Andrew Pinski



Might we want to somehow make __attribute__ ((access, ...))
imply
__attribute__ ((nonnull))?  (for non "none" access modes,
perhaps?)

If so, one place to implement this might be in tree.cc's
get_nonnull_args, and have it add to the bitmap any arguments
that
have an appropriate access attribute.

get_nonnull_args is used in various places:
- validating builtins
- in ranger_cache::block_apply_nonnull
- by -Wnonnull (in pass_post_ipa_warn::execute)
- by -Wanalyzer-possible-null-argument and -Wanalyzer-null-
argument;
I'm tracking the failure of these last two to make use of
__attribute__
((access)) in PR analyzer/104860.

So do we:

(a) leave it up to the user, requiring them to specify
__attribute__
((nonnull)) in addition to  __attribute__ ((access, ...))


...so that's (a) then.

I think it might be more user-friendly to be explicit about this in
the
documentation, maybe something like the attached?


I agree it's worth clarifying the manual.

But I don't think there's a way to annotate a function to indicate
that it will definitely access an object (or dereference a pointer).
Attribute access just implies that it might dereference it (unless
the size is zero), and attribute nonnull that the pointer must not
be null, not that it will be dereferenced (or even that it must be
valid, although that's implied by the language and should probably
be enforced in all contexts by some other warning).

The combination of access with nonzero size and nonnull only means
that the pointer must be nonnull and point to an object with at least
size elements.


Here's an updated version of the patch which expresses that also.

OK for trunk?

Dave



Martin



(not yet fully tested, but seems to build)

Dave






(b) leave it up to the individual sites in GCC that currently
make
use
of get_nonnull_args to add logic for handling   __attribute__
((access,
...))

(c) extend get_nonnull_args

?

Thoughts?
Dave









gcc/ChangeLog:
* doc/extend.texi (Common Function Attributes): Document that
'access' does not imply 'nonnull'.

Signed-off-by: David Malcolm 
---
  gcc/doc/extend.texi | 9 +
  1 file changed, 9 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a4a25e86928..790014f3da5 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2652,6 +2652,15 @@ The mode is intended to be used as a means to help 
validate the expected
  object size, for example in functions that call @code{__builtin_object_size}.
  @xref{Object Size Checking}.
  
+Note that the @code{access} attribute merely specifies how an object

+referenced by the pointer argument can be accessed; it does not imply that
+an access @strong{will} happen.  If the pointer will definitely be
+dereferenced, you may want to also add
+@code{__attribute__((nonnull (@var{arg-index})))} to the function for the
+pointer parameter in question (though the presence of the @code{nonnull}
+attribute does not imply that the parameter will be dereferenced, merely
+that it must be non-null).
+
  @item alias ("@var{target}")
  @cindex @code{alias} function attribute
  The @code{alias} attribute causes the declaration to be emitted as an alias


I'm sorry, I probably wasn't clear.  This text sounds contradictory:

  If the pointer will definitely be dereferenced ... does not imply
  that the parameter will be dereferenced...

The concern is that the constraints implied by atttributes access and
nonnull are independent of each other.  I would suggest to document
that without talking about dereferencing because 

Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-17 Thread Martin Sebor via Gcc-patches

On 3/17/22 12:02, Siddhesh Poyarekar wrote:

On 17/03/2022 23:21, Martin Sebor wrote:

On 3/17/22 11:22, Siddhesh Poyarekar wrote:

On 17/03/2022 22:16, Jeff Law wrote:

    #include 
    char a[] = "abc";
    char b[] = "abcd";

    int f (void)
    {
   return strncmp (a, b, 8);
    }

    where I get

    t.c:7:10: warning: ‘strncmp’ specified bound 8 exceeds source 
size 5

    [-Wstringop-overread]
     7 |   return strncmp (a, b, 8);   // -Wstringop-overread
       |          ^

    even without -Wall.  strncmp sees that a[3] is '\0' so it stops
    comparing
    and there's no UB.

This one is a clear case where warning is bad.   Both arguments are 
constant and we can determine they are NUL terminated and an 
overread will never occur.  No deep analysis really needed here.


THe far more interesting case in my mind is when one or both 
arguments have an unknown NUL termination state.  I could argue 
either side of that case.  I lean towards warning but I understand 
that opinions differ and my priorities have moved away from 
distro-level issues, so identifying code that needs a careful review 
for correctness, particularly old or security sensitive code, has 
become a much lower priority for me.   Combine that with the fact 
that we're really just dealing with over-reads here, I can support 
whatever the broadest consensus is.


Actually in the above reproducer a and b are not const, so this is in 
fact the case where the NUL termination state of the strings is in 
theory unknown.  From the distro level (and in general for 
applications) the question is how common this is and I gathered from 
a Red Hat internal conversation that it's not uncommon.  However 
David pointed out that I need to share more specific examples to 
quantify this, so I need to work on that.  I'll share an update once 
I have it.


One case I am aware of is the pmix package in Fedora/RHEL, which has 
the following warning:


pmix-3.2.3/examples/alloc.c: scope_hint: In function 'main'
pmix-3.2.3/examples/alloc.c:179:31: warning[-Wstringop-overread]: 
'PMIx_Get' reading 512 bytes from a region of size 15
   179 | if (PMIX_SUCCESS != (rc = PMIx_Get(, 
PMIX_UNIV_SIZE, NULL, 0, ))) {

   | ^~
pmix-3.2.3/examples/alloc.c:179:31: note: referencing argument 2 of 
type 'const char *'

pmix-3.2.3/examples/alloc.c:33: included_from: Included from here.
pmix-3.2.3/include/pmix.h:203:27: note: in a call to function 'PMIx_Get'
   203 | PMIX_EXPORT pmix_status_t PMIx_Get(const pmix_proc_t *proc, 
const pmix_key_t key,

   |   ^~~~
   177|   PMIX_PROC_CONSTRUCT();
   178|   PMIX_LOAD_PROCID(, myproc.nspace, 
PMIX_RANK_WILDCARD);
   179|-> if (PMIX_SUCCESS != (rc = PMIx_Get(, 
PMIX_UNIV_SIZE, NULL, 0, ))) {
   180|   fprintf(stderr, "Client ns %s rank %d: PMIx_Get 
universe size failed: %d\n", myproc.nspace, myproc.rank, rc);

   181|   goto done;

which is due to PMIx_Get calling strncmp a few levels within with 
non-const strings and a max size of 512 (the maximum size that a key 
could be; AFAICT it's the size of the buffer into which the key gets 
written out), where the strings are always NULL terminated.


This warning has nothing to do with strncmp.

It's issued for the call to PMIx_Get(), where the caller passes as
the second argument PMIX_UNIV_SIZE, a macro that expands to
the string "pmix.univ.size".

The function is declared like so:

   PMIX_EXPORT pmix_status_t
   PMIx_Get(const pmix_proc_t *proc, const pmix_key_t key,
    const pmix_info_t info[], size_t ninfo,
    pmix_value_t **val);

The type of the second function argument, pmix_key_t, defined as

   typedef char pmix_key_t[PMIX_MAX_KEYLEN+1];

an array of 512 elements (PMIX_MAX_KEYLEN is defined to 511), but
PMIX_UNIV_SIZE is much smaller (just 15 bytes).

The warning detects passing smaller arrays to parameters of larger
types declared using the array syntax.  It's controlled by
-Warray-parameter.


That's odd, shouldn't it show up as -Warray-parameter then and not 
-Wstringop-overread?


I should have said: the array parameter feature is controlled by
-Warray-parameter.  (The warning above is obviously
-Wstringop-overread).

But since -Warray-parameter controls the array parameter feature,
it might be appropriate to also make the -Wstringop-overread and
-Wstringop-overflow instances for calls to such functions conditional
on the former option being enabled.  (Otherwise, -Warray-parameter
has a separate function of its own.)

I do see a minor issue with this warning in GCC 12: it's issued three
times for the same call, rather than once.  That's probably because
the new warning pass that issues it runs multiple times and doesn't
suppress the warning after issuing it the first time.

Martin



Siddhesh





Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-17 Thread Martin Sebor via Gcc-patches

On 3/17/22 11:22, Siddhesh Poyarekar wrote:

On 17/03/2022 22:16, Jeff Law wrote:

    #include 
    char a[] = "abc";
    char b[] = "abcd";

    int f (void)
    {
   return strncmp (a, b, 8);
    }

    where I get

    t.c:7:10: warning: ‘strncmp’ specified bound 8 exceeds source size 5
    [-Wstringop-overread]
     7 |   return strncmp (a, b, 8);   // -Wstringop-overread
       |          ^

    even without -Wall.  strncmp sees that a[3] is '\0' so it stops
    comparing
    and there's no UB.

This one is a clear case where warning is bad.   Both arguments are 
constant and we can determine they are NUL terminated and an overread 
will never occur.  No deep analysis really needed here.


THe far more interesting case in my mind is when one or both arguments 
have an unknown NUL termination state.  I could argue either side of 
that case.  I lean towards warning but I understand that opinions 
differ and my priorities have moved away from distro-level issues, so 
identifying code that needs a careful review for correctness, 
particularly old or security sensitive code, has become a much lower 
priority for me.   Combine that with the fact that we're really just 
dealing with over-reads here, I can support whatever the broadest 
consensus is.


Actually in the above reproducer a and b are not const, so this is in 
fact the case where the NUL termination state of the strings is in 
theory unknown.  From the distro level (and in general for applications) 
the question is how common this is and I gathered from a Red Hat 
internal conversation that it's not uncommon.  However David pointed out 
that I need to share more specific examples to quantify this, so I need 
to work on that.  I'll share an update once I have it.


One case I am aware of is the pmix package in Fedora/RHEL, which has the 
following warning:


pmix-3.2.3/examples/alloc.c: scope_hint: In function 'main'
pmix-3.2.3/examples/alloc.c:179:31: warning[-Wstringop-overread]: 
'PMIx_Get' reading 512 bytes from a region of size 15
   179 | if (PMIX_SUCCESS != (rc = PMIx_Get(, PMIX_UNIV_SIZE, 
NULL, 0, ))) {

   | ^~
pmix-3.2.3/examples/alloc.c:179:31: note: referencing argument 2 of type 
'const char *'

pmix-3.2.3/examples/alloc.c:33: included_from: Included from here.
pmix-3.2.3/include/pmix.h:203:27: note: in a call to function 'PMIx_Get'
   203 | PMIX_EXPORT pmix_status_t PMIx_Get(const pmix_proc_t *proc, 
const pmix_key_t key,

   |   ^~~~
   177|   PMIX_PROC_CONSTRUCT();
   178|   PMIX_LOAD_PROCID(, myproc.nspace, PMIX_RANK_WILDCARD);
   179|-> if (PMIX_SUCCESS != (rc = PMIx_Get(, PMIX_UNIV_SIZE, 
NULL, 0, ))) {
   180|   fprintf(stderr, "Client ns %s rank %d: PMIx_Get 
universe size failed: %d\n", myproc.nspace, myproc.rank, rc);

   181|   goto done;

which is due to PMIx_Get calling strncmp a few levels within with 
non-const strings and a max size of 512 (the maximum size that a key 
could be; AFAICT it's the size of the buffer into which the key gets 
written out), where the strings are always NULL terminated.


This warning has nothing to do with strncmp.

It's issued for the call to PMIx_Get(), where the caller passes as
the second argument PMIX_UNIV_SIZE, a macro that expands to
the string "pmix.univ.size".

The function is declared like so:

  PMIX_EXPORT pmix_status_t
  PMIx_Get(const pmix_proc_t *proc, const pmix_key_t key,
   const pmix_info_t info[], size_t ninfo,
   pmix_value_t **val);

The type of the second function argument, pmix_key_t, defined as

  typedef char pmix_key_t[PMIX_MAX_KEYLEN+1];

an array of 512 elements (PMIX_MAX_KEYLEN is defined to 511), but
PMIX_UNIV_SIZE is much smaller (just 15 bytes).

The warning detects passing smaller arrays to parameters of larger
types declared using the array syntax.  It's controlled by
-Warray-parameter.

Martin



Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-16 Thread Martin Sebor via Gcc-patches

On 3/15/22 19:24, Siddhesh Poyarekar wrote:

On 16/03/2022 02:06, Martin Sebor wrote:

The intended use of the strncmp bound is to limit the comparison to
at most the size of the arrays or (in a subset of cases) the length
of an initial substring. Providing an arbitrary bound that's not
related to the sizes as you describe sounds very much like a misuse.


Nothing in the standard says that the bound is related to the sizes of 
input buffers.  I don't think deducing that intent makes sense either, 
nor concluding that any other use case is misuse.



As a historical note, strncmp was first introduced in UNIX v7 where
its purpose, alongside strncpy, was to manipulate (potentially)
unterminated character arrays like file names stored in fixed size
arrays (typically 14 bytes).  Strncpy would fill the buffers with
ASCII data up to their size and pad the rest with nuls only if there
was room.

Strncmp was then used to compare these potentially unterminated
character arrays (e.g., archive headers in ld and ranlib).  The bound
was the size of the fixed size array.  Its other use case was to compare
leading portions of strings (e.g, when looking for an environment
variable or when stripping "./" from path names).


Thanks for sharing the historical perspective.


Since the early UNIX days, both strncpy and to a lesser extent strncmp
have been widely misused and, along with many other functions in
, a frequent source of bugs due to common misunderstanding
of their intended purpose.  The aim of these warnings is to detect
the common (and sometimes less common) misuses and bugs.


They're all valid uses however since they do not violate the standard. 
If we find at compile time that the strings don't terminate at the 
bounds, emitting the warning is OK but the more pessimistic check seems 
like overkill.



I haven't seen these so I can't very well comment on them.  But I can
assure you that warning for the code above is intentional.  Whether
or not the arrays are nul-terminated, the expected way to call
the function is with a bound no greater than their size (some coding
guidelines are explicit about this; see for example the CERT C Secure
Coding standard rule ARR38-C).

(Granted, the manual makes it sound like -Wstringop-overread only
detects provable past-the-end reads.  That's a mistake in
the documentation that should be fixed.  The warning was never quite
so limited, nor was it intended to be.)


The contention is not that it's not provable, it's more that it's 
doesn't even pass the "based on available information this is definitely 
buggy" assertion, making it more a strong suggestion than a warning that 
something is definitely amiss.  Which is why IMO it is more suitable as 
an analyzer check than a warning.


As the GCC manual prominently states (and as I already pointed out)
warnings are:

  constructions that are not inherently erroneous but that are risky
  or suggest there may have been an error.

None of them implies a definite bug, and only a minority are about
violations of the standard.  Many point out benign code that's just
suspicious.

We can disagree (and many of us do) about the value of this or that
warning but that alone is not sufficient reason to change it.  Least
of all in stage 4, and with no details about the issues you say you
found.

Martin



Re: [PATCH] handle "invisible" reference in -Wdangling-pointer (PR104436)

2022-03-16 Thread Martin Sebor via Gcc-patches

On 3/9/22 06:17, Richard Biener wrote:

On Fri, Feb 11, 2022 at 12:05 AM Martin Sebor via Gcc-patches
 wrote:


On 2/8/22 15:37, Jason Merrill wrote:

On 2/8/22 16:59, Martin Sebor wrote:

Transforming a by-value arguments to by-reference as GCC does for some
class types can trigger -Wdangling-pointer when the argument is used
to store the address of a local variable.  Since the stored value is
not accessible in the caller the warning is a false positive.

The attached patch handles this case by excluding PARM_DECLs with
the DECL_BY_REFERENCE bit set from consideration.

While testing the patch I noticed some instances of the warning are
uninitentionally duplicated as the pass runs more than once.  To avoid
that, I also introduce warning suppression into the handler for this
instance of the warning.  (There might still be others.)


The second test should verify that we do warn about returning 't' from a
function; we don't want to ignore the DECL_BY_REFERENCE RESULT_DECL.


The indirect aggregate case isn't handled and needs more work but
since you brought it up I thought I should look into finishing it.
The attached patch #2 adds support for it.  It also incorporates
Richard's suggestion to test PARM_DECL.  Patch #2 applies on top
of patch #1 which is unchanged from the first revision.


patch #1 would be OK if you'd do the PARM_DECL check there - I'd
rather defer #2 to stage1.

Richard.



I have retested it on x86_64-linux and by building Glibc and
Binutils + GDB.

If now is too late for the aggregate enhancement I'm okay with
deferring it until stage 1.


I committed the adjusted patch in r12-7650.  I'll try to remember to
ping the second patch in stage 1.

Martin






+  tree var = SSA_NAME_VAR (lhs_ref.ref);
+  if (DECL_BY_REFERENCE (var))
+/* Avoid by-value arguments transformed into by-reference.  */
+continue;


I wonder if we can we express this property of invisiref parms somewhere
more general?  I imagine optimizations would find it useful as well.
Could pointer_query somehow treat the reference as pointing to a
function-local object?


I don't quite see where in the pointer_query class this would be
useful (the class also isn't used for optimization).  I could add
a helper to the access_ref class to query this property in warning
code but as this is the only potential client I'm also not sure
that's quite what you had in mind.  I'd need some guidance as to
what you're thinking of here.

Martin




I previously tried to express this by marking the reference as
'restrict', but that was wrong
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97474).

Jason





Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-15 Thread Martin Sebor via Gcc-patches

On 3/15/22 10:40, Siddhesh Poyarekar wrote:

On 15/03/2022 21:09, Martin Sebor wrote:

The strncmp function takes arrays as arguments (not necessarily
strings).  The main purpose of the -Wstringop-overread warning
for calls to it is to detect calls where one of the arrays is
not a nul-terminated string and the bound is larger than the size
of the array.  For example:

   char a[4], b[4];

   int f (void)
   {
 return strncmp (a, b, 8);   // -Wstringop-overread
   }

Such a call is suspect: if one of the arrays isn't nul-terminated
the call is undefined.  Otherwise, if both are nul-terminated there


Isn't "suspect" too harsh a description though?  The bound does not 
specify the size of a or b, it specifies the maximum extent to which to 
compare a and b, the extent being any application-specific limit.  In 
fact the limit could be the size of some arbitrary third buffer that the 
contents of a or b must be copied to, truncating to the bound.


The intended use of the strncmp bound is to limit the comparison to
at most the size of the arrays or (in a subset of cases) the length
of an initial substring. Providing an arbitrary bound that's not
related to the sizes as you describe sounds very much like a misuse.

As a historical note, strncmp was first introduced in UNIX v7 where
its purpose, alongside strncpy, was to manipulate (potentially)
unterminated character arrays like file names stored in fixed size
arrays (typically 14 bytes).  Strncpy would fill the buffers with
ASCII data up to their size and pad the rest with nuls only if there
was room.

Strncmp was then used to compare these potentially unterminated
character arrays (e.g., archive headers in ld and ranlib).  The bound
was the size of the fixed size array.  Its other use case was to compare
leading portions of strings (e.g, when looking for an environment
variable or when stripping "./" from path names).

Since the early UNIX days, both strncpy and to a lesser extent strncmp
have been widely misused and, along with many other functions in
, a frequent source of bugs due to common misunderstanding
of their intended purpose.  The aim of these warnings is to detect
the common (and sometimes less common) misuses and bugs.

I agree the call is undefined if one of the arrays is not nul-terminated 
and that's the thing; nothing about the bound is undefined in this 
context, it's the NUL termination that is key.



is no point in calling strncmp with a bound greater than their sizes.


There is, when the bound describes something else, e.g. the size of a 
third destination buffer into which one of the input buffers may get 
copied into.  Or when the bound describes the maximum length of a set of 
strings where only a subset of the strings are reachable in the current 
function and ranger sees it, allowing us to reduce our input string size 
estimate.  The bounds being the maximum of the lengths of two input 
strings is just one of many possibilities.



With no evidence that this warning is ever harmful I'd consider


There is, the false positives were seen in Fedora/RHEL builds.


I haven't seen these so I can't very well comment on them.  But I can
assure you that warning for the code above is intentional.  Whether
or not the arrays are nul-terminated, the expected way to call
the function is with a bound no greater than their size (some coding
guidelines are explicit about this; see for example the CERT C Secure
Coding standard rule ARR38-C).

(Granted, the manual makes it sound like -Wstringop-overread only
detects provable past-the-end reads.  That's a mistake in
the documentation that should be fixed.  The warning was never quite
so limited, nor was it intended to be.)

Martin




suppressing it a regression.  Since the warning is a deliberate
feature in a released compiler and GCC is now in a regression
fixing stage, this patch is out of scope even if a case where
the warning wasn't helpful did turn up (none has been reported
so far).


Wait, I just reported an issue and it's across multiple packages in 
Fedora/RHEL :)


I think this is a regression since gcc 11 due to misunderstanding the 
specification and assuming too strong a relationship between the size 
argument of strncmp (and indeed strnlen and strndup) and the size of 
objects being passed to it.  Compliant code relies on the compiler to do 
the right thing here, i.e. optimize the strncmp call to strcmp and not 
panic about the size argument being larger than the input buffer size. 
If at all such a diagnostic needs to stay, it ought to go into the 
analyzer, where such looser heuristic suggestions are more acceptable 
and sometimes even appreciated.


FWIW, I'm open to splitting the warning levels as you suggested if 
that's the consensus since it at least provides a way to make these 
warnings saner. However I still haven't found the rationale presented so 
far compelling enough to justify these false positives; I just don't see 
a proportional enough reward.  Hopefully more 

Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-15 Thread Martin Sebor via Gcc-patches

On 3/14/22 23:31, Siddhesh Poyarekar wrote:

The size argument in strncmp only describe the maximum length to which
to compare two strings and is not an indication of sizes of the two
source strings.  Do not warn if it is larger than the two input strings
because it is entirely likely that the size argument is a conservative
maximum to accommodate inputs of different lengths and only a subset is
reachable through the current code path or that it is some other
application-specific property completely unrelated to the sizes of the
input strings.


The strncmp function takes arrays as arguments (not necessarily
strings).  The main purpose of the -Wstringop-overread warning
for calls to it is to detect calls where one of the arrays is
not a nul-terminated string and the bound is larger than the size
of the array.  For example:

  char a[4], b[4];

  int f (void)
  {
return strncmp (a, b, 8);   // -Wstringop-overread
  }

Such a call is suspect: if one of the arrays isn't nul-terminated
the call is undefined.  Otherwise, if both are nul-terminated there
is no point in calling strncmp with a bound greater than their sizes.

With no evidence that this warning is ever harmful I'd consider
suppressing it a regression.  Since the warning is a deliberate
feature in a released compiler and GCC is now in a regression
fixing stage, this patch is out of scope even if a case where
the warning wasn't helpful did turn up (none has been reported
so far).



gcc/ChangeLog:

middle-end/104854
* gimple-ssa-warn-access.cc
(pass_waccess::warn_zero_sized_strncmp_inputs): New function.
(pass_waccess::check_strncmp): Use it.

gcc/testsuite/ChangeLog:

middle-end/104854
* gcc.dg/Wstringop-overread.c (test_strncmp_array): Don't expect
failures for non-zero sizes.

Signed-off-by: Siddhesh Poyarekar 
---

Changes from v1:

A little better approach, ensuring that it tries to warn on zero length
inputs if the size of at least one of the two sources is known.

Also cc'ing Martin so that we can discuss approach on the list instead
of on the bug.  To summarize the discussion so far, Martin suggests that
the warning be split into levels but I'm contesting the utility of the
heuristics as a compiler warning given the looseness of the relationship
between the size argument and the inputs in the case of these functions.


Thanks for CC'ing me.  The motivating example in pr104854 that we have
been discussing there involves strndup with a string literal.  That's
an entirely different case than the one your patch changes, and I don't
understand in what way you think they are related.

Martin




  gcc/gimple-ssa-warn-access.cc | 69 +--
  gcc/testsuite/gcc.dg/Wstringop-overread.c |  2 +-
  2 files changed, 28 insertions(+), 43 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 75297ed7c9e..15299770e29 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2137,6 +2137,9 @@ private:
/* Return true if use follows an invalidating statement.  */
bool use_after_inval_p (gimple *, gimple *, bool = false);
  
+  /* Emit an overread warning for zero sized inputs to strncmp.  */

+  void warn_zero_sized_strncmp_inputs (gimple *, tree *, access_data *);
+
/* A pointer_query object to store information about pointers and
   their targets in.  */
pointer_query m_ptr_qry;
@@ -2619,8 +2622,20 @@ pass_waccess::check_stxncpy (gcall *stmt)
data.mode, , m_ptr_qry.rvals);
  }
  
-/* Check a call STMT to stpncpy() or strncpy() for overflow and warn

-   if it does.  */
+/* Warn for strncmp on a zero sized source or when an argument isn't
+   nul-terminated.  */
+void
+pass_waccess::warn_zero_sized_strncmp_inputs (gimple *stmt, tree *bndrng,
+ access_data *pad)
+{
+  tree func = get_callee_fndecl (stmt);
+  location_t loc = gimple_location (stmt);
+  maybe_warn_for_bound (OPT_Wstringop_overread, loc, stmt, func, bndrng,
+   size_zero_node, pad);
+}
+
+/* Check a call STMT to strncmp () for overflow and warn if it does.  This is
+   limited to checking for NUL terminated arrays for now.  */
  
  void

  pass_waccess::check_strncmp (gcall *stmt)
@@ -2678,46 +2693,16 @@ pass_waccess::check_strncmp (gcall *stmt)
if (!bndrng[0] || integer_zerop (bndrng[0]))
  return;
  
-  if (len1 && tree_int_cst_lt (len1, bndrng[0]))

-bndrng[0] = len1;
-  if (len2 && tree_int_cst_lt (len2, bndrng[0]))
-bndrng[0] = len2;
-
-  /* compute_objsize almost never fails (and ultimately should never
- fail).  Don't bother to handle the rare case when it does.  */
-  if (!compute_objsize (arg1, stmt, 1, , _ptr_qry)
-  || !compute_objsize (arg2, stmt, 1, , _ptr_qry))
-return;
-
-  /* Compute the size of the remaining space in each array after
- subtracting any offset into it.  */
-  offset_int rem1 = 

Re: [PATCH] call mark_dfs_back_edges() before testing EDGE_DFS_BACK [PR104761]

2022-03-03 Thread Martin Sebor via Gcc-patches

On 3/3/22 01:01, Jakub Jelinek wrote:

On Wed, Mar 02, 2022 at 04:15:09PM -0700, Martin Sebor via Gcc-patches wrote:

The -Wdangling-pointer code tests the EDGE_DFS_BACK but the pass never
calls the mark_dfs_back_edges() function that initializes the bit (I
didn't know about it).  As a result the bit is not set when expected,
which can cause false positives under the right conditions.


Not a review because I also had to look up what computes EDGE_DFS_BACK,
so I don't feel the right person to ack the patch.

So, just a few questions.

The code in question is:
   auto gsi = gsi_for_stmt (use_stmt);

   auto_bitmap visited;

   /* A use statement in the last basic block in a function or one that
  falls through to it is after any other prior clobber of the used
  variable unless it's followed by a clobber of the same variable. */
   basic_block bb = use_bb;
   while (bb != inval_bb
  && single_succ_p (bb)
  && !(single_succ_edge (bb)->flags & (EDGE_EH|EDGE_DFS_BACK)))
 {
   if (!bitmap_set_bit (visited, bb->index))
 /* Avoid cycles. */
 return true;

   for (; !gsi_end_p (gsi); gsi_next_nondebug ())
 {
   gimple *stmt = gsi_stmt (gsi);
   if (gimple_clobber_p (stmt))
 {
   if (clobvar == gimple_assign_lhs (stmt))
 /* The use is followed by a clobber.  */
 return false;
 }
 }

   bb = single_succ (bb);
   gsi = gsi_start_bb (bb);
 }

1) shouldn't it give up for EDGE_ABNORMAL too?  I mean, e.g.
following a non-local goto forced edge from a noreturn call
to a non-local label (if there is just one) doesn't seem
right to me


Possibly yes.  I can add it but I don't have a lot of experience with
these bits so if you can suggest a test case to exercise this that
would be helpful.


2) if EDGE_DFS_BACK is computed and 1) is done, is there any
reason why you need 2 levels of protection, i.e. the EDGE_DFS_BACK
check as well as the visited bitmap (and having them use
very different answers, if EDGE_DFS_BACK is seen, the function
will return false, if visited bitmap has a bb, it will return true)?
Can't the visited bitmap go away?


Possibly.  As I said above, I don't have enough experience with these
bits to make (and test) the changes quickly, or enough bandwidth to
come up to speed on them.  Please feel free to make these improvements.


3) I'm concerned about compile time with the above, consider you have
100 use_stmts and 100 corresponding inv_stmts and in each
case you enter this loop and go through a series of very large basic
blocks that don't clobber those stmts; shouldn't it bail out
(return false) after walking some param
controlled number of non-debug stmts (say 1000 by default)?
There is an early exit if
if (dominated_by_p (CDI_DOMINATORS, use_bb, inval_bb))
  return true;
(I admit I haven't read the code what happens if there is more than
one clobber for the same variable)


I tend to agree that the loop is less than optimal.  But before
imposing another arbitrary limit my preference would be to see if
it could be made more efficient.  Without thinking about it too hard,
it seems that with some efficient lookup table a single traversal
per function should be sufficient.  The first time through populate
the table with the clobbered variables along the path from use_bb
and each subsequent time just look up clobvar in the table.

But I have to use up the rest of my 2021 PTO next week before I lose
it and I don't expect to have the cycles to work on this anytime soon.

Martin




The attached patch adds a call to the warning pass to initialize
the bit.  Tested on x86_64-linux.

Martin



Call mark_dfs_back_edges before testing EDGE_DFS_BACK [PR104761].

Resolves:
PR middle-end/104761 - bogus -Wdangling-pointer with cleanup and infinite loop

gcc/ChangeLog:

PR middle-end/104761
* gimple-ssa-warn-access.cc (pass_waccess::execute): Call
mark_dfs_back_edges.

gcc/testsuite/ChangeLog:

PR middle-end/104761
* g++.dg/warn/Wdangling-pointer-4.C: New test.
* gcc.dg/Wdangling-pointer-4.c: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index b7cdad517b3..b519712d76e 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -47,7 +47,7 @@
  #include "tree-object-size.h"
  #include "tree-ssa-strlen.h"
  #include "calls.h"
-#include "cfgloop.h"
+#include "cfganal.h"
  #include "intl.h"
  #include "gimple-range.h"
  #include "stringpool.h"
@@ -4710,6 +4710,9 @@ pass_waccess::execute (function *fun)
calculate_dominance_info (CDI_DOMINATORS);

[PATCH] call mark_dfs_back_edges() before testing EDGE_DFS_BACK [PR104761]

2022-03-02 Thread Martin Sebor via Gcc-patches

The -Wdangling-pointer code tests the EDGE_DFS_BACK but the pass never
calls the mark_dfs_back_edges() function that initializes the bit (I
didn't know about it).  As a result the bit is not set when expected,
which can cause false positives under the right conditions.

The attached patch adds a call to the warning pass to initialize
the bit.  Tested on x86_64-linux.

MartinCall mark_dfs_back_edges before testing EDGE_DFS_BACK [PR104761].

Resolves:
PR middle-end/104761 - bogus -Wdangling-pointer with cleanup and infinite loop

gcc/ChangeLog:

	PR middle-end/104761
	* gimple-ssa-warn-access.cc (pass_waccess::execute): Call
	mark_dfs_back_edges.

gcc/testsuite/ChangeLog:

	PR middle-end/104761
	* g++.dg/warn/Wdangling-pointer-4.C: New test.
	* gcc.dg/Wdangling-pointer-4.c: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index b7cdad517b3..b519712d76e 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -47,7 +47,7 @@
 #include "tree-object-size.h"
 #include "tree-ssa-strlen.h"
 #include "calls.h"
-#include "cfgloop.h"
+#include "cfganal.h"
 #include "intl.h"
 #include "gimple-range.h"
 #include "stringpool.h"
@@ -4710,6 +4710,9 @@ pass_waccess::execute (function *fun)
   calculate_dominance_info (CDI_DOMINATORS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
+  /* Set or clear EDGE_DFS_BACK bits on back edges.  */
+  mark_dfs_back_edges (fun);
+
   /* Create a new ranger instance and associate it with FUN.  */
   m_ptr_qry.rvals = enable_ranger (fun);
   m_func = fun;
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C
new file mode 100644
index 000..3608cc79e9a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C
@@ -0,0 +1,23 @@
+/* PR middle-end/104761 - False positive -Wdangling-pointer warning
+   in NetworkManager
+   { dg-do compile }
+   { dg-options "-O -Wall -fno-exceptions" } */
+
+struct S { int i; };
+
+struct X { ~X (); };
+
+void g (int);
+
+void test (int i)
+{
+  S s = { 0 };
+
+  X x;
+
+  if (i)
+{
+  g (s.i);// { dg-bogus "-Wdangling-pointer" }
+  for ( ; ; );
+}
+}
diff --git a/gcc/testsuite/gcc.dg/Wdangling-pointer-4.c b/gcc/testsuite/gcc.dg/Wdangling-pointer-4.c
new file mode 100644
index 000..b2716c7b634
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wdangling-pointer-4.c
@@ -0,0 +1,23 @@
+/* PR middle-end/104761 - False positive -Wdangling-pointer warning
+   in NetworkManager
+   { dg-do compile }
+   { dg-options "-O -Wall" } */
+
+typedef struct { int i; } S;
+
+void f (S **);
+
+int g (int);
+
+void nowarn (int x)
+{
+  S s = { 0 };
+
+  __attribute__((__cleanup__ (f))) S *p = 0;
+
+  if (x)
+{
+  g (s.i);// { dg-bogus "-Wdangling-pointer" }
+  for ( ; ; );
+}
+}


PING [PATCH] handle "invisible" reference in -Wdangling-pointer (PR104436)

2022-03-01 Thread Martin Sebor via Gcc-patches

Pinging the two patches here:
https://gcc.gnu.org/pipermail/gcc-patches/2022-February/590230.html

On 2/10/22 16:04, Martin Sebor wrote:

On 2/8/22 15:37, Jason Merrill wrote:

On 2/8/22 16:59, Martin Sebor wrote:

Transforming a by-value arguments to by-reference as GCC does for some
class types can trigger -Wdangling-pointer when the argument is used
to store the address of a local variable.  Since the stored value is
not accessible in the caller the warning is a false positive.

The attached patch handles this case by excluding PARM_DECLs with
the DECL_BY_REFERENCE bit set from consideration.

While testing the patch I noticed some instances of the warning are
uninitentionally duplicated as the pass runs more than once.  To avoid
that, I also introduce warning suppression into the handler for this
instance of the warning.  (There might still be others.)


The second test should verify that we do warn about returning 't' from 
a function; we don't want to ignore the DECL_BY_REFERENCE RESULT_DECL.


The indirect aggregate case isn't handled and needs more work but
since you brought it up I thought I should look into finishing it.
The attached patch #2 adds support for it.  It also incorporates
Richard's suggestion to test PARM_DECL.  Patch #2 applies on top
of patch #1 which is unchanged from the first revision.

I have retested it on x86_64-linux and by building Glibc and
Binutils + GDB.

If now is too late for the aggregate enhancement I'm okay with
deferring it until stage 1.




+  tree var = SSA_NAME_VAR (lhs_ref.ref);
+  if (DECL_BY_REFERENCE (var))
+    /* Avoid by-value arguments transformed into by-reference.  */
+    continue;


I wonder if we can we express this property of invisiref parms 
somewhere more general?  I imagine optimizations would find it useful 
as well. Could pointer_query somehow treat the reference as pointing 
to a function-local object?


I don't quite see where in the pointer_query class this would be
useful (the class also isn't used for optimization).  I could add
a helper to the access_ref class to query this property in warning
code but as this is the only potential client I'm also not sure
that's quite what you had in mind.  I'd need some guidance as to
what you're thinking of here.

Martin




I previously tried to express this by marking the reference as 
'restrict', but that was wrong 
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97474).


Jason





Re: [PATCH] warn-access: Fix up check_pointer_uses [PR104715]

2022-03-01 Thread Martin Sebor via Gcc-patches

On 3/1/22 11:41, Jakub Jelinek wrote:

Hi!

The following testcase emits bogus -Wdangling-pointer warnings.
The bug is that when it sees that ptr immediate use is a call that
returns one of its arguments, it will assume that the return value
is based on ptr, but that is the case only if ptr is passed to the
argument that is actually returned (so e.g. for memcpy the first argument,
etc.).  When the builtins guarantee e.g. that the result is based on the
first argument (either ERF_RETURNS_ARG 0 in which case it will always
just returns the first argument as is, or when it is something like
strstr or strpbrk or mempcpy that it returns some pointer based on the
first argument), it means the result is not based on second or following
argument if any.  The second hunk fixes this.

The first hunk just removes an unnecessary TREE_CODE check, the code only
pushes SSA_NAMEs into the pointers vector and if it didn't, it uses
   FOR_EACH_IMM_USE_FAST (use_p, iter, ptr)
a few lines below this, which of course requires that ptr is a SSA_NAME.
Tree checking on SSA_NAME_VERSION will already ensure that if it wasn't
a SSA_NAME, we'd ICE.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


Thanks for the fix.  It makes sense to me.  Besides the test for
the false positives I would suggest to add one to verify that using
the first argument to a strstr() call is diagnosed if it's dangling
(both as is, as well as with an offset from the first element).
There are tests for memchr and strchr in the -Wdangling-pointer
test suite but none for strstr.

Martin



2022-03-01  Jakub Jelinek  

PR tree-optimization/104715
* gimple-ssa-warn-access.cc (pass_waccess::check_pointer_uses): Don't
unnecessarily test if ptr is a SSA_NAME, it has to be.  Only push lhs
of a call if gimple_call_return_arg is equal to ptr, not just when it
is non-NULL.

* c-c++-common/Wdangling-pointer-7.c: New test.

--- gcc/gimple-ssa-warn-access.cc.jj2022-02-28 16:22:40.860520930 +0100
+++ gcc/gimple-ssa-warn-access.cc   2022-02-28 16:55:01.242272499 +0100
@@ -4169,8 +4169,7 @@ pass_waccess::check_pointer_uses (gimple
for (unsigned i = 0; i != pointers.length (); ++i)
  {
tree ptr = pointers[i];
-  if (TREE_CODE (ptr) == SSA_NAME
- && !bitmap_set_bit (visited, SSA_NAME_VERSION (ptr)))
+  if (!bitmap_set_bit (visited, SSA_NAME_VERSION (ptr)))
/* Avoid revisiting the same pointer.  */
continue;
  
@@ -4267,7 +4266,7 @@ pass_waccess::check_pointer_uses (gimple
  
  	  if (gcall *call = dyn_cast (use_stmt))

{
- if (gimple_call_return_arg (call))
+ if (gimple_call_return_arg (call) == ptr)
if (tree lhs = gimple_call_lhs (call))
  if (TREE_CODE (lhs) == SSA_NAME)
pointers.safe_push (lhs);
--- gcc/testsuite/c-c++-common/Wdangling-pointer-7.c.jj 2022-02-28 
17:09:09.906355082 +0100
+++ gcc/testsuite/c-c++-common/Wdangling-pointer-7.c2022-02-28 
17:03:50.533839892 +0100
@@ -0,0 +1,36 @@
+/* PR tree-optimization/104715 */
+/* { dg-do compile } */
+/* { dg-options "-Wdangling-pointer" } */
+
+char *
+foo (char *p)
+{
+  {
+char q[61] = 
"012345678901234567890123456789012345678901234567890123456789";
+char *r = q;
+p = __builtin_strcat (p, r);
+  }
+  return p;/* { dg-bogus "using dangling pointer" } */
+}
+
+char *
+bar (char *p)
+{
+  {
+char q[] = "0123456789";
+char *r = q;
+p = __builtin_strstr (p, r);
+  }
+  return p;/* { dg-bogus "using dangling pointer" } */
+}
+
+char *
+baz (char *p)
+{
+  {
+char q[] = "0123456789";
+char *r = q;
+p = __builtin_strpbrk (p, r);
+  }
+  return p;/* { dg-bogus "using dangling pointer" } */
+}

Jakub





Re: [PATCH] Update -Warray-bounds documentation [PR104355]

2022-02-14 Thread Martin Sebor via Gcc-patches

On 2/10/22 23:48, Richard Sandiford wrote:

Martin Sebor via Gcc-patches  writes:

The -Warray-bounds description in the manual is out of date in
a couple of ways.  First it claims that the option is only active
with optimization, which isn't entirely correct since at least one
instance is issued even without it.  Second, the description of
its level 2 suggests it controls the warning for all trailing
array members, when it only controls it for trailing one-element
arrays (this was made tighter in GCC 10 but we neglected to update
the manual).

In addition, the word "always" in the description of the option
is also interpreted by some as implying that every instance of
the warning is necessarily a true positive.  I've reworded
the description to hopefully avoid this misreading(*).

Finally, the generic text that talks about the interaction with
optimizations says that -Wmaybe-uninitialized is not issued unless
optimization is enabled.  That's also not accurate anymore since
at least one instance of the warning is independent of optimization
(passing uninitialized objects by reference to const arguments).

The attached changes correct these oversights.

Martin

[*] It should probably be made clearer in the generic text that
no instance of any warning, not just -Warray-bounds, should be
taken to be a definitive indication of a bug in the code.  I've
left that for later.


Yeah, maybe, but I guess it's unlikely to be useful in practice.
The chances of users happening to read a given bit of generic text
seem pretty low.

Doesn't mean we shouldn't do it of course (provided that we don't then
castigate users for having failed to notice it).


I'm sure you're right that few users go to the trouble of studying
the manual when interpreting a warning (and some not even before
submitting a problem report).




Update -Warray-bounds documentation [PR104355].

Resolves:
PR middle-end/104355 - Misleading and outdated -Warray-bounds documentation

gcc/ChangeLog:
* doc/invoke.texi (-Warray-bounds): Update documentation.


diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b49ba22df89..b7b1f47a5ce 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5641,8 +5641,10 @@ warns that an unrecognized option is present.
  
  The effectiveness of some warnings depends on optimizations also being

  enabled. For example @option{-Wsuggest-final-types} is more effective
-with link-time optimization and @option{-Wmaybe-uninitialized} does not
-warn at all unless optimization is enabled.
+with link-time optimization and some instances of other warnings may
+not be issued at all unless optimization is enabled.  While optimization
+in general improves the efficacy of control and data flow sensitive
+warnings, in some cases it may also cause false positives.
  
  @table @gcctabopt

  @item -Wpedantic
@@ -7691,20 +7693,22 @@ void f (char c, int i)
  @itemx -Warray-bounds=@var{n}
  @opindex Wno-array-bounds
  @opindex Warray-bounds
-This option is only active when @option{-ftree-vrp} is active
-(default for @option{-O2} and above). It warns about subscripts to arrays
-that are always out of bounds. This warning is enabled by @option{-Wall}.
+Warn about out of bounds subscripts or offsets into arrays. This warning
+level is enabled by @option{-Wall}.  It is the most effective when


It's not clear to me which level is “this level” here.  How about
something like “This warning is enabled at level 1…”?


Yes, good catch, that was a mistake on my part.



“It is more effective when” seems more natural to me than “It is the most
effective when”, but maybe that's just me.


-Warray-bounds doesn't do much without -ftree-vrp (it detects out-of-
bounds offsets in calls to built-ins), and does almost nothing below
-O2 (all it diagnoses at -O0 is strlen() calls with past-the-end
offsets to string constants).  But since the rest of the sentence
mention that it's not completely silent even at -O0 your words sound
good to me too.



Looks good to me otherwise FWIW.  OK with those changes if you agree and
if no-one has further comments by Monday.


Pushed now in r12-7234.

Martin



Thanks,
Richard


+@option{-ftree-vrp} is active (the default for @option{-O2} and above)
+but a subset of instances are issued even without optimization.
  
  @table @gcctabopt

  @item -Warray-bounds=1
-This is the warning level of @option{-Warray-bounds} and is enabled
+This is the default warning level of @option{-Warray-bounds} and is enabled
  by @option{-Wall}; higher levels are not, and must be explicitly requested.
  
  @item -Warray-bounds=2

-This warning level also warns about out of bounds access for
-arrays at the end of a struct and for arrays accessed through
-pointers. This warning level may give a larger number of
-false positives and is deactivated by default.
+This warning level also warns out of bounds accesses to trailing struct
+members of one-element array types (@pxref{Zero Length}) and about
+the intermedia

[PATCH] Update -Warray-bounds documentation [PR104355]

2022-02-10 Thread Martin Sebor via Gcc-patches

The -Warray-bounds description in the manual is out of date in
a couple of ways.  First it claims that the option is only active
with optimization, which isn't entirely correct since at least one
instance is issued even without it.  Second, the description of
its level 2 suggests it controls the warning for all trailing
array members, when it only controls it for trailing one-element
arrays (this was made tighter in GCC 10 but we neglected to update
the manual).

In addition, the word "always" in the description of the option
is also interpreted by some as implying that every instance of
the warning is necessarily a true positive.  I've reworded
the description to hopefully avoid this misreading(*).

Finally, the generic text that talks about the interaction with
optimizations says that -Wmaybe-uninitialized is not issued unless
optimization is enabled.  That's also not accurate anymore since
at least one instance of the warning is independent of optimization
(passing uninitialized objects by reference to const arguments).

The attached changes correct these oversights.

Martin

[*] It should probably be made clearer in the generic text that
no instance of any warning, not just -Warray-bounds, should be
taken to be a definitive indication of a bug in the code.  I've
left that for later.Update -Warray-bounds documentation [PR104355].

Resolves:
PR middle-end/104355 - Misleading and outdated -Warray-bounds documentation

gcc/ChangeLog:
	* doc/invoke.texi (-Warray-bounds): Update documentation.


diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b49ba22df89..b7b1f47a5ce 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5641,8 +5641,10 @@ warns that an unrecognized option is present.
 
 The effectiveness of some warnings depends on optimizations also being
 enabled. For example @option{-Wsuggest-final-types} is more effective
-with link-time optimization and @option{-Wmaybe-uninitialized} does not
-warn at all unless optimization is enabled.
+with link-time optimization and some instances of other warnings may
+not be issued at all unless optimization is enabled.  While optimization
+in general improves the efficacy of control and data flow sensitive
+warnings, in some cases it may also cause false positives.
 
 @table @gcctabopt
 @item -Wpedantic
@@ -7691,20 +7693,22 @@ void f (char c, int i)
 @itemx -Warray-bounds=@var{n}
 @opindex Wno-array-bounds
 @opindex Warray-bounds
-This option is only active when @option{-ftree-vrp} is active
-(default for @option{-O2} and above). It warns about subscripts to arrays
-that are always out of bounds. This warning is enabled by @option{-Wall}.
+Warn about out of bounds subscripts or offsets into arrays. This warning
+level is enabled by @option{-Wall}.  It is the most effective when
+@option{-ftree-vrp} is active (the default for @option{-O2} and above)
+but a subset of instances are issued even without optimization.
 
 @table @gcctabopt
 @item -Warray-bounds=1
-This is the warning level of @option{-Warray-bounds} and is enabled
+This is the default warning level of @option{-Warray-bounds} and is enabled
 by @option{-Wall}; higher levels are not, and must be explicitly requested.
 
 @item -Warray-bounds=2
-This warning level also warns about out of bounds access for
-arrays at the end of a struct and for arrays accessed through
-pointers. This warning level may give a larger number of
-false positives and is deactivated by default.
+This warning level also warns out of bounds accesses to trailing struct
+members of one-element array types (@pxref{Zero Length}) and about
+the intermediate results of pointer arithmetic that may yield out of
+bounds values. This warning level may give a larger number of false
+positives and is deactivated by default.
 @end table
 
 @item -Warray-compare


Re: [PATCH] handle "invisible" reference in -Wdangling-pointer (PR104436)

2022-02-10 Thread Martin Sebor via Gcc-patches

On 2/8/22 15:37, Jason Merrill wrote:

On 2/8/22 16:59, Martin Sebor wrote:

Transforming a by-value arguments to by-reference as GCC does for some
class types can trigger -Wdangling-pointer when the argument is used
to store the address of a local variable.  Since the stored value is
not accessible in the caller the warning is a false positive.

The attached patch handles this case by excluding PARM_DECLs with
the DECL_BY_REFERENCE bit set from consideration.

While testing the patch I noticed some instances of the warning are
uninitentionally duplicated as the pass runs more than once.  To avoid
that, I also introduce warning suppression into the handler for this
instance of the warning.  (There might still be others.)


The second test should verify that we do warn about returning 't' from a 
function; we don't want to ignore the DECL_BY_REFERENCE RESULT_DECL.


The indirect aggregate case isn't handled and needs more work but
since you brought it up I thought I should look into finishing it.
The attached patch #2 adds support for it.  It also incorporates
Richard's suggestion to test PARM_DECL.  Patch #2 applies on top
of patch #1 which is unchanged from the first revision.

I have retested it on x86_64-linux and by building Glibc and
Binutils + GDB.

If now is too late for the aggregate enhancement I'm okay with
deferring it until stage 1.




+  tree var = SSA_NAME_VAR (lhs_ref.ref);
+  if (DECL_BY_REFERENCE (var))
+    /* Avoid by-value arguments transformed into by-reference.  */
+    continue;


I wonder if we can we express this property of invisiref parms somewhere 
more general?  I imagine optimizations would find it useful as well. 
Could pointer_query somehow treat the reference as pointing to a 
function-local object?


I don't quite see where in the pointer_query class this would be
useful (the class also isn't used for optimization).  I could add
a helper to the access_ref class to query this property in warning
code but as this is the only potential client I'm also not sure
that's quite what you had in mind.  I'd need some guidance as to
what you're thinking of here.

Martin




I previously tried to express this by marking the reference as 
'restrict', but that was wrong 
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97474).


Jason

Subject: [PATCH 1/2] Avoid -Wdangling-pointer for by-transparent-reference
 arguments [PR104436].

This change avoids -Wdangling-pointer for by-value arguments transformed
into by-transparent-reference.

Resolves:
PR middle-end/104436 - spurious -Wdangling-pointer assigning local address to a class passed by value

gcc/ChangeLog:

	PR middle-end/104436
	* gimple-ssa-warn-access.cc (pass_waccess::check_dangling_stores):
	Check for warning suppression.  Avoid by-value arguments transformed
	into by-transparent-reference.

gcc/testsuite/ChangeLog:

	PR middle-end/104436
	* c-c++-common/Wdangling-pointer-7.c: New test.
	* g++.dg/warn/Wdangling-pointer-4.C: New test.
---
 gcc/gimple-ssa-warn-access.cc | 13 ++-
 .../c-c++-common/Wdangling-pointer-7.c| 20 +++
 .../g++.dg/warn/Wdangling-pointer-4.C | 34 +++
 3 files changed, 66 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wdangling-pointer-7.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 80d41ea4383..0c319a32b70 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4517,6 +4517,9 @@ pass_waccess::check_dangling_stores (basic_block bb,
   if (!stmt)
 	break;
 
+  if (warning_suppressed_p (stmt, OPT_Wdangling_pointer_))
+	continue;
+
   if (is_gimple_call (stmt)
 	  && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
 	/* Avoid looking before nonconst, nonpure calls since those might
@@ -4542,10 +4545,16 @@ pass_waccess::check_dangling_stores (basic_block bb,
 	}
   else if (TREE_CODE (lhs_ref.ref) == SSA_NAME)
 	{
-	  /* Avoid looking at or before stores into unknown objects.  */
 	  gimple *def_stmt = SSA_NAME_DEF_STMT (lhs_ref.ref);
 	  if (!gimple_nop_p (def_stmt))
+	/* Avoid looking at or before stores into unknown objects.  */
 	return;
+
+	  tree var = SSA_NAME_VAR (lhs_ref.ref);
+	  if (DECL_BY_REFERENCE (var))
+	/* Avoid by-value arguments transformed into by-reference.  */
+	continue;
+
 	}
   else if (TREE_CODE (lhs_ref.ref) == MEM_REF)
 	{
@@ -4578,6 +4587,8 @@ pass_waccess::check_dangling_stores (basic_block bb,
 		  "storing the address of local variable %qD in %qE",
 		  rhs_ref.ref, lhs))
 	{
+	  suppress_warning (stmt, OPT_Wdangling_pointer_);
+
 	  location_t loc = DECL_SOURCE_LOCATION (rhs_ref.ref);
 	  inform (loc, "%qD declared here", rhs_ref.ref);
 
diff --git a/gcc/testsuite/c-c++-common/Wdangling-pointer-7.c b/gcc/testsuite/c-c++-common/Wdangling-pointer-7.c
new file mode 100644
index 

Re: [PATCH] tree-optimization/104373 - early uninit diagnostic on unreachable code

2022-02-09 Thread Martin Sebor via Gcc-patches

On 2/9/22 00:12, Richard Biener wrote:

On Tue, 8 Feb 2022, Jeff Law wrote:




On 2/8/2022 12:03 AM, Richard Biener via Gcc-patches wrote:

The following improves early uninit diagnostics by computing edge
reachability using our value-numbering framework in its cheapest
mode and ignoring unreachable blocks when looking
for uninitialized uses.  To not ICE with -fdump-tree-all the
early uninit pass needs a dumpfile since VN tries to dump statistics.

For gimple-match.c at -O0 -g this causes a 2% increase in compile-time.

In theory all early diagnostic passes could benefit from a VN run but
that would require more refactoring that's not appropriate at this stage.
This patch addresses a GCC 12 diagnostic regression and also happens to
fix one XFAIL in gcc.dg/uninit-pr20644-O0.c

Bootstrapped and tested on x86_64-unknown-linux-gnu, OK for trunk?

Thanks,
Richard.

2022-02-04  Richard Biener  

  PR tree-optimization/104373
  * tree-ssa-sccvn.h (do_rpo_vn): New export exposing the
  walk kind.
  * tree-ssa-sccvn.cc (do_rpo_vn): Export, get the default
  walk kind as argument.
  (run_rpo_vn): Adjust.
  (pass_fre::execute): Likewise.
  * tree-ssa-uninit.cc (warn_uninitialized_vars): Skip
  blocks not reachable.
  (execute_late_warn_uninitialized): Mark all edges as
  executable.
  (execute_early_warn_uninitialized): Use VN to compute
  executable edges.
  (pass_data_early_warn_uninitialized): Enable a dump file,
  change dump name to warn_uninit.

  * g++.dg/warn/Wuninitialized-32.C: New testcase.
  * gcc.dg/uninit-pr20644-O0.c: Remove XFAIL.

I'm conflicted on this ;-)

I generally lean on the side of eliminating false positives in these
diagnostics.  So identifying unreachable blocks and using that to prune the
set of warnings we generate, even at -O0 is good from that point of view.

But doing something like this has many of the problems that relying on
optimizations does, even if we don't optimize away the unreachable code.
Right now the warning should be fairly stable at -O0 -- the set of diagnostics
you get isn't going to change a lot release to release which is important to
some users.   Second, at -O0 whether or not you get a warning isn't a function
of how good our unreachable code analysis might be.

This was quite a contentious topic many years ago.  So much that I dropped
some work on Wuninit on the floor as I just couldn't take the arguing.  So be
aware that you might be opening a can of worms.

So the question comes down to a design decision.   What's more important to
the end users?  Fewer false positives or better stability in the warning?  I
think the former, but there's certainly been a vocal group that prefers the
latter.


I see - I didn't think of this aspect at all but that means I have no
idea on whether it is important or not ...

In our own setup we're running into "instabilities" with optimization
when building packages that enable -Werror, so I can see shops doing
dev builds at -O0 with warnings and -Werror but drop -Werror for
optimized builds.


On the implementation side I have zero concerns.    Looking further out, ISTM
we could mark the blocks as unreachable (rather than deducing it from edge
flags).  That would make it pretty easy to mark those blocks relatively early
and allow us to suppress any middle end diagnostic occurring in an unreachable
block.


So what I had in mind is that for the set of early diagnostic passes

   PUSH_INSERT_PASSES_WITHIN (pass_build_ssa_passes)
   NEXT_PASS (pass_fixup_cfg);
   NEXT_PASS (pass_build_ssa);
   NEXT_PASS (pass_warn_printf);
   NEXT_PASS (pass_warn_nonnull_compare);
   NEXT_PASS (pass_early_warn_uninitialized);
   NEXT_PASS (pass_warn_access, /*early=*/true);

we'd run VN and keep it's lattice around (and not just the
EDGE_EXECUTABLE flags).  That would for example allow
pass_warn_nonnull_compare to see that in

void foo (void *p __attribute__((nonnull)))
{
   void *q = p;
   if (q)
 bar (q);
}

we are comparing a never NULL pointer.  Currently the q = p copy
makes it not realize this.  Likewise some constants can be
propagated this way.

Of course using the VN lattice means quite some changes in those
passes.  Even without the VN lattice having unreachable edges
marked could improve diagnostics for, say PHI nodes, if only
a single executable edge remains.

Martin, do you have any thoughts here?  Any opinion on the patch
that for now just marks (not) executable edges to prune diagnostics at
-O0?


Many middle end warnings now run at -O0.  Thanks to Ranger (and
the pointer_query solution), they can identify many of the same
problem statements as with optimization.  But for the same reason
they're also more prone to false positives for unreachable code
because DCE doesn't run at -O0.  So in my mind, identifying at
least some of it then, is a step in the right direction.

So for the avoidance of doubt, I'm in favor of both the patch and
extending the approach to other warnings.

Thanks
Martin



Thanks,

[PATCH] handle "invisible" reference in -Wdangling-pointer (PR104436)

2022-02-08 Thread Martin Sebor via Gcc-patches

Transforming a by-value arguments to by-reference as GCC does for some
class types can trigger -Wdangling-pointer when the argument is used
to store the address of a local variable.  Since the stored value is
not accessible in the caller the warning is a false positive.

The attached patch handles this case by excluding PARM_DECLs with
the DECL_BY_REFERENCE bit set from consideration.

While testing the patch I noticed some instances of the warning are
uninitentionally duplicated as the pass runs more than once.  To avoid
that, I also introduce warning suppression into the handler for this
instance of the warning.  (There might still be others.)

Tested on x86_64-linux.

MartinAvoid -Wdangling-pointer for by-transparent-reference arguments [PR104436].

Resolves:
PR middle-end/104436 - spurious -Wdangling-pointer assigning local address to a class passed by value

gcc/ChangeLog:

	PR middle-end/104436
	* gimple-ssa-warn-access.cc (pass_waccess::check_dangling_stores):
	Check for warning suppression.  Avoid by-value arguments transformed
	into by-transparent-reference.

gcc/testsuite/ChangeLog:

	PR middle-end/104436
	* c-c++-common/Wdangling-pointer-7.c: New test.
	* g++.dg/warn/Wdangling-pointer-4.C: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 80d41ea4383..0c319a32b70 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4517,6 +4517,9 @@ pass_waccess::check_dangling_stores (basic_block bb,
   if (!stmt)
 	break;
 
+  if (warning_suppressed_p (stmt, OPT_Wdangling_pointer_))
+	continue;
+
   if (is_gimple_call (stmt)
 	  && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
 	/* Avoid looking before nonconst, nonpure calls since those might
@@ -4542,10 +4545,16 @@ pass_waccess::check_dangling_stores (basic_block bb,
 	}
   else if (TREE_CODE (lhs_ref.ref) == SSA_NAME)
 	{
-	  /* Avoid looking at or before stores into unknown objects.  */
 	  gimple *def_stmt = SSA_NAME_DEF_STMT (lhs_ref.ref);
 	  if (!gimple_nop_p (def_stmt))
+	/* Avoid looking at or before stores into unknown objects.  */
 	return;
+
+	  tree var = SSA_NAME_VAR (lhs_ref.ref);
+	  if (DECL_BY_REFERENCE (var))
+	/* Avoid by-value arguments transformed into by-reference.  */
+	continue;
+
 	}
   else if (TREE_CODE (lhs_ref.ref) == MEM_REF)
 	{
@@ -4578,6 +4587,8 @@ pass_waccess::check_dangling_stores (basic_block bb,
 		  "storing the address of local variable %qD in %qE",
 		  rhs_ref.ref, lhs))
 	{
+	  suppress_warning (stmt, OPT_Wdangling_pointer_);
+
 	  location_t loc = DECL_SOURCE_LOCATION (rhs_ref.ref);
 	  inform (loc, "%qD declared here", rhs_ref.ref);
 
diff --git a/gcc/testsuite/c-c++-common/Wdangling-pointer-7.c b/gcc/testsuite/c-c++-common/Wdangling-pointer-7.c
new file mode 100644
index 000..433727dd845
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wdangling-pointer-7.c
@@ -0,0 +1,20 @@
+/* Verify -Wdangling-pointer is issued only once.
+   { dg-do compile }
+   { dg-options "-O -Wall" } */
+
+void *p;
+
+void escape_global_warn_once (void)
+{
+  int x[5];
+
+  p = [3];// { dg-regexp "\[^\n\r\]+: warning: \[^\n\r\]+ \\\[-Wdangling-pointer.?\\\]" "message" }
+}
+
+
+void escape_param_warn_once (void **p)
+{
+  int x[5];
+
+  *p = [3];   // { dg-regexp "\[^\n\r\]+: warning: \[^\n\r\]+ \\\[-Wdangling-pointer.?\\\]" "message" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C
new file mode 100644
index 000..b3d144a9e6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-4.C
@@ -0,0 +1,34 @@
+/* PR middle-end/104436 - spurious -Wdangling-pointer assigning local
+   address to a class passed by value
+   { dg-do compile }
+   { dg-options "-O1 -Wall" } */
+
+struct S
+{
+  S (void *p): p (p) { }
+  S (const S ): p (s.p) { }
+
+  void *p;
+};
+
+
+void nowarn_assign_by_value (S s)
+{
+  int i;
+  S t ();
+  s = t;// { dg-bogus "-Wdangling-pointer" }
+}
+
+void nowarn_assign_by_value_arg (S s)
+{
+  S t ();
+  s = t;// { dg-bogus "-Wdangling-pointer" }
+}
+
+
+void warn_assign_local_by_reference (S )
+{
+  int i;
+  S t ();
+  s = t;// { dg-warning "-Wdangling-pointer" }
+}


Re: [PATCH 0/3] Enable pointer_query caching throughout.

2022-02-03 Thread Martin Sebor via Gcc-patches

On 2/3/22 17:33, Martin Sebor wrote:

On 2/3/22 17:18, David Edelsohn wrote:

On Thu, Feb 3, 2022 at 6:09 PM Martin Sebor  wrote:


On 2/3/22 15:56, David Edelsohn wrote:

This series of patches has exploded memory usage and I can no longer
bootstrap GCC on AIX.

As with the Ranger problem exposed by Aldy's patch last September,
something is not freeing memory.

Even on systems where GCC still bootstrap, this excessive memory usage
severely damages GCC compile performance.


Does the change below by any chance make a difference?  (It's just
a hunch, I haven't tested it beyond quickly building stage 1 and
running a few tests.)


Hi, Martin

Thanks for the quick response.  Yes, I am able to restore bootstrap on
AIX (32 bit) with the change.


Let me finish testing it and if all goes well commit it later tonight.


Now pushed as r12-7043.

Martin



Thanks for the confirmation!

Martin



Thanks, David



Martin


diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h
index 4c725eeaf34..801a240c38d 100644
--- a/gcc/pointer-query.h
+++ b/gcc/pointer-query.h
@@ -164,9 +164,9 @@ class pointer_query
 struct cache_type
 {
   /* 1-based indices into cache.  */
-    vec indices;
+    auto_vec indices;
   /* The cache itself.  */
-    vec access_refs;
+    auto_vec access_refs;
 };

   public:






Re: [PATCH 0/3] Enable pointer_query caching throughout.

2022-02-03 Thread Martin Sebor via Gcc-patches

On 2/3/22 17:18, David Edelsohn wrote:

On Thu, Feb 3, 2022 at 6:09 PM Martin Sebor  wrote:


On 2/3/22 15:56, David Edelsohn wrote:

This series of patches has exploded memory usage and I can no longer
bootstrap GCC on AIX.

As with the Ranger problem exposed by Aldy's patch last September,
something is not freeing memory.

Even on systems where GCC still bootstrap, this excessive memory usage
severely damages GCC compile performance.


Does the change below by any chance make a difference?  (It's just
a hunch, I haven't tested it beyond quickly building stage 1 and
running a few tests.)


Hi, Martin

Thanks for the quick response.  Yes, I am able to restore bootstrap on
AIX (32 bit) with the change.


Let me finish testing it and if all goes well commit it later tonight.

Thanks for the confirmation!

Martin



Thanks, David



Martin


diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h
index 4c725eeaf34..801a240c38d 100644
--- a/gcc/pointer-query.h
+++ b/gcc/pointer-query.h
@@ -164,9 +164,9 @@ class pointer_query
 struct cache_type
 {
   /* 1-based indices into cache.  */
-vec indices;
+auto_vec indices;
   /* The cache itself.  */
-vec access_refs;
+auto_vec access_refs;
 };

   public:




Re: [PATCH 0/3] Enable pointer_query caching throughout.

2022-02-03 Thread Martin Sebor via Gcc-patches

On 2/3/22 15:56, David Edelsohn wrote:

This series of patches has exploded memory usage and I can no longer
bootstrap GCC on AIX.

As with the Ranger problem exposed by Aldy's patch last September,
something is not freeing memory.

Even on systems where GCC still bootstrap, this excessive memory usage
severely damages GCC compile performance.


Does the change below by any chance make a difference?  (It's just
a hunch, I haven't tested it beyond quickly building stage 1 and
running a few tests.)

Martin


diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h
index 4c725eeaf34..801a240c38d 100644
--- a/gcc/pointer-query.h
+++ b/gcc/pointer-query.h
@@ -164,9 +164,9 @@ class pointer_query
   struct cache_type
   {
 /* 1-based indices into cache.  */
-vec indices;
+auto_vec indices;
 /* The cache itself.  */
-vec access_refs;
+auto_vec access_refs;
   };

 public:


Re: s390: Fix bootstrap -Wformat-diag errors

2022-02-03 Thread Martin Sebor via Gcc-patches

On 2/3/22 09:45, Martin Liška wrote:

On 2/3/22 17:43, Martin Sebor wrote:

On 2/3/22 01:59, Martin Liška wrote:

On 2/3/22 09:24, Robin Dapp via Gcc-patches wrote:

Hi Martin,


Either this:

    error ("% is unknown", orig_p);

or this would be better:

    error ("attribute % is unknown", orig_p);

The %< %> directives will render it in single quotes like keywords and
identifiers.  Using %qs would render it in double quotes like a 
string,

which wouldn't be quite right.


the x86 backend will print the error message in a different format 
using

single quotes e.g.

   bla.cc:2:5: error: attribute ‘bleh’ argument ‘target’ is unknown


That's a bug in the i386 back end:
   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90524


I don't find that better to be frank but maybe it would make sense for
us to also adopt this error message style and not use a different one?
They use %qs, though - or is there an intention to also change x86's
error messages?  I guess in general it's better to have similar error
messages across targets for the same problem.

Regards
  Robin


Hello.

I've just coincidentally fixed the issue with r12-7013-g0415470c8d6620
where I use the same error format as i386 does.


The change repeats the i386 mistake in the s360 back end.  If
the error is supposed to point out that orig_p is not a valid
argument to attribute target as I believe is the case then
the new call should be:

   error ("attribute % argument %qs is unknown", orig_p);

Martin


Yeah, fixed with g:9db03cd0caf6bbde1de302bf3509dc26ca8bff2b.


Great, thank you!

Martin



Cheers,
Martin




Re: s390: Fix bootstrap -Wformat-diag errors

2022-02-03 Thread Martin Sebor via Gcc-patches

On 2/3/22 01:59, Martin Liška wrote:

On 2/3/22 09:24, Robin Dapp via Gcc-patches wrote:

Hi Martin,


Either this:

    error ("% is unknown", orig_p);

or this would be better:

    error ("attribute % is unknown", orig_p);

The %< %> directives will render it in single quotes like keywords and
identifiers.  Using %qs would render it in double quotes like a string,
which wouldn't be quite right.


the x86 backend will print the error message in a different format using
single quotes e.g.

   bla.cc:2:5: error: attribute ‘bleh’ argument ‘target’ is unknown


That's a bug in the i386 back end:
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90524


I don't find that better to be frank but maybe it would make sense for
us to also adopt this error message style and not use a different one?
They use %qs, though - or is there an intention to also change x86's
error messages?  I guess in general it's better to have similar error
messages across targets for the same problem.

Regards
  Robin


Hello.

I've just coincidentally fixed the issue with r12-7013-g0415470c8d6620
where I use the same error format as i386 does.


The change repeats the i386 mistake in the s360 back end.  If
the error is supposed to point out that orig_p is not a valid
argument to attribute target as I believe is the case then
the new call should be:

  error ("attribute % argument %qs is unknown", orig_p);

Martin


[committed] Correct typos in -Wuse-after-free description.

2022-02-02 Thread Martin Sebor via Gcc-patches

I committed r12-7009 to fix a couple of typos in the description
of the option.

https://gcc.gnu.org/pipermail/gcc-cvs/2022-February/360083.html

Martin


[PATCH 3/3] Enable pointer_query caching for -Wrestrict.

2022-02-02 Thread Martin Sebor via Gcc-patches
The third patch in the series adds a pointer_query instance to the wrestrict
pass and uses it for each invocation to check a function.

gcc/ChangeLog:

* gimple-ssa-warn-restrict.cc (class pass_wrestrict): Outline ctor.
(pass_wrestrict::m_ptr_qry): New member.
(wrestrict_walk): Rename...
(pass_wrestrict::check_block): ...to this.
(pass_wrestrict::execute): Set up and tear down pointer_query and
ranger.
(builtin_memref::builtin_memref): Change ctor argument.  Simplify.
(builtin_access::builtin_access): Same.
(builtin_access::m_ptr_qry): New member.
(check_call): Rename...
(pass_wrestrict::check_call): ...to this.
(check_bounds_or_overlap): Change argument.
* gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Same.
---
 gcc/gimple-ssa-warn-restrict.cc | 126 
 gcc/gimple-ssa-warn-restrict.h  |   2 +-
 2 files changed, 62 insertions(+), 66 deletions(-)

diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
index d1beb01fe89..72418398dad 100644
--- a/gcc/gimple-ssa-warn-restrict.cc
+++ b/gcc/gimple-ssa-warn-restrict.cc
@@ -62,46 +62,63 @@ const pass_data pass_data_wrestrict = {
 class pass_wrestrict : public gimple_opt_pass
 {
  public:
-  pass_wrestrict (gcc::context *ctxt)
-: gimple_opt_pass (pass_data_wrestrict, ctxt)
-{ }
+  pass_wrestrict (gcc::context *);
 
-  opt_pass *clone () { return new pass_wrestrict (m_ctxt); }
+  // opt_pass *clone () { return new pass_wrestrict (m_ctxt); }
 
   virtual bool gate (function *);
   virtual unsigned int execute (function *);
+
+  void check_call (gimple *);
+
+  void check_block (basic_block);
+
+  /* A pointer_query object to store information about pointers and
+ their targets in.  */
+  pointer_query m_ptr_qry;
 };
 
+pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
+  : gimple_opt_pass (pass_data_wrestrict, ctxt),
+m_ptr_qry ()
+{ }
+
 bool
 pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
 {
   return warn_array_bounds || warn_restrict || warn_stringop_overflow;
 }
 
-static void check_call (range_query *, gimple *);
-
-static void
-wrestrict_walk (range_query *query, basic_block bb)
+void
+pass_wrestrict::check_block (basic_block bb)
 {
   /* Iterate over statements, looking for function calls.  */
-  for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
-   gsi_next ())
+  for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next ())
 {
   gimple *stmt = gsi_stmt (si);
   if (!is_gimple_call (stmt))
continue;
 
-  check_call (query, stmt);
+  check_call (stmt);
 }
 }
 
 unsigned
 pass_wrestrict::execute (function *fun)
 {
-  gimple_ranger ranger;
+  /* Create a new ranger instance and associate it with FUN.  */
+  m_ptr_qry.rvals = enable_ranger (fun);
+
   basic_block bb;
   FOR_EACH_BB_FN (bb, fun)
-wrestrict_walk (, bb);
+check_block (bb);
+
+  m_ptr_qry.flush_cache ();
+
+  /* Release the ranger instance and replace it with a global ranger.
+ Also reset the pointer since calling disable_ranger() deletes it.  */
+  disable_ranger (fun);
+  m_ptr_qry.rvals = NULL;
 
   return 0;
 }
@@ -145,7 +162,7 @@ public:
  only the destination reference is.  */
   bool strbounded_p;
 
-  builtin_memref (range_query *, gimple *, tree, tree);
+  builtin_memref (pointer_query &, gimple *, tree, tree);
 
   tree offset_out_of_bounds (int, offset_int[3]) const;
 
@@ -153,7 +170,7 @@ private:
   /* Call statement to the built-in.  */
   gimple *stmt;
 
-  range_query *query;
+  pointer_query _ptr_qry;
 
   /* Ctor helper to set or extend OFFRANGE based on argument.  */
   void extend_offset_range (tree);
@@ -187,7 +204,8 @@ class builtin_access
&& detect_overlap != _access::no_overlap);
   }
 
-  builtin_access (range_query *, gimple *, builtin_memref &, builtin_memref &);
+  builtin_access (pointer_query &, gimple *,
+ builtin_memref &, builtin_memref &);
 
   /* Entry point to determine overlap.  */
   bool overlap ();
@@ -225,7 +243,7 @@ class builtin_access
a size SIZE in bytes.  If SIZE is NULL_TREE then the size is assumed
to be unknown.  STMT is the statement in which expr appears in.  */
 
-builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr,
+builtin_memref::builtin_memref (pointer_query , gimple *stmt, tree expr,
tree size)
 : ptr (expr),
   ref (),
@@ -238,7 +256,7 @@ builtin_memref::builtin_memref (range_query *query, gimple 
*stmt, tree expr,
   maxobjsize (tree_to_shwi (max_object_size ())),
   strbounded_p (),
   stmt (stmt),
-  query (query)
+  m_ptr_qry (ptrqry)
 {
   /* Unfortunately, wide_int default ctor is a no-op so array members
  of the type must be set individually.  */
@@ -257,7 +275,7 @@ builtin_memref::builtin_memref (range_query *query, gimple 
*stmt, tree expr,
   tree range[2];
   /* 

[PATCH 2/3] Enable pointer_query caching for -Warray-bounds.

2022-02-02 Thread Martin Sebor via Gcc-patches
The second patch in the series adds a pointer_query instance to the array
bounds checker object and uses it for each invocation to check a function.

gcc/ChangeLog:

* gimple-array-bounds.cc (array_bounds_checker::array_bounds_checker):
Define ctor.
(array_bounds_checker::get_value_range): Use new member.
(array_bounds_checker::check_mem_ref): Same.
* gimple-array-bounds.h (array_bounds_checker::array_bounds_checker):
Outline ctor.
(array_bounds_checker::m_ptr_query): New member.
---
 gcc/gimple-array-bounds.cc | 13 ++---
 gcc/gimple-array-bounds.h  | 10 ++
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 80c70b49607..7ec8b08c8d2 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "gimple.h"
 #include "ssa.h"
+#include "pointer-query.h"
 #include "gimple-array-bounds.h"
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
@@ -37,7 +38,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "domwalk.h"
 #include "tree-cfg.h"
 #include "attribs.h"
-#include "pointer-query.h"
+
+array_bounds_checker::array_bounds_checker (struct function *func,
+   range_query *qry)
+  : fun (func), m_ptr_qry (qry)
+{
+  /* No-op.  */
+}
 
 // This purposely returns a value_range, not a value_range_equiv, to
 // break the dependency on equivalences for this pass.
@@ -45,7 +52,7 @@ along with GCC; see the file COPYING3.  If not see
 const value_range *
 array_bounds_checker::get_value_range (const_tree op, gimple *stmt)
 {
-  return ranges->get_value_range (op, stmt);
+  return m_ptr_qry.rvals->get_value_range (op, stmt);
 }
 
 /* Try to determine the DECL that REF refers to.  Return the DECL or
@@ -401,7 +408,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
tree ref,
   axssize = wi::to_offset (access_size);
 
   access_ref aref;
-  if (!compute_objsize (ref, m_stmt, 0, , ranges))
+  if (!m_ptr_qry.get_ref (ref, m_stmt, , 0))
 return false;
 
   if (aref.offset_in_range (axssize))
diff --git a/gcc/gimple-array-bounds.h b/gcc/gimple-array-bounds.h
index d42146b87c8..eb399271da7 100644
--- a/gcc/gimple-array-bounds.h
+++ b/gcc/gimple-array-bounds.h
@@ -20,13 +20,14 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GIMPLE_ARRAY_BOUNDS_H
 #define GCC_GIMPLE_ARRAY_BOUNDS_H
 
+#include "pointer-query.h"
+
 class array_bounds_checker
 {
   friend class check_array_bounds_dom_walker;
 
 public:
-  array_bounds_checker (struct function *fun, range_query *v)
-: fun (fun), ranges (v) { }
+  array_bounds_checker (struct function *, range_query *);
   void check ();
 
 private:
@@ -38,8 +39,9 @@ private:
 
   /* Current function.  */
   struct function *fun;
-  /* Ranger instance.  */
-  range_query *ranges;
+  /* A pointer_query object to store information about pointers and
+ their targets in.  */
+  pointer_query m_ptr_qry;
   /* Current statement.  */
   gimple *m_stmt;
 };
-- 
2.34.1



[PATCH 1/3] Make pointer_query cache a private member.

2022-02-02 Thread Martin Sebor via Gcc-patches
The first patch in the series make the pointer_query cache a private
member of the class and removes the ability to create an object of it
without one, or one with an external cache.  It also simplifies existing
clients of the class that provide an external cache to avoid doing so.

gcc/ChangeLog:

* gimple-ssa-warn-access.cc (pass_waccess::pass_waccess): Remove
pointer_query cache.
* pointer-query.cc (pointer_query::pointer_query): Remove cache
argument.  Zero-initialize new cache member.
(pointer_query::get_ref): Replace cache pointer with direct access.
(pointer_query::put_ref): Same.
(pointer_query::flush_cache): Same.
(pointer_query::dump): Same.
* pointer-query.h (class pointer_query): Remove cache argument from
ctor.  Change cache pointer to cache subobject member.
* tree-ssa-strlen.cc: Remove pointer_query cache.
---
 gcc/gimple-ssa-warn-access.cc |  8 ++--
 gcc/pointer-query.cc  | 74 +++
 gcc/pointer-query.h   | 12 +++---
 gcc/tree-ssa-strlen.cc|  8 ++--
 4 files changed, 44 insertions(+), 58 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index ad5e2f4458e..4b3d2c00b03 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2137,10 +2137,9 @@ private:
   /* Return true if use follows an invalidating statement.  */
   bool use_after_inval_p (gimple *, gimple *, bool = false);
 
-  /* A pointer_query object and its cache to store information about
- pointers and their targets in.  */
+  /* A pointer_query object to store information about pointers and
+ their targets in.  */
   pointer_query m_ptr_qry;
-  pointer_query::cache_type m_var_cache;
   /* Mapping from DECLs and their clobber statements in the function.  */
   hash_map m_clobbers;
   /* A bit is set for each basic block whose statements have been assigned
@@ -2158,8 +2157,7 @@ private:
 
 pass_waccess::pass_waccess (gcc::context *ctxt)
   : gimple_opt_pass (pass_data_waccess, ctxt),
-m_ptr_qry (NULL, _var_cache),
-m_var_cache (),
+m_ptr_qry (NULL),
 m_clobbers (),
 m_bb_uids_set (),
 m_func (),
diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc
index b092ef4fbdc..afbcd0a15ea 100644
--- a/gcc/pointer-query.cc
+++ b/gcc/pointer-query.cc
@@ -1433,12 +1433,11 @@ ssa_name_limit_t::~ssa_name_limit_t ()
 }
 
 /* Default ctor.  Initialize object with pointers to the range_query
-   and cache_type instances to use or null.  */
+   instance to use or null.  */
 
-pointer_query::pointer_query (range_query *qry /* = NULL */,
- cache_type *cache /* = NULL */)
-: rvals (qry), var_cache (cache), hits (), misses (),
-  failures (), depth (), max_depth ()
+pointer_query::pointer_query (range_query *qry /* = NULL */)
+  : rvals (qry), hits (), misses (), failures (), depth (), max_depth (),
+var_cache ()
 {
   /* No op.  */
 }
@@ -1449,28 +1448,22 @@ pointer_query::pointer_query (range_query *qry /* = 
NULL */,
 const access_ref *
 pointer_query::get_ref (tree ptr, int ostype /* = 1 */) const
 {
-  if (!var_cache)
-{
-  ++misses;
-  return NULL;
-}
-
   unsigned version = SSA_NAME_VERSION (ptr);
   unsigned idx = version << 1 | (ostype & 1);
-  if (var_cache->indices.length () <= idx)
+  if (var_cache.indices.length () <= idx)
 {
   ++misses;
   return NULL;
 }
 
-  unsigned cache_idx = var_cache->indices[idx];
-  if (var_cache->access_refs.length () <= cache_idx)
+  unsigned cache_idx = var_cache.indices[idx];
+  if (var_cache.access_refs.length () <= cache_idx)
 {
   ++misses;
   return NULL;
 }
 
-  access_ref _ref = var_cache->access_refs[cache_idx];
+  const access_ref _ref = var_cache.access_refs[cache_idx];
   if (cache_ref.ref)
 {
   ++hits;
@@ -1491,17 +1484,17 @@ pointer_query::get_ref (tree ptr, gimple *stmt, 
access_ref *pref,
   const unsigned version
 = TREE_CODE (ptr) == SSA_NAME ? SSA_NAME_VERSION (ptr) : 0;
 
-  if (var_cache && version)
+  if (version)
 {
   unsigned idx = version << 1 | (ostype & 1);
-  if (idx < var_cache->indices.length ())
+  if (idx < var_cache.indices.length ())
{
- unsigned cache_idx = var_cache->indices[idx] - 1;
- if (cache_idx < var_cache->access_refs.length ()
- && var_cache->access_refs[cache_idx].ref)
+ unsigned cache_idx = var_cache.indices[idx] - 1;
+ if (cache_idx < var_cache.access_refs.length ()
+ && var_cache.access_refs[cache_idx].ref)
{
  ++hits;
- *pref = var_cache->access_refs[cache_idx];
+ *pref = var_cache.access_refs[cache_idx];
  return true;
}
}
@@ -1525,7 +1518,7 @@ void
 pointer_query::put_ref (tree ptr, const access_ref , int ostype /* = 1 */)
 {
   /* Only add populated/valid entries.  */
-  if 

[PATCH 0/3] Enable pointer_query caching throughout.

2022-02-02 Thread Martin Sebor via Gcc-patches
Richard, as we discussed(*), this patch series enables the pointer_query
cache in the remaining two passes where it's currently disabled.  Since
not using the cache is not an option anymore, the first patch in
the series makes it a private member of the pointer_query class and its
use unconditional.  It also simplifies the two passes that use it to
avoid having to install it.

Tested on x86_64-linux.

Martin

[*] For reference:
https://gcc.gnu.org/pipermail/gcc-patches/2022-January/589243.html


Re: s390: Fix bootstrap -Wformat-diag errors

2022-02-02 Thread Martin Sebor via Gcc-patches

On 2/2/22 09:35, Robin Dapp via Gcc-patches wrote:

Hi,

this fixes the s390 bootstrap errors caused by -Werror=format-diag.  It
simply splits the problematic format strings.


Either this:

  error ("% is unknown", orig_p);

or this would be better:

  error ("attribute % is unknown", orig_p);

The %< %> directives will render it in single quotes like keywords and
identifiers.  Using %qs would render it in double quotes like a string,
which wouldn't be quite right.

Martin



Bootstrapped and regtested with -march=z15.

Is it OK?

Regards
  Robin

--

gcc/ChangeLog:

 * config/s390/s390.cc (s390_valid_target_attribute_inner_p): Split
 format strings.




Re: [PATCH] declare std::array members attribute const [PR101831]

2022-02-01 Thread Martin Sebor via Gcc-patches

On 2/1/22 17:15, Jonathan Wakely wrote:

On Wed, 2 Feb 2022 at 00:13, Martin Sebor  wrote:


On 2/1/22 12:48, Jonathan Wakely wrote:

On Tue, 1 Feb 2022 at 18:54, Martin Sebor via Libstdc++
 wrote:


Passing an uninitialized object to a function that takes its argument
by const reference is diagnosed by -Wmaybe-uninitialized because most
such functions read the argument.  The exceptions are functions that
don't access the object but instead use its address to compute
a result.  This includes a number of std::array member functions such
as std::array::size() which returns the template argument N.  Such
functions may be candidates for attribute const which also avoids
the warning.  The attribute typically only benefits extern functions
that IPA cannot infer the property from, but in this case it helps
avoid the warning which runs very early on, even without optimization
or inlining.  The attached patch adds the attribute to a subset of
those member functions of std::array.  (It doesn't add it to const
member functions like cbegin() or front() that return a const_iterator
or const reference to the internal data.)

It might be possible to infer this property from inline functions
earlier on than during IPA and avoid having to annotate them explicitly.
That seems like an enhancement worth considering in the future.

Tested on x86_64-linux.

Martin


new file mode 100644
index 000..b7743adf3c9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/iterators/begin_end.cc
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+//
+// Copyright (C) 2011-2022 Free Software Foundation, Inc.

Those dates look wrong. I no longer bother putting a license text and
copyright notice on simple tests like this. It's meaningless to assert
copyright on something so trivial that doesn't do anything.



Should I take to mean that you're okay with the rest of the change
(i.e., with the notice removed)?


Yes, OK for trunk either with the notice entirely removed, or just fix
the dates (I don't think it is copied from an existing test dating
from 2011, right?)


I copied it from 23_containers/array/iterators/end_is_one_past.cc
without even looking at the dates.



Whichever you prefer.



Okay, pushed in r12-6992.

Martin


Re: [PATCH] declare std::array members attribute const [PR101831]

2022-02-01 Thread Martin Sebor via Gcc-patches

On 2/1/22 12:48, Jonathan Wakely wrote:

On Tue, 1 Feb 2022 at 18:54, Martin Sebor via Libstdc++
 wrote:


Passing an uninitialized object to a function that takes its argument
by const reference is diagnosed by -Wmaybe-uninitialized because most
such functions read the argument.  The exceptions are functions that
don't access the object but instead use its address to compute
a result.  This includes a number of std::array member functions such
as std::array::size() which returns the template argument N.  Such
functions may be candidates for attribute const which also avoids
the warning.  The attribute typically only benefits extern functions
that IPA cannot infer the property from, but in this case it helps
avoid the warning which runs very early on, even without optimization
or inlining.  The attached patch adds the attribute to a subset of
those member functions of std::array.  (It doesn't add it to const
member functions like cbegin() or front() that return a const_iterator
or const reference to the internal data.)

It might be possible to infer this property from inline functions
earlier on than during IPA and avoid having to annotate them explicitly.
That seems like an enhancement worth considering in the future.

Tested on x86_64-linux.

Martin


new file mode 100644
index 000..b7743adf3c9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/iterators/begin_end.cc
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+//
+// Copyright (C) 2011-2022 Free Software Foundation, Inc.

Those dates look wrong. I no longer bother putting a license text and
copyright notice on simple tests like this. It's meaningless to assert
copyright on something so trivial that doesn't do anything.



Should I take to mean that you're okay with the rest of the change
(i.e., with the notice removed)?

Martin


[PATCH] adjust warn-access pass placement [PR104260]

2022-02-01 Thread Martin Sebor via Gcc-patches

The attached patch adjusts the placement of the warn-access pass
as the two of you suggested in the bug.  Please let me know if
this is good to commit or if you want me to make some other tweaks.

The patch passes tests in an x86_64-linux bootstrap.

MartinPR middle-end/104260 - Misplaced waccess3 pass

gcc/ChangeLog:

	PR 104260
	* passes.def (pass_warn_access): Adjust pass placement.

diff --git a/gcc/passes.def b/gcc/passes.def
index 3e75de46c23..f7718181038 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -60,10 +60,10 @@ along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_warn_printf);
   NEXT_PASS (pass_warn_nonnull_compare);
   NEXT_PASS (pass_early_warn_uninitialized);
+  NEXT_PASS (pass_warn_access, /*early=*/true);
   NEXT_PASS (pass_ubsan);
   NEXT_PASS (pass_nothrow);
   NEXT_PASS (pass_rebuild_cgraph_edges);
-  NEXT_PASS (pass_warn_access, /*early=*/true);
   POP_INSERT_PASSES ()
 
   NEXT_PASS (pass_local_optimization_passes);
@@ -428,9 +428,9 @@ along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_gimple_isel);
   NEXT_PASS (pass_harden_conditional_branches);
   NEXT_PASS (pass_harden_compares);
+  NEXT_PASS (pass_warn_access, /*early=*/false);
   NEXT_PASS (pass_cleanup_cfg_post_optimizing);
   NEXT_PASS (pass_warn_function_noreturn);
-  NEXT_PASS (pass_warn_access, /*early=*/false);
 
   NEXT_PASS (pass_expand);
 


[PATCH] declare std::array members attribute const [PR101831]

2022-02-01 Thread Martin Sebor via Gcc-patches

Passing an uninitialized object to a function that takes its argument
by const reference is diagnosed by -Wmaybe-uninitialized because most
such functions read the argument.  The exceptions are functions that
don't access the object but instead use its address to compute
a result.  This includes a number of std::array member functions such
as std::array::size() which returns the template argument N.  Such
functions may be candidates for attribute const which also avoids
the warning.  The attribute typically only benefits extern functions
that IPA cannot infer the property from, but in this case it helps
avoid the warning which runs very early on, even without optimization
or inlining.  The attached patch adds the attribute to a subset of
those member functions of std::array.  (It doesn't add it to const
member functions like cbegin() or front() that return a const_iterator
or const reference to the internal data.)

It might be possible to infer this property from inline functions
earlier on than during IPA and avoid having to annotate them explicitly.
That seems like an enhancement worth considering in the future.

Tested on x86_64-linux.

MartinDeclare std::array members with attribute const [PR101831].

Resolves:
PR libstdc++/101831 - Spurious maybe-uninitialized warning on std::array::size

libstdc++-v3/ChangeLog:

	* include/std/array (begin): Declare const member function attribute
	const.
	(end, rbegin, rend, size, max_size, empty, data): Same.
	* testsuite/23_containers/array/capacity/empty.cc: Add test cases.
	* testsuite/23_containers/array/capacity/max_size.cc: Same.
	* testsuite/23_containers/array/capacity/size.cc: Same.
	* testsuite/23_containers/array/iterators/begin_end.cc: New test.

diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index b4d8fc81a52..e45143fb329 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -127,7 +127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { std::swap_ranges(begin(), end(), __other.begin()); }
 
   // Iterators.
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   _GLIBCXX17_CONSTEXPR iterator
   begin() noexcept
   { return iterator(data()); }
@@ -137,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   begin() const noexcept
   { return const_iterator(data()); }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   _GLIBCXX17_CONSTEXPR iterator
   end() noexcept
   { return iterator(data() + _Nm); }
@@ -147,7 +147,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   end() const noexcept
   { return const_iterator(data() + _Nm); }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   _GLIBCXX17_CONSTEXPR reverse_iterator
   rbegin() noexcept
   { return reverse_iterator(end()); }
@@ -157,7 +157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   rbegin() const noexcept
   { return const_reverse_iterator(end()); }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   _GLIBCXX17_CONSTEXPR reverse_iterator
   rend() noexcept
   { return reverse_iterator(begin()); }
@@ -188,15 +188,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { return const_reverse_iterator(begin()); }
 
   // Capacity.
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   constexpr size_type
   size() const noexcept { return _Nm; }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   constexpr size_type
   max_size() const noexcept { return _Nm; }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   constexpr bool
   empty() const noexcept { return size() == 0; }
 
@@ -278,7 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  	   : _AT_Type::_S_ref(_M_elems, 0);
   }
 
-  [[__nodiscard__]]
+  [[__gnu__::__const__, __nodiscard__]]
   _GLIBCXX17_CONSTEXPR pointer
   data() noexcept
   { return _AT_Type::_S_ptr(_M_elems); }
diff --git a/libstdc++-v3/testsuite/23_containers/array/capacity/empty.cc b/libstdc++-v3/testsuite/23_containers/array/capacity/empty.cc
index 3f3f282ad9d..cecbae39e45 100644
--- a/libstdc++-v3/testsuite/23_containers/array/capacity/empty.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/capacity/empty.cc
@@ -40,8 +40,26 @@ test01()
   }
 }
 
+#pragma GCC push_options
+#pragma GCC optimize "0"
+
+void
+test02()
+{
+  {
+const size_t len = 3;
+typedef std::array array_type;
+array_type a;
+
+VERIFY( a.empty() == false );// { dg-bogus "-Wmaybe-uninitialized"
+  }
+}
+
+#pragma GCC pop_options
+
 int main()
 {
   test01();
+  test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/capacity/max_size.cc b/libstdc++-v3/testsuite/23_containers/array/capacity/max_size.cc
index 0e000258530..4629316161d 100644
--- a/libstdc++-v3/testsuite/23_containers/array/capacity/max_size.cc
+++ 

Re: [PATCH] enable -Winvalid-memory-order for C++ [PR99612]

2022-01-27 Thread Martin Sebor via Gcc-patches

On 1/27/22 16:47, Andrew Pinski wrote:

On Wed, Dec 8, 2021 at 8:50 AM Martin Sebor via Gcc-patches
 wrote:


Even with -Wno-system-headers enabled, the -Winvalid-memory-order
code tries to make sure calls to atomic functions with invalid
memory orders are diagnosed even though the C atomic functions
are defined as macros in the  system header.
The warning triggers at all optimization levels, including -O0.

Independently, the core diagnostic enhancements implemented earlier
this year (the warning group control) enable warnings for functions
defined in system headers that are inlined into user code.  This
was done for similar reason as above: because it's desirable to
diagnose invalid calls made from user code to system functions
(e.g., buffer overflows, invalid or mismatched deallocations,
etc.)

However, the C macro solution interferes with the code diagnostic
changes and prevents the invalid memory model warnings from being
issued for the same problems in C++.  In addition, because C++
atomics are ordinary (inline) functions that call the underlying
__atomic_xxx built-ins, the invalid memory orders can only be
detected with both inlining and constant propagation enabled.

The attached patch removes these limitations and enables
-Winvalid-memory-order to trigger even for C++ std::atomic,
(almost) just like it does in C, at all optimization levels
including -O0.

To make that possible I had to move -Winvalid-memory-order from
builtins.c to a GIMPLE pass where it can use context-sensitive
range info at -O0, instead of relying on constant propagation
(only available at -O1 and above).  Although the same approach
could be used to emit better object code for C++ atomics at -O0
(i.e., use the right memory order instead of dropping to seq_cst),
this patch doesn't do that.)

In addition to enabling the warning I've also enhanced it to
include the memory models involved in the diagnosed call (both
the problem ones and the viable alternatives).

Tested on x86_64-linux.

Jonathan, I CC you for two reasons: a) because this solution
is based on your (as well as my own) preference for handling
C++ system headers, and because of our last week's discussion
of the false positives in std::string resulting from the same
choice there.

I don't anticipate this change to lead to the same fallout
because it's unlikely for GCC to synthesize invalid memory
orders out of thin air; and b) because the current solution
can only detect the problems in calls to atomic functions at
-O0 that are declared with attribute always_inline.  This
includes member functions defined in the enclosing atomic
class but not namespace-scope functions.  To make
the detection possible those would also have to be
always_inline.  If that's a change you'd like to see I can
look into making it happen.


This causes gcc.target/aarch64/atomic-inst-cas.c testcase to fail on
aarch64-linux-gnu. We warn now even for the case where we don't have
undefined behavior.
In the sense the code checks the success and failure memory model
before calling __atomic_compare_exchange_n.
Testcase:
int test_cas_atomic_relaxed_consume_char (char* val, char* foo, char* bar) {
  int model_s = 0;
  int model_f = 1;
  if (model_s < model_f) return 0;
  if (model_f == 3 || model_f == 4) return 0;
  return __atomic_compare_exchange_n (val, foo, bar, 0, model_s, model_f);
}

Do we really want to warn about this case and other cases where we
check the memory model before calling __atomic_compare_exchange_n?
That is, do we want to warn this early in the optimization pipeline
and even without flow control checks?


The warning runs very early intentionally: to detect the same
misuses in C++ as in C, without optimization.  (In C++, constant
memory models become variables because the C++ atomics functions
are wrappers around the built-ins.)

In practice, I'd expect most calls to atomic functions to be made
with constant memory models, and code like in the test case above
to be uncommon, so I think the choice of warning at -O0 was
the right one.

Martin


[PATCH] constrain PHI handling in -Wuse-after-free (PR104232)

2022-01-27 Thread Martin Sebor via Gcc-patches

The indiscriminate PHI handling by -Wuse-after-free has caused
the false positive reported in PR 104232.  The attached patch
refines the handling to only consider PHIs all of whose operands
refer to the same object and disregard the rest.

Tested on x86_64-linux and by compiling a few toolchain projects,
including Glibc and Binutils/GDB, to verify the absence of false
positives.

MartinConstrain PHI handling in -Wuse-after-free [PR104232].

Resolves:
PR middle-end/104232 - spurious -Wuse-after-free after conditional free

gcc/ChangeLog:

	PR middle-end/104232
	* gimple-ssa-warn-access.cc (pointers_related_p): Add argument.
	Handle PHIs.  Add a synonymous overload.
	(pass_waccess::check_pointer_uses): Call pointers_related_p.

gcc/testsuite/ChangeLog:

	PR middle-end/104232
	* g++.dg/warn/Wuse-after-free4.C: New test.
	* gcc.dg/Wuse-after-free-2.c: New test.
	* gcc.dg/Wuse-after-free-3.c: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 3dcaf4230b8..ad5e2f4458e 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4080,7 +4080,8 @@ maybe_warn_mismatched_realloc (tree ptr, gimple *realloc_stmt, gimple *stmt)
either don't or their relationship cannot be determined.  */
 
 static bool
-pointers_related_p (gimple *stmt, tree p, tree q, pointer_query )
+pointers_related_p (gimple *stmt, tree p, tree q, pointer_query ,
+		auto_bitmap )
 {
   if (!ptr_derefs_may_alias_p (p, q))
 return false;
@@ -4093,7 +4094,47 @@ pointers_related_p (gimple *stmt, tree p, tree q, pointer_query )
it involves a self-referential PHI.  Return a conservative result.  */
 return false;
 
-  return pref.ref == qref.ref;
+  if (pref.ref == qref.ref)
+return true;
+
+  /* If either pointer is a PHI, iterate over all its operands and
+ return true if they're all related to the other pointer.  */
+  tree ptr = q;
+  unsigned version;
+  gphi *phi = pref.phi ();
+  if (phi)
+version = SSA_NAME_VERSION (pref.ref);
+  else
+{
+  phi = qref.phi ();
+  if (!phi)
+	return false;
+
+  ptr = p;
+  version = SSA_NAME_VERSION (qref.ref);
+}
+
+  if (!bitmap_set_bit (visited, version))
+return true;
+
+  unsigned nargs = gimple_phi_num_args (phi);
+  for (unsigned i = 0; i != nargs; ++i)
+{
+  tree arg = gimple_phi_arg_def (phi, i);
+  if (!pointers_related_p (stmt, arg, ptr, qry, visited))
+	return false;
+}
+
+  return true;
+}
+
+/* Convenience wrapper for the above.  */
+
+static bool
+pointers_related_p (gimple *stmt, tree p, tree q, pointer_query )
+{
+  auto_bitmap visited;
+  return pointers_related_p (stmt, p, q, qry, visited);
 }
 
 /* For a STMT either a call to a deallocation function or a clobber, warn
@@ -4192,7 +4233,12 @@ pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
 	{
 	  if (gimple_code (use_stmt) == GIMPLE_PHI)
 		{
+		  /* Only add a PHI result to POINTERS if all its
+		 operands are related to PTR, otherwise continue.  */
 		  tree lhs = gimple_phi_result (use_stmt);
+		  if (!pointers_related_p (stmt, lhs, ptr, m_ptr_qry))
+		continue;
+
 		  if (TREE_CODE (lhs) == SSA_NAME)
 		{
 		  pointers.safe_push (lhs);
diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free4.C b/gcc/testsuite/g++.dg/warn/Wuse-after-free4.C
new file mode 100644
index 000..599d9bfe3c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free4.C
@@ -0,0 +1,27 @@
+/* PR middle-end/104232 - spurious -Wuse-after-free after conditional free
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+char* f (void);
+
+struct A
+{
+  char *p;
+  A (): p () { }
+  ~A ()
+  {
+__builtin_free (p);   // { dg-bogus "-Wuse-after-free" }
+  }
+};
+
+int test_no_warn (void)
+{
+  A px, qx;
+
+  qx.p = f ();
+  if (!qx.p)
+return 0;
+
+  px.p = f ();
+  return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/Wuse-after-free-2.c b/gcc/testsuite/gcc.dg/Wuse-after-free-2.c
new file mode 100644
index 000..9f7ed4529f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wuse-after-free-2.c
@@ -0,0 +1,115 @@
+/* PR middle-end/104232 - spurious -Wuse-after-free after conditional free
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void free (void*);
+
+void sink (void*);
+
+void nowarn_cond_2 (char *p0, char *q0, int i)
+{
+  char *r = i ? p0 : q0;
+
+  free (p0);
+
+  /* The use of a PHI operand could be diagnosed using the "maybe" form
+ of the warning at level 2 but it's not done.  If it ever changes
+ this test and those below will need to be updated.  */
+  sink (r);
+}
+
+void nowarn_cond_2_null (char *p0, int i)
+{
+  char *r = i ? p0 : 0;
+
+  free (p0);
+  sink (r);
+}
+
+void nowarn_cond_3 (char *p0, char *q0, int i)
+{
+  char *r = i < 0 ? p0 - 1 : 0 < i ? p0 + 1 : q0;
+
+  free (p0);
+  sink (r);
+}
+
+void nowarn_cond_3_null (char *p0, int i)
+{
+  char *r = i < 0 ? p0 - 1 : 0 < i ? p0 + 1 : 0;
+
+  free (p0);
+  sink (r);
+}
+
+void 

Re: [PATCH] warn-access: Prevent -Wuse-after-free on ARM [PR104213]

2022-01-26 Thread Martin Sebor via Gcc-patches

On 1/26/22 08:24, Jason Merrill via Gcc-patches wrote:

On 1/25/22 18:33, Marek Polacek wrote:

Here, -Wuse-after-free warns about using 'this' which, on ARM, cdtors
return, as mandated by the EABI.  To be entirely correct, it only
requires it for C1 and C2 ctors and D2 and D1 dtors, but I don't feel
like changing that now and possibly running into issues later on.

This patch uses suppress_warning on 'this' for certain cdtor_returns_this
cases in the C++ FE, and then warn_invalid_pointer makes use of this
information and doesn't warn.

In my first attempt I tried suppress_warning the MODIFY_EXPR or 
RETURN_EXPR

we build in build_delete_destructor_body, but the complication is that
the suppress_warning bits don't always survive gimplification; see e.g.
gimplify_modify_expr where we do

  6130   if (COMPARISON_CLASS_P (*from_p))
  6131 copy_warning (assign, *from_p);

but here we're not dealing with a comparison.  Removing that check
regresses uninit-pr74762.C.  Adding copy_warning (assign, *expr_p)
regresses c-c++-common/uninit-17.c.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK if Martin doesn't have any suggestions.


Nothing further from me.

Thanks
Martin




PR target/104213

gcc/cp/ChangeLog:

* decl.cc (finish_constructor_body): Suppress -Wuse-after-free.
(finish_destructor_body): Likewise.
* optimize.cc (build_delete_destructor_body): Likewise.

gcc/ChangeLog:

* gimple-ssa-warn-access.cc (pass_waccess::warn_invalid_pointer): 
Don't

warn when the SSA_NAME_VAR of REF has supressed -Wuse-after-free.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wuse-after-free2.C: New test.
---
  gcc/cp/decl.cc   |  2 ++
  gcc/cp/optimize.cc   |  1 +
  gcc/gimple-ssa-warn-access.cc    | 14 +++---
  gcc/testsuite/g++.dg/warn/Wuse-after-free2.C | 10 ++
  4 files changed, 24 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wuse-after-free2.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 22d3dd1e2ad..6534a7fd320 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17315,6 +17315,7 @@ finish_constructor_body (void)
    add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
    val = DECL_ARGUMENTS (current_function_decl);
+  suppress_warning (val, OPT_Wuse_after_free);
    val = build2 (MODIFY_EXPR, TREE_TYPE (val),
  DECL_RESULT (current_function_decl), val);
    /* Return the address of the object.  */
@@ -17408,6 +17409,7 @@ finish_destructor_body (void)
    tree val;
    val = DECL_ARGUMENTS (current_function_decl);
+  suppress_warning (val, OPT_Wuse_after_free);
    val = build2 (MODIFY_EXPR, TREE_TYPE (val),
  DECL_RESULT (current_function_decl), val);
    /* Return the address of the object.  */
diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
index 4ad3f1dc9aa..13ab8b7361e 100644
--- a/gcc/cp/optimize.cc
+++ b/gcc/cp/optimize.cc
@@ -166,6 +166,7 @@ build_delete_destructor_body (tree delete_dtor, 
tree complete_dtor)

    if (targetm.cxx.cdtor_returns_this ())
  {
    tree val = DECL_ARGUMENTS (delete_dtor);
+  suppress_warning (val, OPT_Wuse_after_free);
    val = build2 (MODIFY_EXPR, TREE_TYPE (val),
  DECL_RESULT (delete_dtor), val);
    add_stmt (build_stmt (0, RETURN_EXPR, val));
diff --git a/gcc/gimple-ssa-warn-access.cc 
b/gcc/gimple-ssa-warn-access.cc

index 8bc33eeb6fa..484bcd34c25 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -3880,9 +3880,17 @@ pass_waccess::warn_invalid_pointer (tree ref, 
gimple *use_stmt,

  bool maybe, bool equality /* = false */)
  {
    /* Avoid printing the unhelpful "" in the diagnostics.  */
-  if (ref && TREE_CODE (ref) == SSA_NAME
-  && (!SSA_NAME_VAR (ref) || DECL_ARTIFICIAL (SSA_NAME_VAR (ref
-    ref = NULL_TREE;
+  if (ref && TREE_CODE (ref) == SSA_NAME)
+    {
+  tree var = SSA_NAME_VAR (ref);
+  if (!var)
+    ref = NULL_TREE;
+  /* Don't warn for cases like when a cdtor returns 'this' on 
ARM.  */

+  else if (warning_suppressed_p (var, OPT_Wuse_after_free))
+    return;
+  else if (DECL_ARTIFICIAL (var))
+    ref = NULL_TREE;
+    }
    location_t use_loc = gimple_location (use_stmt);
    if (use_loc == UNKNOWN_LOCATION)
diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C 
b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C

new file mode 100644
index 000..6d5f2bf01b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C
@@ -0,0 +1,10 @@
+// PR target/104213
+// { dg-do compile }
+// { dg-options "-Wuse-after-free" }
+
+class C
+{
+    virtual ~C();
+};
+
+C::~C() {} // { dg-bogus "used after" }

base-commit: aeac414923aa1e87986c7fc6f9b921d89a9b86cf






Re: [PATCH] warn-access: Prevent -Wuse-after-free on ARM [PR104213]

2022-01-25 Thread Martin Sebor via Gcc-patches

On 1/25/22 16:33, Marek Polacek via Gcc-patches wrote:

Here, -Wuse-after-free warns about using 'this' which, on ARM, cdtors
return, as mandated by the EABI.  To be entirely correct, it only
requires it for C1 and C2 ctors and D2 and D1 dtors, but I don't feel
like changing that now and possibly running into issues later on.

This patch uses suppress_warning on 'this' for certain cdtor_returns_this
cases in the C++ FE, and then warn_invalid_pointer makes use of this
information and doesn't warn.

In my first attempt I tried suppress_warning the MODIFY_EXPR or RETURN_EXPR
we build in build_delete_destructor_body, but the complication is that
the suppress_warning bits don't always survive gimplification; see e.g.
gimplify_modify_expr where we do

  6130   if (COMPARISON_CLASS_P (*from_p))
  6131 copy_warning (assign, *from_p);

but here we're not dealing with a comparison.  Removing that check
regresses uninit-pr74762.C.  Adding copy_warning (assign, *expr_p)
regresses c-c++-common/uninit-17.c.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


Thanks for picking this up!

My only concern with suppressing the warning for the pointer rather
than just for the return statement is that it not lead to false
negatives.  I played with the patch a little, trying to trigger one
but couldn't so it might be unfounded.  Still, I'd expect targeting
the statement to be a simpler change (the warning already checks
for the suppression bit on the statement).  Did you try it?

For reference, one of the test cases I tried is below.  It would
be good to  add it to the test suite to make sure the bug is caught
(there's a duplicate warning there that should at some point get
squashed).

struct A
{
  virtual ~A ();
  void f ();
};

A::~A ()
{
  operator delete (this);
  f ();
}

Martin



PR target/104213

gcc/cp/ChangeLog:

* decl.cc (finish_constructor_body): Suppress -Wuse-after-free.
(finish_destructor_body): Likewise.
* optimize.cc (build_delete_destructor_body): Likewise.

gcc/ChangeLog:

* gimple-ssa-warn-access.cc (pass_waccess::warn_invalid_pointer): Don't
warn when the SSA_NAME_VAR of REF has supressed -Wuse-after-free.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wuse-after-free2.C: New test.
---
  gcc/cp/decl.cc   |  2 ++
  gcc/cp/optimize.cc   |  1 +
  gcc/gimple-ssa-warn-access.cc| 14 +++---
  gcc/testsuite/g++.dg/warn/Wuse-after-free2.C | 10 ++
  4 files changed, 24 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wuse-after-free2.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 22d3dd1e2ad..6534a7fd320 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17315,6 +17315,7 @@ finish_constructor_body (void)
add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
  
val = DECL_ARGUMENTS (current_function_decl);

+  suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object.  */
@@ -17408,6 +17409,7 @@ finish_destructor_body (void)
tree val;
  
val = DECL_ARGUMENTS (current_function_decl);

+  suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object.  */
diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
index 4ad3f1dc9aa..13ab8b7361e 100644
--- a/gcc/cp/optimize.cc
+++ b/gcc/cp/optimize.cc
@@ -166,6 +166,7 @@ build_delete_destructor_body (tree delete_dtor, tree 
complete_dtor)
if (targetm.cxx.cdtor_returns_this ())
  {
tree val = DECL_ARGUMENTS (delete_dtor);
+  suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
  DECL_RESULT (delete_dtor), val);
add_stmt (build_stmt (0, RETURN_EXPR, val));
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 8bc33eeb6fa..484bcd34c25 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -3880,9 +3880,17 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple 
*use_stmt,
bool maybe, bool equality /* = false */)
  {
/* Avoid printing the unhelpful "" in the diagnostics.  */
-  if (ref && TREE_CODE (ref) == SSA_NAME
-  && (!SSA_NAME_VAR (ref) || DECL_ARTIFICIAL (SSA_NAME_VAR (ref
-ref = NULL_TREE;
+  if (ref && TREE_CODE (ref) == SSA_NAME)
+{
+  tree var = SSA_NAME_VAR (ref);
+  if (!var)
+   ref = NULL_TREE;
+  /* Don't warn for cases like when a cdtor returns 'this' on ARM.  */
+  else if (warning_suppressed_p (var, OPT_Wuse_after_free))
+   return;
+  else if (DECL_ARTIFICIAL (var))
+   ref = NULL_TREE;
+}
  

Re: [PATCH] avoid recomputing PHI results after failure (PR 104203)

2022-01-25 Thread Martin Sebor via Gcc-patches

On 1/25/22 04:15, Richard Biener wrote:

On Mon, Jan 24, 2022 at 11:55 PM Martin Sebor  wrote:


The pointer_query algorithm fails when it's unable to determine
the provenance of an pointer SSA variable.  A failure prevents it
from making a record of the variable in the cache.  Although this
doesn't happen often, one common cause of failures is PHI nodes:
e.g., because one of its arguments references the PHI itself, or
an undefined variable.  Because a failed SSA_NAME isn't added to
the cache, the computation that led up to its failure is repeated
on each interesting use of the variable. This is computationally
wasteful and can cause excessive CPU usage in pathological cases
like in the test case in PR 104203.

To avoid the problem the attached patch changes the logic for PHI
arguments and nodes to cache the most conservative result on such
a failure.  It treats such a pointer as pointing into the middle
of an object of maximum size (same as under some other conditions).

In addition, the patch also adds a new timer variable to
the warn_access pass to make these problems easier in the future
to track down.


LGTM.


Committed in r12-6869.




There are a number of other conditions under which point_query
fails.  Even though the same approach could be used to replace
all those, I did not make the change in this patch.


It's probably worth fixing them.  Btw, I wonder whether caching
fails as true fails would work as well though caching a conservative
answer of course is fine.


That's another approach: add a bitset and set a bit for each SSA
variable for which the lookup failed (or didn't find anything
interesting).  It would save space in the cache.  I didn't use
it because it would require more churn in the code, but it's
something to consider in the future (the cache itself could
stand to be further split up, with pointer offsets in one and
sizes in another).




Tested on x86_64-linux.

Martin

PS This solution relies on the pointer_query instance having caching
enabled.  Two warning passes run without a cache: -Warray-bounds in
VRP and -Wrestrict in the wrestrict pass.  I can look into enabling
it for GCC 12 if there's concern that they might be impacted.


Please.  There is IMHO no reason to not use the cache - for PHIs
you can run into the same PHI arg def from multiple edges and thus
you'll do unnecessary work even when you just do a single query
for the toplevel API.


Let me post a patch with that.

Martin



Richard.




[committed] remove duplicate block from pointer_query::dump

2022-01-24 Thread Martin Sebor via Gcc-patches

The pointer_query::dump() function contains a duplicate block of
code that does the same thing as a prior block, just a little
differently.  I removed the code after testing it on x86_linux.

The committed change is below for reference:
https://gcc.gnu.org/pipermail/gcc-cvs/2022-January/359756.html

Martin


[PATCH] avoid recomputing PHI results after failure (PR 104203)

2022-01-24 Thread Martin Sebor via Gcc-patches

The pointer_query algorithm fails when it's unable to determine
the provenance of an pointer SSA variable.  A failure prevents it
from making a record of the variable in the cache.  Although this
doesn't happen often, one common cause of failures is PHI nodes:
e.g., because one of its arguments references the PHI itself, or
an undefined variable.  Because a failed SSA_NAME isn't added to
the cache, the computation that led up to its failure is repeated
on each interesting use of the variable. This is computationally
wasteful and can cause excessive CPU usage in pathological cases
like in the test case in PR 104203.

To avoid the problem the attached patch changes the logic for PHI
arguments and nodes to cache the most conservative result on such
a failure.  It treats such a pointer as pointing into the middle
of an object of maximum size (same as under some other conditions).

In addition, the patch also adds a new timer variable to
the warn_access pass to make these problems easier in the future
to track down.

There are a number of other conditions under which point_query
fails.  Even though the same approach could be used to replace
all those, I did not make the change in this patch.

Tested on x86_64-linux.

Martin

PS This solution relies on the pointer_query instance having caching
enabled.  Two warning passes run without a cache: -Warray-bounds in
VRP and -Wrestrict in the wrestrict pass.  I can look into enabling
it for GCC 12 if there's concern that they might be impacted.PR tree-optimization/104203 - huge compile-time regression in pointer_query


gcc/ChangeLog:

	PR tree-optimization/104203
	* gimple-ssa-warn-access.cc (pass_data pass_data_waccess): Use
	TV_WARN_ACCESS.
	* pointer-query.cc (access_ref::merge_ref): Change return type.
	Convert failure to a conservative success.
	(access_ref::get_ref): Adjust to the change above.  Short-circuit
	PHI evaluation after first failure turned into conservative success.
	* pointer-query.h (access_ref::merge_ref): Change return type.
	* timevar.def (TV_WARN_ACCESS): New timer variable.

diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc
index a61ac8968f5..b092ef4fbdc 100644
--- a/gcc/pointer-query.cc
+++ b/gcc/pointer-query.cc
@@ -629,7 +629,7 @@ access_ref::phi () const
ARG refers to the null pointer.  Return true on success and false
on failure.  */
 
-bool
+void
 access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt,
 		   int ostype, bool skip_null,
 		   ssa_name_limit_t , pointer_query )
@@ -637,8 +637,16 @@ access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt,
   access_ref aref;
   if (!compute_objsize_r (arg, stmt, false, ostype, , snlim, )
   || aref.sizrng[0] < 0)
-/* This may be a PHI with all null pointer arguments.  */
-return false;
+{
+  /* This may be a PHI with all null pointer arguments.  Handle it
+	 conservatively by setting all properties to the most permissive
+	 values. */
+  base0 = false;
+  offrng[0] = offrng[1] = 0;
+  add_max_offset ();
+  set_max_size_range ();
+  return;
+}
 
   if (all_refs)
 {
@@ -675,13 +683,13 @@ access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt,
   if (arg_known_size)
 	sizrng[0] = aref.sizrng[0];
 
-  return true;
+  return;
 }
 
   /* Disregard null pointers in PHIs with two or more arguments.
  TODO: Handle this better!  */
   if (nullp)
-return true;
+return;
 
   const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize);
 
@@ -717,7 +725,7 @@ access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt,
   sizrng[0] = minsize;
   parmarray = merged_parmarray;
 
-  return true;
+  return;
 }
 
 /* Determine and return the largest object to which *THIS refers.  If
@@ -755,14 +763,12 @@ access_ref::get_ref (vec *all_refs,
 
 	  access_ref aref;
 	  tree arg1 = gimple_assign_rhs1 (def_stmt);
-	  if (!aref.merge_ref (all_refs, arg1, def_stmt, ostype, false,
-			   *psnlim, *qry))
-	return NULL_TREE;
+	  aref.merge_ref (all_refs, arg1, def_stmt, ostype, false,
+			  *psnlim, *qry);
 
 	  tree arg2 = gimple_assign_rhs2 (def_stmt);
-	  if (!aref.merge_ref (all_refs, arg2, def_stmt, ostype, false,
-			   *psnlim, *qry))
-	return NULL_TREE;
+	  aref.merge_ref (all_refs, arg2, def_stmt, ostype, false,
+			  *psnlim, *qry);
 
 	  if (pref && pref != this)
 	{
@@ -801,16 +807,24 @@ access_ref::get_ref (vec *all_refs,
   phi_ref = *pref;
 }
 
+  const offset_int maxobjsize = wi::to_offset (max_object_size ());
   const unsigned nargs = gimple_phi_num_args (phi_stmt);
   for (unsigned i = 0; i < nargs; ++i)
 {
   access_ref phi_arg_ref;
   bool skip_null = i || i + 1 < nargs;
   tree arg = gimple_phi_arg_def (phi_stmt, i);
-  if (!phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null,
-			  *psnlim, *qry))
-	return NULL_TREE;
+  phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null,
+			 *psnlim, *qry);
+
+   

[PATCH v2] constrain conservative string lengths to array sizes [PR104119]

2022-01-20 Thread Martin Sebor via Gcc-patches

The updated patch ensures the tighter bound isn't used to compute
the sprintf result and adds a test to verify that.  (This is messy
in the strlen/sprintf pass and should be cleaned up to avoid this
mistake in the future.)

Rested on x86_64-linux.

On 1/19/22 18:20, Martin Sebor wrote:

The attached patch suppresses a class of unexpected -Wformat-overflow
(and -truncation) warnings introduced as a result of better range info
with the integration of the strlen pass with Ranger.

The sprintf warning code relies on the strlen pass data to determine
the lengths of string arguments to %s directives.  When the data for
a string are present, such as after a strlen call, the length can be
either a constant or, in the case of interest, a range (including
[N, PTRDIFF_MAX - 2] for a string of unbounded length).  When absent
because no string call has been seen yet, the string length is
considered to be bounded by the size of the array it's stored in.
This constrains the maximum number of bytes output by the %s directive
and reduces false positives.

The problem this patch addresses is that in the interesting case there
is no logic similar to the last ("no data") case, and so the maximum
number of bytes can be in excess of the size of the array.  The patch
does it by computing the size of the object (or member) in which
the string is stored and using its size minus 1 as the upper bound
on the length.  To do that, I had to adjust the APIs to pass in
the pointer_query instance of the range_query.  The meat of the change
is in the new get_maxbound() function.

There might be opportunities to do better still.  I'll try to look
into them if I still have time.

Tested on x86_64-linux.

Martin
Constrain conservative string lengths to array sizes [PR104119].

Resolves:
PR tree-optimization/104119 - unexpected -Wformat-overflow after strlen in ILP32 since Ranger integration

gcc/ChangeLog:

	PR tree-optimization/104119
	* gimple-ssa-sprintf.cc (struct directive): Change argument type.
	(format_none): Same.
	(format_percent): Same.
	(format_integer): Same.
	(format_floating): Same.
	(get_string_length): Same.
	(format_character): Same.
	(format_string): Same.
	(format_plain): Same.
	(format_directive): Same.
	(compute_format_length): Same.
	(handle_printf_call): Same.
	* tree-ssa-strlen.cc (get_range_strlen_dynamic): Same.   Call
	get_maxbound.
	(get_range_strlen_phi): Same.
	(get_maxbound): New function.
	(strlen_pass::get_len_or_size): Adjust to parameter change.
	* tree-ssa-strlen.h (get_range_strlen_dynamic): Change argument type.

gcc/testsuite/ChangeLog:

	PR tree-optimization/104119
	* gcc.dg/tree-ssa/builtin-snprintf-13.c: New test.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-29.c: New test.

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index 98ab563a01b..c93f12f90b5 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -600,7 +600,7 @@ struct directive
 
   /* Format conversion function that given a directive and an argument
  returns the formatting result.  */
-  fmtresult (*fmtfunc) (const directive &, tree, range_query *);
+  fmtresult (*fmtfunc) (const directive &, tree, pointer_query &);
 
   /* Return True when the format flag CHR has been used.  */
   bool get_flag (char chr) const
@@ -968,7 +968,7 @@ directive::set_precision (tree arg, range_query *query)
 /* Return the result of formatting a no-op directive (such as '%n').  */
 
 static fmtresult
-format_none (const directive &, tree, range_query *)
+format_none (const directive &, tree, pointer_query &)
 {
   fmtresult res (0);
   return res;
@@ -977,7 +977,7 @@ format_none (const directive &, tree, range_query *)
 /* Return the result of formatting the '%%' directive.  */
 
 static fmtresult
-format_percent (const directive &, tree, range_query *)
+format_percent (const directive &, tree, pointer_query &)
 {
   fmtresult res (1);
   return res;
@@ -1199,7 +1199,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
used when the directive argument or its value isn't known.  */
 
 static fmtresult
-format_integer (const directive , tree arg, range_query *query)
+format_integer (const directive , tree arg, pointer_query _qry)
 {
   tree intmax_type_node;
   tree uintmax_type_node;
@@ -1383,7 +1383,7 @@ format_integer (const directive , tree arg, range_query *query)
   /* Try to determine the range of values of the integer argument
 	 (range information is not available for pointers).  */
   value_range vr;
-  query->range_of_expr (vr, arg, dir.info->callstmt);
+  ptr_qry.rvals->range_of_expr (vr, arg, dir.info->callstmt);
 
   if (!vr.varying_p () && !vr.undefined_p ())
 	{
@@ -1414,7 +1414,7 @@ format_integer (const directive , tree arg, range_query *query)
 	  if (code == INTEGER_CST)
 		{
 		  arg = gimple_assign_rhs1 (def);
-		  return format_integer (dir, arg, query);
+		  return format_integer (dir, arg, ptr_qry);
 		}
 
 	  if (code == NOP_EXPR)
@@ -1459,16 

Re: [PATCH] Fix Werror=format-diag with --disable-nls.

2022-01-20 Thread Martin Sebor via Gcc-patches

On 1/20/22 10:03, Jakub Jelinek wrote:

On Thu, Jan 20, 2022 at 09:56:59AM -0700, Martin Sebor wrote:

With normal -Wformat I see all expected warnings in:
char *foo (const char *) __attribute__((format_arg(1)));
void bar (const char *, ...) __attribute__((format(printf, 1, 2)));


-Wformat-diag is internal to GCC and needs one of the GCC-internal
attributes to enable, like __gcc_cxxdiag__, for example like this:

   __attribute__ ((format (__gcc_cxxdiag__, 1, 2)))
   void bar (const char *, ...);

With that it triggers in all the same instances as -Wformat below
(as near I can tell for a modified test case).


Glad to hear that, but then I don't understand why we didn't warn on
cp/error.cc before Martin L.'s change when --disable-nls wasn't used.


Good question!  There does seem to be some strange interplay between
parentheses and -Wformat for __gcc_cdiag__ functions in the C++ front
end:

__attribute__ ((format (__gcc_cxxdiag__, 1, 2)))
void bar (const char *, ...);

void
baz (int x)
{
  bar (x ? "<%s" : "%i", x);   // -Wformat-diag
  bar ((x ? "<%s" : "%i"), x); // silence
  bar ((x ? ("<%s") : ("%i")), x); // silence
}

The C front end warns on all three calls.

With attribute printf both the C and C++ front ends issue a -Wformat
for all three calls as expected (passing an int to %s).

Martin


Re: [PATCH] Fix Werror=format-diag with --disable-nls.

2022-01-20 Thread Martin Sebor via Gcc-patches

On 1/20/22 09:43, Jakub Jelinek wrote:

On Thu, Jan 20, 2022 at 09:33:30AM -0700, Martin Sebor wrote:

Oh, and one more thing, but this time not about this source file but about
the warning.  Does it handle the gettext case?
I think -Wformat generally does, gettext has format_arg attribute.
If the warning handles
pp_printf ("", str);
and
pp_printf (cond ? "" : "", str);
and
pp_printf (cond ? "" : "something %s", str);
and
pp_printf (gettext (""), str);
then maybe it should also handle
pp_printf (cond ? gettext ("") : ", str);
and
pp_printf (cond ? gettext ("") : "something %s, str);
too?


-Wformat-diag is part of -Wformat so they both should handle the same
things.  Do you see a difference between what they handle?


With normal -Wformat I see all expected warnings in:
char *foo (const char *) __attribute__((format_arg(1)));
void bar (const char *, ...) __attribute__((format(printf, 1, 2)));


-Wformat-diag is internal to GCC and needs one of the GCC-internal
attributes to enable, like __gcc_cxxdiag__, for example like this:

  __attribute__ ((format (__gcc_cxxdiag__, 1, 2)))
  void bar (const char *, ...);

With that it triggers in all the same instances as -Wformat below
(as near I can tell for a modified test case).

Martin



void
baz (int x)
{
   bar ("%ld", x);
   bar (x ? "%ld" : "%ld", x);
   bar (x ? "%ld" : "%lld", x);
   bar (foo ("%ld"), x);
   bar (x ? foo ("%ld") : "%ld", x);
   bar (x ? foo ("%ld") : "%lld", x);
   bar (foo (x ? "%ld" : "%ld"), x);
   bar (foo (x ? "%ld" : "%lld"), x);
}
(on all bar calls, on those with different strings or one in foo and other
not 2).
 From the fact that -Wformat-diag didn't warn on the
pp_printf (cond ? gettext ("") : ", str);
case I assume -Wformat-diag doesn't handle this.

Jakub





Re: [PATCH] Fix Werror=format-diag with --disable-nls.

2022-01-20 Thread Martin Sebor via Gcc-patches

On 1/20/22 03:28, Jakub Jelinek wrote:

On Thu, Jan 20, 2022 at 11:17:28AM +0100, Jakub Jelinek via Gcc-patches wrote:

--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -768,6 +768,11 @@ class_key_or_enum_as_string (tree t)
  return "struct";
  }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
  /* Print out a class declaration T under the control of FLAGS,
 in the form `class foo'.  */
@@ -851,6 +856,10 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
 flags & ~TFF_TEMPLATE_HEADER);
  }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic pop
+#endif


Oh, and one more thing, but this time not about this source file but about
the warning.  Does it handle the gettext case?
I think -Wformat generally does, gettext has format_arg attribute.
If the warning handles
   pp_printf ("", str);
and
   pp_printf (cond ? "" : "", str);
and
   pp_printf (cond ? "" : "something %s", str);
and
   pp_printf (gettext (""), str);
then maybe it should also handle
   pp_printf (cond ? gettext ("") : ", str);
and
   pp_printf (cond ? gettext ("") : "something %s, str);
too?


-Wformat-diag is part of -Wformat so they both should handle the same
things.  Do you see a difference between what they handle?

Martin



Jakub





[PATCH] constrain conservative string lengths to array sizes [PR104119]

2022-01-19 Thread Martin Sebor via Gcc-patches

The attached patch suppresses a class of unexpected -Wformat-overflow
(and -truncation) warnings introduced as a result of better range info
with the integration of the strlen pass with Ranger.

The sprintf warning code relies on the strlen pass data to determine
the lengths of string arguments to %s directives.  When the data for
a string are present, such as after a strlen call, the length can be
either a constant or, in the case of interest, a range (including
[N, PTRDIFF_MAX - 2] for a string of unbounded length).  When absent
because no string call has been seen yet, the string length is
considered to be bounded by the size of the array it's stored in.
This constrains the maximum number of bytes output by the %s directive
and reduces false positives.

The problem this patch addresses is that in the interesting case there
is no logic similar to the last ("no data") case, and so the maximum
number of bytes can be in excess of the size of the array.  The patch
does it by computing the size of the object (or member) in which
the string is stored and using its size minus 1 as the upper bound
on the length.  To do that, I had to adjust the APIs to pass in
the pointer_query instance of the range_query.  The meat of the change
is in the new get_maxbound() function.

There might be opportunities to do better still.  I'll try to look
into them if I still have time.

Tested on x86_64-linux.

MartinConstrain conservative string lengths to array sizes [PR104119].

Resolves:
PR tree-optimization/104119 - unexpected -Wformat-overflow after strlen in ILP32 since Ranger integration

gcc/ChangeLog:

	PR tree-optimization/104119
	* gimple-ssa-sprintf.cc (struct directive): Change argument type.
	(format_none): Same.
	(format_percent): Same.
	(format_integer): Same.
	(format_floating): Same.
	(get_string_length): Same.
	(format_character): Same.
	(format_string): Same.
	(format_plain): Same.
	(format_directive): Same.
	(compute_format_length): Same.
	(handle_printf_call): Same.
	* tree-ssa-strlen.cc (get_range_strlen_dynamic): Same.   Call
	get_maxbound.
	(get_range_strlen_phi): Same.
	(get_maxbound): New function.
	(strlen_pass::get_len_or_size): Adjust to parameter change.
	* tree-ssa-strlen.h (get_range_strlen_dynamic): Change argument type.

gcc/testsuite/ChangeLog:

	PR tree-optimization/104119
	* gcc.dg/tree-ssa/builtin-sprintf-warn-29.c: New test.

diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index 98ab563a01b..268b1eed427 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -600,7 +600,7 @@ struct directive
 
   /* Format conversion function that given a directive and an argument
  returns the formatting result.  */
-  fmtresult (*fmtfunc) (const directive &, tree, range_query *);
+  fmtresult (*fmtfunc) (const directive &, tree, pointer_query &);
 
   /* Return True when the format flag CHR has been used.  */
   bool get_flag (char chr) const
@@ -968,7 +968,7 @@ directive::set_precision (tree arg, range_query *query)
 /* Return the result of formatting a no-op directive (such as '%n').  */
 
 static fmtresult
-format_none (const directive &, tree, range_query *)
+format_none (const directive &, tree, pointer_query &)
 {
   fmtresult res (0);
   return res;
@@ -977,7 +977,7 @@ format_none (const directive &, tree, range_query *)
 /* Return the result of formatting the '%%' directive.  */
 
 static fmtresult
-format_percent (const directive &, tree, range_query *)
+format_percent (const directive &, tree, pointer_query &)
 {
   fmtresult res (1);
   return res;
@@ -1199,7 +1199,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
used when the directive argument or its value isn't known.  */
 
 static fmtresult
-format_integer (const directive , tree arg, range_query *query)
+format_integer (const directive , tree arg, pointer_query _qry)
 {
   tree intmax_type_node;
   tree uintmax_type_node;
@@ -1383,7 +1383,7 @@ format_integer (const directive , tree arg, range_query *query)
   /* Try to determine the range of values of the integer argument
 	 (range information is not available for pointers).  */
   value_range vr;
-  query->range_of_expr (vr, arg, dir.info->callstmt);
+  ptr_qry.rvals->range_of_expr (vr, arg, dir.info->callstmt);
 
   if (!vr.varying_p () && !vr.undefined_p ())
 	{
@@ -1414,7 +1414,7 @@ format_integer (const directive , tree arg, range_query *query)
 	  if (code == INTEGER_CST)
 		{
 		  arg = gimple_assign_rhs1 (def);
-		  return format_integer (dir, arg, query);
+		  return format_integer (dir, arg, ptr_qry);
 		}
 
 	  if (code == NOP_EXPR)
@@ -1459,16 +1459,16 @@ format_integer (const directive , tree arg, range_query *query)
   /* For unsigned conversions/directives or signed when
 	 the minimum is positive, use the minimum and maximum to compute
 	 the shortest and longest output, respectively.  */
-  res.range.min = format_integer (dir, argmin, query).range.min;
-  

Re: [PATCH] waccess: Look at calls when tracking clobbers [PR104092]

2022-01-19 Thread Martin Sebor via Gcc-patches

On 1/19/22 09:22, Richard Sandiford wrote:

Martin Sebor  writes:

On 1/19/22 03:09, Richard Sandiford wrote:

Richard Biener  writes:

On Tue, Jan 18, 2022 at 2:40 PM Richard Sandiford via Gcc-patches
 wrote:


In this PR the waccess pass was fed:

D.10779 ={v} {CLOBBER};
VIEW_CONVERT_EXPR(D.10779) = .MASK_LOAD_LANES (addr_5(D), 
64B, _2);
_7 = D.10779.__val[0];

However, the tracking of m_clobbers only looked at gassigns,
so it missed that the clobber on the first line was overwritten
by the call on the second line.


Just as a note another possible def can come via asm() outputs
and clobbers.  There would have been walk_stmt_load_store_ops
to track all those down (not sure if the function is a good fit here).


Hmm.  Looking at what the pass is doing in more detail, I'm not sure
this approach to handling m_clobbers is safe.  The pass walks the
blocks in sequence (rather than using a dom walk, say):

FOR_EACH_BB_FN (bb, fun)
  check_block (bb);

so it could see the clobber after a later dominating assignment.
Similarly check_call_dangling could see a use that is “protected”
by a later assignment.


check_call_dangling() reports only uses that are dominated by prior
clobbers (determined in use_after_inval_p) so it should not have
this problem.


Yeah, but what I mean is that, if we have:

   A dominates B dominates C
   A clobbers X
   B defines X
   C uses X

we could still see them in this order:

   A, C, B

The dominance check would then succeed for  even though B
should invalidate the clobber.


I see.  I think you're right, that case of "clobber revival" isn't
handled.  I don't know how to trigger it or have a sense of how
often it might come up (the dangling check runs only very early,
before loop unrolling, to try to avoid it as much as possible).
But running the first loop in dominator order instead as you
suggest should be easy enough.  Do you happen to have an idea
for a test case to trigger the problem and verify it's fixed?

Martin



Thanks,
Richard




Re: [PATCH] waccess: Look at calls when tracking clobbers [PR104092]

2022-01-19 Thread Martin Sebor via Gcc-patches

On 1/19/22 03:09, Richard Sandiford wrote:

Richard Biener  writes:

On Tue, Jan 18, 2022 at 2:40 PM Richard Sandiford via Gcc-patches
 wrote:


In this PR the waccess pass was fed:

   D.10779 ={v} {CLOBBER};
   VIEW_CONVERT_EXPR(D.10779) = .MASK_LOAD_LANES (addr_5(D), 
64B, _2);
   _7 = D.10779.__val[0];

However, the tracking of m_clobbers only looked at gassigns,
so it missed that the clobber on the first line was overwritten
by the call on the second line.


Just as a note another possible def can come via asm() outputs
and clobbers.  There would have been walk_stmt_load_store_ops
to track all those down (not sure if the function is a good fit here).


Hmm.  Looking at what the pass is doing in more detail, I'm not sure
this approach to handling m_clobbers is safe.  The pass walks the
blocks in sequence (rather than using a dom walk, say):

   FOR_EACH_BB_FN (bb, fun)
 check_block (bb);

so it could see the clobber after a later dominating assignment.
Similarly check_call_dangling could see a use that is “protected”
by a later assignment.


check_call_dangling() reports only uses that are dominated by prior
clobbers (determined in use_after_inval_p) so it should not have
this problem.

Martin



Richard




[committed] add test for PR104076

2022-01-18 Thread Martin Sebor via Gcc-patches

A -Wdangling-pointer false positive reported just the other day
on this list has disappeared after an unrelated change to
the gimplifier (r12-6694).  In r12-6714 I've committed the regression
test for it, though I'm not sure I see what the warning code could
have done to avoid the false positive.  Ideas are welcome.

Thanks
Martin


[committed] prune out expected warning [PR104103]

2022-01-18 Thread Martin Sebor via Gcc-patches

The regression test gcc.dg/torture/pr57147-2.c triggers a valid
warning by passing a variable with zero size to a function that
expects an array of size 1.  The recent change to run the access
pass also earlier in the optimization pipeline has triggered
this warning.  In r12-6713 I have committed a change to prune
the warning out.

https://gcc.gnu.org/g:282110ae8b54250c8dcb73afc6f30761a41e38e6

I saw the test failure in my build before committing the original
change but then couldn't reproduce it so I chalked it up to cosmic
rays without deeper investigation.  My bad.

Martin


[committed] fix a typo in pointer_related_p [PR104069]

2022-01-18 Thread Martin Sebor via Gcc-patches

The new pointer_related_p() utility function added for -Wuse-after-free
is documented to conservatively return false when it cannot determine
relatedness but actually returns true.  That has caused the false
positive reported in PR 104069.  In r12-6712 I've committed as obvious
a fix for this mistake along with a test case.

https://gcc.gnu.org/g:2f714642e574c64e1c0e093cad3de6f8accb6ec7

Martin


Re: [PATCH] gimple-ssa-warn-access: Fix up asan_test.C -Wdangling-pointer regression [PR104103]

2022-01-18 Thread Martin Sebor via Gcc-patches

On 1/18/22 16:56, Jakub Jelinek wrote:

Hi!

As reported in the PR or as I've seen since the weekend, asan_test.C fails
because of many warnings like:
/home/jakub/src/gcc/gcc/testsuite/g++.dg/asan/asan_test.cc:1157:10: error: 
using a dangling pointer to an unnamed temporary [-Werror=dangling-pointer=]
/home/jakub/src/gcc/gcc/testsuite/g++.dg/asan/asan_test.cc:1157:10: error: 
using a dangling pointer to an unnamed temporary [-Werror=dangling-pointer=]
/home/jakub/src/gcc/gcc/testsuite/g++.dg/asan/asan_test.cc:1162:27: error: 
using a dangling pointer to an unnamed temporary [-Werror=dangling-pointer=]
...
(lots of them).
There are no dangling pointers though, the warning pass sees:
   some_automatic_var ={v} {CLOBBER};
   .ASAN_MARK (POISON, _automatic_var, 8);
and warns on that (both on user vars and on e.g. TARGET_EXPR temporaries).
There is nothing wrong on that, .ASAN_MARK is compiler instrumentation,
which doesn't even touch the variable in any way nor make it escaped.
What it instead does is change bytes in the shadow memory corresponding
to the variable to reflect that the variable is out of scope and make
sure that access to it would be diagnosed at runtime.
So, for all purposes of the -Wdangling-pointer and -Wuse-after-free
warnings, we should ignore this internal call.

Bootstrapped/regtested on x86_64-linux and i686-linux, fixes asan_test.C
FAIL (so no new test has been added), ok for trunk?


This is in line with what's done for -Wmaybe-uninitialized so it makes
sense to do it here as well.  -Wmaybe-uninitialized also exempts calls
to sanitizer built-ins from checking.  I don't know if they might come
up here but if it can't be ruled out, moving the code from
tree-ssa-uninit.cc into a utility helper and calling it from both
places might be a good idea.

Martin



2022-01-18  Jakub Jelinek  

PR middle-end/104103
* gimple-ssa-warn-access.cc (pass_waccess::check_call): Don't check
.ASAN_MARK calls.

--- gcc/gimple-ssa-warn-access.cc.jj2022-01-16 20:55:46.783932110 +0100
+++ gcc/gimple-ssa-warn-access.cc   2022-01-18 20:56:13.697780325 +0100
@@ -4232,6 +4232,11 @@ pass_waccess::check_call (gcall *stmt)
if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
  check_builtin (stmt);
  
+  /* .ASAN_MARK doesn't access any vars, only modifies shadow memory.  */

+  if (gimple_call_internal_p (stmt)
+  && gimple_call_internal_fn (stmt) == IFN_ASAN_MARK)
+return;
+
if (!m_early_checks_p)
  if (tree callee = gimple_call_fndecl (stmt))
{

Jakub





Re: [PATCH] waccess: Look at calls when tracking clobbers [PR104092]

2022-01-18 Thread Martin Sebor via Gcc-patches

On 1/18/22 06:37, Richard Sandiford wrote:

In this PR the waccess pass was fed:

   D.10779 ={v} {CLOBBER};
   VIEW_CONVERT_EXPR(D.10779) = .MASK_LOAD_LANES (addr_5(D), 
64B, _2);
   _7 = D.10779.__val[0];

However, the tracking of m_clobbers only looked at gassigns,
so it missed that the clobber on the first line was overwritten
by the call on the second line.

This patch splits the updating of m_clobbers out into its own
function, called after the check_*() routines, and extends it
to handle both gassigns and gcalls.  I think that makes sense
as an instance of the "read, operate, write" model, with the
new function being part of "write".

Previously only the gimple_clobber_p handling was conditional
on m_check_dangling_p, but I think the whole of the new function
can be.  We only enter stmts into m_clobbers if m_check_dangling_p,
so we only need to remove them under the same condition.


Thanks for the patch.  If you or someone can think of a test case
that's independent of a target, adding one would be very helpful.

Other than that, since I can't approve any changes I CC Jason who
was kind enough to approve the implementation of the warning for
his OK.

Martin



Tested on aarch64-linux-gnu.  OK to install?

Richard


gcc/
PR middle-end/104092
* gimple-ssa-warn-access.cc (pass_waccess::update_clobbers_from_lhs):
New function, split out from...
(pass_waccess::check_stmt): ...here and generalized to calls.
(pass_waccess::check_block): Call it.

gcc/testsuite/
* gcc.target/aarch64/sve/acle/general/pr104092.c: New test.
---
  gcc/gimple-ssa-warn-access.cc | 68 +++
  .../aarch64/sve/acle/general/pr104092.c   |  7 ++
  2 files changed, 48 insertions(+), 27 deletions(-)
  create mode 100644 
gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr104092.c

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index f639807a78a..25066fa6b89 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2094,6 +2094,9 @@ private:
/* Check a non-call statement.  */
void check_stmt (gimple *);
  
+  /* Update the clobber map based on the lhs of a statement.  */

+  void update_clobbers_from_lhs (gimple *);
+
/* Check statements in a basic block.  */
void check_block (basic_block);
  
@@ -4270,33 +4273,6 @@ is_auto_decl (tree x)

  void
  pass_waccess::check_stmt (gimple *stmt)
  {
-  if (m_check_dangling_p && gimple_clobber_p (stmt))
-{
-  /* Ignore clobber statemts in blocks with exceptional edges.  */
-  basic_block bb = gimple_bb (stmt);
-  edge e = EDGE_PRED (bb, 0);
-  if (e->flags & EDGE_EH)
-   return;
-
-  tree var = gimple_assign_lhs (stmt);
-  m_clobbers.put (var, stmt);
-  return;
-}
-
-  if (is_gimple_assign (stmt))
-{
-  /* Clobbered unnamed temporaries such as compound literals can be
-revived.  Check for an assignment to one and remove it from
-M_CLOBBERS.  */
-  tree lhs = gimple_assign_lhs (stmt);
-  while (handled_component_p (lhs))
-   lhs = TREE_OPERAND (lhs, 0);
-
-  if (is_auto_decl (lhs))
-   m_clobbers.remove (lhs);
-  return;
-}
-
if (greturn *ret = dyn_cast  (stmt))
  {
if (optimize && flag_isolate_erroneous_paths_dereference)
@@ -4326,6 +4302,42 @@ pass_waccess::check_stmt (gimple *stmt)
  }
  }
  
+/* Update the clobber map based on the lhs of STMT.  */

+
+void
+pass_waccess::update_clobbers_from_lhs (gimple *stmt)
+{
+  if (gimple_clobber_p (stmt))
+{
+  /* Ignore clobber statements in blocks with exceptional edges.  */
+  basic_block bb = gimple_bb (stmt);
+  edge e = EDGE_PRED (bb, 0);
+  if (e->flags & EDGE_EH)
+   return;
+
+  tree var = gimple_assign_lhs (stmt);
+  m_clobbers.put (var, stmt);
+  return;
+}
+
+  if (is_gimple_assign (stmt) || is_gimple_call (stmt))
+{
+  /* Clobbered unnamed temporaries such as compound literals can be
+revived.  Check for an assignment to one and remove it from
+M_CLOBBERS.  */
+  tree lhs = gimple_get_lhs (stmt);
+  if (!lhs)
+   return;
+
+  while (handled_component_p (lhs))
+   lhs = TREE_OPERAND (lhs, 0);
+
+  if (is_auto_decl (lhs))
+   m_clobbers.remove (lhs);
+  return;
+}
+}
+
  /* Check basic block BB for invalid accesses.  */
  
  void

@@ -4340,6 +4352,8 @@ pass_waccess::check_block (basic_block bb)
check_call (call);
else
check_stmt (stmt);
+  if (m_check_dangling_p)
+   update_clobbers_from_lhs (stmt);
  }
  }
  
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr104092.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr104092.c

new file mode 100644
index 000..c17ece7d82f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr104092.c
@@ -0,0 +1,7 @@
+/* { dg-options "-O2 -Wall" } */
+
+#include 
+

Re: [PATCH] middle-end/101292 - invalid memory access with warning control

2022-01-18 Thread Martin Sebor via Gcc-patches

On 1/18/22 01:36, Richard Biener wrote:

On Mon, 17 Jan 2022, Martin Sebor wrote:


On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:

The warning control falls into the C++ trap of using a reference
to old hashtable contents for a put operation which can end up
re-allocating that before reading from the old freed referenced to
source.  Fixed by introducing a temporary.


I think a better place to fix this and avoid the gotcha once and
for all is in the GCC hash_map: C++ containers are expected to
handle the insertion of own elements gracefully.


I don't think that's reasonably possible if you consider

   T *a = map.get (X);
   T *b = map.get (Y);
   map.put (Z, *a);
   map.put (W, *b);


This case is up to the caller to handle, the same as anything else
involving pointers or references into reallocated storage (it's no
different in C than it is in C++).

The specific case I'm referring to is passing a pointer or reference
to a single element in a container to the first modifying call on
the container.



the only way to "fix" it would be to change the API to not
return by reference for get, remove get_or_insert (or change
its API to also require passing the new value).


No, the fix is to have the modifying function create a copy of
the element being inserted before reallocating the container.



Note the above shows that making 'put' take the value by
value instead of by reference doesn't work either.

IMHO the issue is that C++ doesn't make it obvious that 'put'
gets a pointer to the old element (stupid references).


The problem isn't specific to references, it can come up with
pointers just as easily.  Pointers might just make it more obvious.

Martin



Richard.


Martin



Bootstrap & regtest running on x86_64-unknown-linux-gnu.

2022-01-17  Richard Biener  

  PR middle-end/101292
  * diagnostic-spec.c (copy_warning): Make sure to not
  reference old hashtable content on possible resize.
  * warning-control.cc (copy_warning): Likewise.
---
   gcc/diagnostic-spec.c  | 5 -
   gcc/warning-control.cc | 3 ++-
   2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index a8af229d677..4341ccfaae9 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
 else
   {
 if (from_spec)
-   nowarn_map->put (to, *from_spec);
+   {
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to, tem);
+   }
  else
nowarn_map->remove (to);
   }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index f9808bf4392..fa39ecab421 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
  gcc_assert (supp);
   
   	  gcc_checking_assert (nowarn_map);

- nowarn_map->put (to_loc, *from_spec);
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to_loc, tem);
}
  else
{









Re: PING 4 [PATCH v2 2/2] add -Wdangling-pointer [PR #63272]

2022-01-17 Thread Martin Sebor via Gcc-patches

On 1/17/22 06:46, Stephan Bergmann wrote:

On 10/01/2022 22:51, Martin Sebor via Gcc-patches wrote:

Last ping for this stage 1 feature before stage 3 ends:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html


This hits somewhat unexpectedly at (test case reduced from a hit in 
LibreOffice)


Thanks for the small test case!  It seems like the PHI handling
(conditionals) might overly simplistic.  Let me look into it.

I tried to set up OpenOffice for testing with the latest GCC but
couldn't get the build to finish (it failed downloading some
unavailable prerequisites).  I don't remember what problem I ran
into with LibreOffice; it was before I upgraded to Fedora 35 just
a couple of weeks ago.  Let me retry again (the build is still
downloading tarballs).

In the meantime, do you have any tips or suggestions getting it
set up that aren't on the instructions page below?  (Especially
for using an alternate compiler and non-default options.)

https://wiki.documentfoundation.org/Development/BuildingOnLinux#Fedora.2FRedHat

Martin




$ cat test.cc
#include 
struct S1 {
    S1(int);
    ~S1();
};
struct S2 { S2(std::initializer_list); };
S2 f1();
S2 f2(bool b) { return b ? f1() : S2{0}; }



$ g++ -Wdangling-pointer -c test.cc
test.cc: In function ‘S2 f2(bool)’:
test.cc:8:42: warning: dangling pointer to an unnamed temporary may be 
used [-Wdangling-pointer=]

    8 | S2 f2(bool b) { return b ? f1() : S2{0}; }
  |  ^
test.cc:8:39: note: unnamed temporary defined here
    8 | S2 f2(bool b) { return b ? f1() : S2{0}; }
  |   ^
test.cc:8:42: warning: dangling pointer to an unnamed temporary may be 
used [-Wdangling-pointer=]

    8 | S2 f2(bool b) { return b ? f1() : S2{0}; }
  |  ^
test.cc:8:39: note: unnamed temporary defined here
    8 | S2 f2(bool b) { return b ? f1() : S2{0}; }
  |   ^






Re: [PATCH] middle-end/101292 - invalid memory access with warning control

2022-01-17 Thread Martin Sebor via Gcc-patches

On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:

The warning control falls into the C++ trap of using a reference
to old hashtable contents for a put operation which can end up
re-allocating that before reading from the old freed referenced to
source.  Fixed by introducing a temporary.


I think a better place to fix this and avoid the gotcha once and
for all is in the GCC hash_map: C++ containers are expected to
handle the insertion of own elements gracefully.

Martin



Bootstrap & regtest running on x86_64-unknown-linux-gnu.

2022-01-17  Richard Biener  

PR middle-end/101292
* diagnostic-spec.c (copy_warning): Make sure to not
reference old hashtable content on possible resize.
* warning-control.cc (copy_warning): Likewise.
---
  gcc/diagnostic-spec.c  | 5 -
  gcc/warning-control.cc | 3 ++-
  2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index a8af229d677..4341ccfaae9 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
else
  {
if (from_spec)
-   nowarn_map->put (to, *from_spec);
+   {
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to, tem);
+   }
else
nowarn_map->remove (to);
  }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index f9808bf4392..fa39ecab421 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
  gcc_assert (supp);
  
  	  gcc_checking_assert (nowarn_map);

- nowarn_map->put (to_loc, *from_spec);
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to_loc, tem);
}
else
{




Re: gcc/configure: out of date

2022-01-15 Thread Martin Sebor via Gcc-patches

Martin, I've looked into removing the -Wno-error for this warning
for just a subset of targets.  It seems doable with some hardcoding
in configure.ac but if you're planning to do the cleanup for all of
them I'm wondering if we should even bother.  What do you think?

Martin

On 1/14/22 08:46, Martin Liška wrote:

Hello.

I noticed that when I run:
ACLOCAL=~/bin/automake-1.15.1/bin/aclocal  
AUTOMAKE=~/bin/automake-1.15.1/bin/automake autoconf


in gcc subfolder I get the following diff:

diff --git a/gcc/configure b/gcc/configure
index d19059e13cc..ff570f73ef5 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -5352,7 +5352,26 @@ else
    GDC="$ac_cv_prog_GDC"
  fi

+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the D 
compiler works" >&5

+$as_echo_n "checking whether the D compiler works... " >&6; }
+if ${acx_cv_d_compiler_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.d <&1 || echo failure`
+  if test x"$errors" = x && test -f conftest.$ac_objext; then
+    acx_cv_d_compiler_works=yes
+  fi
+  rm -f conftest.*
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$acx_cv_d_compiler_works" >&5

+$as_echo "$acx_cv_d_compiler_works" >&6; }
+if test "x$GDC" != xno && test x$acx_cv_d_compiler_works != xno; then
    have_gdc=yes
  else
    have_gdc=no
@@ -19640,7 +19659,7 @@ else
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
-#line 19643 "configure"
+#line 19662 "configure"
  #include "confdefs.h"

  #if HAVE_DLFCN_H
@@ -19746,7 +19765,7 @@ else
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
-#line 19749 "configure"
+#line 19768 "configure"
  #include "confdefs.h"

  #if HAVE_DLFCN_H

Am I correct that somebody forgot to re-generate the file?

Martin




Re: [PATCH v2 1/2] add -Wuse-after-free

2022-01-15 Thread Martin Sebor via Gcc-patches

On 1/11/22 15:40, Jason Merrill wrote:

On 11/30/21 17:32, Martin Sebor via Gcc-patches wrote:

Attached is a revised patch with the following changes based
on your comments:

1) Set and use statement uids to determine which statement
    precedes which in the same basic block.
2) Avoid testing flag_isolate_erroneous_paths_dereference.
3) Use post-dominance to decide whether to use the "maybe"
    phrasing vs a definite form.

David raised (and in our offline discussion today reiterated)
an objection to the default setting of the option being
the strictest.  I have not changed that in this revision.
See my rationale for this choice in my reply below:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/583176.html


In the latest C2x draft I see in the list of undefined behavior

"The value of a pointer that refers to space deallocated by a call to 
the free or realloc function is used (7.22.3)."


So the case that would be technically undefined would be comparing the 
reallocated pointer to the old pointer which has been deallocated.


The C++ draft is more nuanced: it says, "When the end of the duration of 
a region of storage is reached, the values of all pointers representing 
the address of any part of that region of storage become invalid pointer 
values (6.8.3).  Indirection through an invalid pointer value and 
passing an invalid pointer value to a deallocation function have 
undefined behavior.  Any other use of an invalid pointer value has 
implementation-defined behavior."


So the case above is implementation-defined in C++, not undefined.

Let's put =2 in -Wall for now.

With that change, this and the -Wdangling-pointer patch are OK on Friday 
afternoon if there are no other comments before then.

I've adjusted both patches and pushed r12-6605 and r12-6606 after
retesting with a few packages.  In -Wdangling-pointer I reworded
the warning to refer to "unnamed temporary" instead of "compound
literal" since it triggers for those as well.

While rebuilding LLVM and a few its projects with the patches
I noticed the -Wdangling-pointer change exposes what seems like
a Ranger bug for one translation unit (it enters an infinite loop):
I opened pr104038 for it.

Martin




On 11/23/21 2:16 PM, Martin Sebor wrote:

On 11/22/21 6:32 PM, Jeff Law wrote:



On 11/1/2021 4:17 PM, Martin Sebor via Gcc-patches wrote:

Patch 1 in the series detects a small subset of uses of pointers
made indeterminate by calls to deallocation functions like free
or C++ operator delete.  To control the conditions the warnings
are issued under the new -Wuse-after-free= option provides three
levels.  At the lowest level the warning triggers only for
unconditional uses of freed pointers and doesn't warn for uses
in equality expressions.  Level 2 warns also for come conditional
uses, and level 3 also for uses in equality expressions.

I debated whether to make level 2 or 3 the default included in
-Wall.  I decided on 3 for two reasons: 1) to raise awareness
of both the problem and GCC's new ability to detect it: using
a pointer after it's been freed, even only in principle, by
a successful call to realloc, is undefined, and 2) because
it's trivial to lower the level either globally, or locally
by suppressing the warning around such misuses.

I've tested the patch on x86_64-linux and by building Glibc
and Binutils/GDB.  It triggers a number of times in each, all
due to comparing invalidated pointers for equality (i.e., level
3).  I have suppressed these in GCC (libiberty) by a #pragma,
and will see how the Glibc folks want to deal with theirs (I
track them in BZ #28521).

The tests contain a number of xfails due to limitations I'm
aware of.  I marked them pr?? until the patch is approved.
I will open bugs for them before committing if I don't resolve
them in a followup.

Martin

gcc-63272-1.diff

Add -Wuse-after-free.

gcc/c-family/ChangeLog

* c.opt (-Wuse-after-free): New options.

gcc/ChangeLog:

* diagnostic-spec.c (nowarn_spec_t::nowarn_spec_t): Handle
OPT_Wreturn_local_addr and OPT_Wuse_after_free_.
* diagnostic-spec.h (NW_DANGLING): New enumerator.
* doc/invoke.texi (-Wuse-after-free): Document new option.
* gimple-ssa-warn-access.cc (pass_waccess::check_call): Rename...
(pass_waccess::check_call_access): ...to this.
(pass_waccess::check): Rename...
(pass_waccess::check_block): ...to this.
(pass_waccess::check_pointer_uses): New function.
(pass_waccess::gimple_call_return_arg): New function.
(pass_waccess::warn_invalid_pointer): New function.
(pass_waccess::check_builtin): Handle free and realloc.
(gimple_use_after_inval_p): New function.
(get_realloc_lhs): New function.
(maybe_warn_mismatched_realloc): New function.
(pointers_related_p): New function.
(pass_waccess::check_call): Call check_pointer_uses.
(pass_waccess::execute): Compute and free dominance info.

libcpp/ChangeLog:

* fi

Re: [Patch][V4][Patch 2/2]Enable -Wuninitialized + -ftrivial-auto-var-init for address taken variables.

2022-01-14 Thread Martin Sebor via Gcc-patches

On 1/14/22 11:29, Qing Zhao wrote:




On Jan 14, 2022, at 12:11 PM, Martin Sebor  wrote:

On 1/14/22 09:30, Qing Zhao wrote:

On Jan 14, 2022, at 6:45 AM, Richard Biener  wrote:

On Thu, Jan 13, 2022 at 2:45 AM Qing Zhao  wrote:


Hi, Richard,

This is the updated version for the second patch, which is mainly the change for 
"Enable -Wuninitialized + -ftrivial-auto-var-init for  address taken variables”.

In this update, I mainly made the following change:

1.  Delete “repl_var”, use the var_def_stmt, i.e, the call to .DEFERRED_INIT to 
record the warning suppressed info.
2. Add and change the comments in multiple places to make the change more 
readable.

Now, for the deleted variable, we will get the necessary info to report warning 
from the call to .DEFERRED_INIT.

A. the name string of DECL from the 3rd parameter of the call;
B. the location of the DECL from the location of the call;
C. the call can also be used to hold the information on whether the warning
   has been issued or not to suppress warning messages when needed;

Please see the detailed description below for the problem and solution of this 
patch.

This patch has been bootstrapped and regressing tested on both X86 and aarch64.

Okay for GCC12?


I think the change to split "%qD is used uninitialized" is bad for i8n
though it seems
like none of the strings passed to warn_uninit are currently marked
for localization.
I suppose there's lazy matching with the exact same strings passed to
warning_at around like 641 but after your change those will no longer match up,

Silly question: What does the above “641” mean?


At around line 641 :)


I thought of this, but I didn’t find a meaningful statement around line 641 in 
tree-ssa-uninit.c…

  636 found_alloc = true;
  637   break;
  638 }
  639
  640   if (!is_gimple_assign (def_stmt))
  641 break;
  642
  643   tree_code code = gimple_assign_rhs_code (def_stmt);
  644   if (code != ADDR_EXPR && code != POINTER_PLUS_EXPR)
  645 break;
  



at least for the "%qs ..." case constructed.  I think a better way
(for i8n) would be
to pass down a flag whether it is "may" or "is" and have the full translatable
strings literally passed to warning_at at the expense of some code duplication.
Actually the extra flag is unnecessary, the OPT_W... we pass is already fully
specifying that.

The only issue with the above change is:  among the  4 calls to “warn_uninit” 
as following:
if (use_stmt)
 warn_uninit (OPT_Wuninitialized, def, SSA_NAME_VAR (def),
-"%qD is used uninitialized", use_stmt);
+"is used uninitialized", use_stmt);
  }
  }
@@ -932,10 +1015,10 @@ warn_uninitialized_vars (bool wmaybe_uninit)
   tree use = USE_FROM_PTR (use_p);
   if (wlims.always_executed)
 warn_uninit (OPT_Wuninitialized, use, SSA_NAME_VAR (use),
-"%qD is used uninitialized", stmt);
+"is used uninitialized", stmt);
   else if (wmaybe_uninit)
 warn_uninit (OPT_Wmaybe_uninitialized, use, SSA_NAME_VAR (use),
-"%qD may be used uninitialized", stmt);
+"may be used uninitialized", stmt);
 }
   /* For limiting the alias walk below we count all
@@ -1182,7 +1265,7 @@ warn_uninitialized_phi (gphi *phi, vec *worklist,
warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
SSA_NAME_VAR (uninit_op),
-  "%qD may be used uninitialized in this function",
+  "may be used uninitialized in this function",
uninit_use_stmt, loc);
All the strings passed map well with the OPT_W… except the last one, since the 
last one has an additional string “in this function” at the end.
However, since the last call has the last argument “loc” been NULL, maybe we 
can use this to distinguish.


Now that diagnostics are prefixed by something like "In function 'foo':
the "in this function" part is superfluous and could be removed from
all warning messages.


Okay, so, you mean that it’s safe to just remove “in this function” from the 
last callsite?


Yes, I would remove it.  It might require some cleanup in the test
suite but I wouldn't expect it to be too bad.





When there's no location (i.e., loc is UNKNOWN_LOCATION) the called
code tries to derive a location from the context.  When it can't, it
won't point anywhere useful, so if that case ever comes up here it
should probably be handled by using the location of the curly brace
closing the function definition.


You mean the following in the routine warn_uninit:

  /* Use either the location of the read statement or that of the PHI
  argument, or that of the uninitialized variable, in that order,
  whichever is valid.  */
   location_t location = UNKNOWN_LOCATION;
   if (gimple_has_location 

Re: [Patch][V4][Patch 2/2]Enable -Wuninitialized + -ftrivial-auto-var-init for address taken variables.

2022-01-14 Thread Martin Sebor via Gcc-patches

On 1/14/22 09:30, Qing Zhao wrote:




On Jan 14, 2022, at 6:45 AM, Richard Biener  wrote:

On Thu, Jan 13, 2022 at 2:45 AM Qing Zhao  wrote:


Hi, Richard,

This is the updated version for the second patch, which is mainly the change for 
"Enable -Wuninitialized + -ftrivial-auto-var-init for  address taken variables”.

In this update, I mainly made the following change:

1.  Delete “repl_var”, use the var_def_stmt, i.e, the call to .DEFERRED_INIT to 
record the warning suppressed info.
2. Add and change the comments in multiple places to make the change more 
readable.

Now, for the deleted variable, we will get the necessary info to report warning 
from the call to .DEFERRED_INIT.

A. the name string of DECL from the 3rd parameter of the call;
B. the location of the DECL from the location of the call;
C. the call can also be used to hold the information on whether the warning
   has been issued or not to suppress warning messages when needed;

Please see the detailed description below for the problem and solution of this 
patch.

This patch has been bootstrapped and regressing tested on both X86 and aarch64.

Okay for GCC12?


I think the change to split "%qD is used uninitialized" is bad for i8n
though it seems
like none of the strings passed to warn_uninit are currently marked
for localization.
I suppose there's lazy matching with the exact same strings passed to
warning_at around like 641 but after your change those will no longer match up,


Silly question: What does the above “641” mean?


At around line 641 :)




at least for the "%qs ..." case constructed.  I think a better way
(for i8n) would be
to pass down a flag whether it is "may" or "is" and have the full translatable
strings literally passed to warning_at at the expense of some code duplication.
Actually the extra flag is unnecessary, the OPT_W... we pass is already fully
specifying that.


The only issue with the above change is:  among the  4 calls to “warn_uninit” 
as following:

if (use_stmt)
 warn_uninit (OPT_Wuninitialized, def, SSA_NAME_VAR (def),
-"%qD is used uninitialized", use_stmt);
+"is used uninitialized", use_stmt);
  }
  }

@@ -932,10 +1015,10 @@ warn_uninitialized_vars (bool wmaybe_uninit)
   tree use = USE_FROM_PTR (use_p);
   if (wlims.always_executed)
 warn_uninit (OPT_Wuninitialized, use, SSA_NAME_VAR (use),
-"%qD is used uninitialized", stmt);
+"is used uninitialized", stmt);
   else if (wmaybe_uninit)
 warn_uninit (OPT_Wmaybe_uninitialized, use, SSA_NAME_VAR (use),
-"%qD may be used uninitialized", stmt);
+"may be used uninitialized", stmt);
 }

   /* For limiting the alias walk below we count all
@@ -1182,7 +1265,7 @@ warn_uninitialized_phi (gphi *phi, vec *worklist,

warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
SSA_NAME_VAR (uninit_op),
-  "%qD may be used uninitialized in this function",
+  "may be used uninitialized in this function",
uninit_use_stmt, loc);

All the strings passed map well with the OPT_W… except the last one, since the 
last one has an additional string “in this function” at the end.
However, since the last call has the last argument “loc” been NULL, maybe we 
can use this to distinguish.


Now that diagnostics are prefixed by something like "In function 'foo':
the "in this function" part is superfluous and could be removed from
all warning messages.

When there's no location (i.e., loc is UNKNOWN_LOCATION) the called
code tries to derive a location from the context.  When it can't, it
won't point anywhere useful, so if that case ever comes up here it
should probably be handled by using the location of the curly brace
closing the function definition.

Martin



Instead of doing

+  if (gimple_call_internal_p (var_def_stmt, IFN_DEFERRED_INIT))
+   {
+ /* Ignore the call to .DEFERRED_INIT that define the original
+var itself as the following case:
+   temp = .DEFERRED_INIT (4, 2, â~@~\alt_reloc");
+   alt_reloc = temp;
+In order to avoid generating warning for the fake usage
+at alt_reloc = temp.
...

I thought of many options, none really very appealing so I guess we have to
go with this for now.


I agree with you, this is really ugly, I am not very comfortable myself either. 
But looks like no better way to resolve it….


So OK with the i8n thing sorted out - please post one hopefully last update
for the patch.


Will do it.



Thanks for your patience,


Thank you!

Qing

Richard.


thanks.

Qing.


Enable -Wuninitialized + -ftrivial-auto-var-init for address
taken variables.

With -ftrivial-auto-var-init, the address taken auto variable is replaced with
a 

[COMMITTED] test to verify -Wformat-overflow uses context-sensitive ranges

2022-01-14 Thread Martin Sebor via Gcc-patches

Converting the strlen/sprintf pass to Ranger has considerably
improved the accuracy of -Wformat-overflow warnings: they can avoid
triggering for safe input even at -O0 while at the same time detect
provable overflow.  The conversion didn't come with any tests so in
r12-6591 I committed one that verifies both of these improvements.

https://gcc.gnu.org/pipermail/gcc-cvs/2022-January/359299.html

Martin


Re: Document current '-Wuninitialized'/'-Wmaybe-uninitialized' diagnostics for OpenACC test cases

2022-01-13 Thread Martin Sebor via Gcc-patches

On 1/13/22 03:55, Thomas Schwinge wrote:

Hi!

This has fallen out of (unfinished...) work earlier in the year: pushed
to master branch commit 4bd8b1e881f0c26a5103cd1919809b3d63b60ef2
"Document current '-Wuninitialized'/'-Wmaybe-uninitialized' diagnostics
for OpenACC test cases".


Thanks for the heads up.  If any of these are recent regressions
(either the false negatives or the false positives) it would be
helpful to isolate them to a few representative test cases.
The warning itself hasn't changed much in GCC 12 but regressions
in it could be due to the jump threading changes that it tends to
be sensitive to.

Martin




Grüße
  Thomas


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955




Re: [PATCH] Fix -Wformat-diag for rs6000 target.

2022-01-13 Thread Martin Sebor via Gcc-patches

On 1/13/22 05:55, Richard Sandiford wrote:

Martin Sebor via Gcc-patches  writes:

On 1/12/22 02:02, Martin Liška wrote:

Hello.

We've got -Wformat-diag for some time and I think we should start using it
in -Werror for GCC bootstrap. The following patch removes last pieces of
the warning
for rs6000 target.

Ready to be installed?
Thanks,
Martin


gcc/ChangeLog:

  * config/rs6000/rs6000-call.c (rs6000_invalid_builtin): Wrap
  keywords and use %qs instead of %<%s%>.
  (rs6000_expand_builtin): Likewise.

gcc/testsuite/ChangeLog:

  * gcc.target/powerpc/bfp/scalar-extract-exp-5.c: Adjust scans in
  testcases.
  * gcc.target/powerpc/bfp/scalar-extract-sig-5.c: Likewise.
  * gcc.target/powerpc/bfp/scalar-insert-exp-11.c: Likewise.
---
   gcc/config/rs6000/rs6000-call.c   | 8 
   .../gcc.target/powerpc/bfp/scalar-extract-exp-5.c | 2 +-
   .../gcc.target/powerpc/bfp/scalar-extract-sig-5.c | 2 +-
   .../gcc.target/powerpc/bfp/scalar-insert-exp-11.c | 2 +-
   4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-call.c
b/gcc/config/rs6000/rs6000-call.c
index c78b8b08c40..becdad73812 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -3307,7 +3307,7 @@ rs6000_invalid_builtin (enum rs6000_gen_builtins
fncode)
    "-mvsx");
     break;
   case ENB_IEEE128_HW:
-  error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name);
+  error ("%qs requires ISA 3.0 IEEE 128-bit floating-point", name);


The instances of the warning where floating point is at the end
of a message aren't correct.  The warning should be relaxed to
allow unhyphenated floating point as a noun (as discussed briefly
last March:
https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566881.html)


Wouldn't it be fair to say that “floating point” in the message above is
really an adjective modifying an implicit noun?  The floating (decimal)
point doesn't itself have 128 bits.

Like you say in the linked message, we could add an explicit noun too.
But the change seems OK as-is to me.


I agree you could say that too.  I didn't mean what I said as
an objection to the change but more as an observation that it
shouldn't be necessary (and an acknowledgment that I haven't
yet done what I said I'd do).

Martin



Thanks,
Richard




Re: [PATCH] Fix -Wformat-diag for rs6000 target.

2022-01-12 Thread Martin Sebor via Gcc-patches

On 1/12/22 02:02, Martin Liška wrote:

Hello.

We've got -Wformat-diag for some time and I think we should start using it
in -Werror for GCC bootstrap. The following patch removes last pieces of 
the warning

for rs6000 target.

Ready to be installed?
Thanks,
Martin


gcc/ChangeLog:

 * config/rs6000/rs6000-call.c (rs6000_invalid_builtin): Wrap
 keywords and use %qs instead of %<%s%>.
 (rs6000_expand_builtin): Likewise.

gcc/testsuite/ChangeLog:

 * gcc.target/powerpc/bfp/scalar-extract-exp-5.c: Adjust scans in
 testcases.
 * gcc.target/powerpc/bfp/scalar-extract-sig-5.c: Likewise.
 * gcc.target/powerpc/bfp/scalar-insert-exp-11.c: Likewise.
---
  gcc/config/rs6000/rs6000-call.c   | 8 
  .../gcc.target/powerpc/bfp/scalar-extract-exp-5.c | 2 +-
  .../gcc.target/powerpc/bfp/scalar-extract-sig-5.c | 2 +-
  .../gcc.target/powerpc/bfp/scalar-insert-exp-11.c | 2 +-
  4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-call.c 
b/gcc/config/rs6000/rs6000-call.c

index c78b8b08c40..becdad73812 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -3307,7 +3307,7 @@ rs6000_invalid_builtin (enum rs6000_gen_builtins 
fncode)

   "-mvsx");
    break;
  case ENB_IEEE128_HW:
-  error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name);
+  error ("%qs requires ISA 3.0 IEEE 128-bit floating-point", name);
    break;
  case ENB_DFP:
    error ("%qs requires the %qs option", name, "-mhard-dfp");
@@ -5589,20 +5589,20 @@ rs6000_expand_builtin (tree exp, rtx target, rtx 
/* subtarget */,

    if (bif_is_nosoft (*bifaddr)
    && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
  {
-  error ("%<%s%> not supported with %<-msoft-float%>",
+  error ("%qs not supported with %<-msoft-float%>",
   bifaddr->bifname);
    return const0_rtx;
  }

    if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
  {
-  error ("%<%s%> is not supported in 32-bit mode", bifaddr->bifname);
+  error ("%qs is not supported in 32-bit mode", bifaddr->bifname);
    return const0_rtx;
  }

    if (bif_is_ibmld (*bifaddr) && !FLOAT128_2REG_P (TFmode))
  {
-  error ("%<%s%> requires % to be IBM 128-bit format",
+  error ("%qs requires % to be IBM 128-bit format",
   bifaddr->bifname);
    return const0_rtx;
  }
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c

index 34184812dc5..1225613b275 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
@@ -14,7 +14,7 @@ get_exponent (__ieee128 *p)
  {
    __ieee128 source = *p;

-  return scalar_extract_exp (source);    /* { dg-error "requires ISA 
3.0 IEEE 128-bit floating point" } */
+  return scalar_extract_exp (source);    /* { dg-error "requires ISA 
3.0 IEEE 128-bit floating-point" } */


This instance of the warning isn't correct.  It should be relaxed
to allow unhyphenated floating point as a noun at the end of
a message, as discussed briefly last March:

https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566881.html

Martin


  }


diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c

index 13c64fc3acf..adf0e4f99df 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
@@ -12,5 +12,5 @@ get_significand (__ieee128 *p)
  {
    __ieee128 source = *p;

-  return (long long int) __builtin_vec_scalar_extract_sig (source); /* 
{ dg-error "requires ISA 3.0 IEEE 128-bit floating point" } */
+  return (long long int) __builtin_vec_scalar_extract_sig (source); /* 
{ dg-error "requires ISA 3.0 IEEE 128-bit floating-point" } */

  }
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c

index a5dd852e60f..6787a67950b 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
@@ -16,5 +16,5 @@ insert_exponent (__ieee128 *significand_p,
    __ieee128 significand = *significand_p;
    unsigned long long int exponent = *exponent_p;

-  return scalar_insert_exp (significand, exponent); /* { dg-error 
"requires ISA 3.0 IEEE 128-bit floating point" } */
+  return scalar_insert_exp (significand, exponent); /* { dg-error 
"requires ISA 3.0 IEEE 128-bit floating-point" } */

  }




Re: [PATCH] Fix -Wformat-diag for s390x target.

2022-01-12 Thread Martin Sebor via Gcc-patches

On 1/12/22 02:03, Martin Liška wrote:

Hello.

We've got -Wformat-diag for some time and I think we should start using it
in -Werror for GCC bootstrap. The following patch removes last pieces of 
the warning

for s390x target.

Ready to be installed?
Thanks,
Martin


gcc/ChangeLog:

 * config/s390/s390-c.c (s390_expand_overloaded_builtin): Wrap
 keyword in quotes.
 (s390_resolve_overloaded_builtin): Remove trailing dot.
 * config/s390/s390.c (s390_const_operand_ok): Use - for range.
 (s390_expand_builtin): Remove trailing dot.
 (s390_emit_prologue): Likewise, use semicolon.
 (s390_option_override_internal): Update keyword.
 * varasm.c (do_assemble_alias): Wrap keyword in quotes.
---
  gcc/config/s390/s390-c.c |  9 +
  gcc/config/s390/s390.c   | 28 ++--
  gcc/varasm.c |  2 +-
  3 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/gcc/config/s390/s390-c.c b/gcc/config/s390/s390-c.c
index 600018421df..10bc6ac8900 100644
--- a/gcc/config/s390/s390-c.c
+++ b/gcc/config/s390/s390-c.c
@@ -484,7 +484,8 @@ s390_expand_overloaded_builtin (location_t loc,
  case S390_OVERLOADED_BUILTIN_s390_vec_step:
    if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
  {
-  error_at (loc, "builtin vec_step can only be used on vector 
types.");

+  error_at (loc, "builtin %qs can only be used on vector types",
+    "vec_step ");


I'd have expected the warning to also trigger for the missing
hyphen in "builtin" (as per the GCC coding conventions) but it
looks like the code only looks for "builtin function".  I must
have done that because of the large number of misspellings.

Regardless, if the name of the function is __builtin_vec_step
(or __builtin_s390_vec_step?) then quoting the entire name of
the function as is conventionally done in the rest of GCC would
be one solution.  Rather than hardcoding the name as a string
there should be a way to do that by passing the right tree to
%qD (or %qF like below).  Based on my reading of the rest of
the file I wonder if this might be the decl:

s390_builtin_decls[bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_s390_vec_step]]

Alternatively, if the preferred name to call the function with
is vec_step then simply vec_step without the "builtin" would
suffice.

(As an aside, there's a spurious space at the end of "vec_step "
above.)


    return error_mark_node;
  }
    return build_int_cst (NULL_TREE,
@@ -905,7 +906,7 @@ s390_resolve_overloaded_builtin (location_t loc,
    if (ob_flags & B_INT)
  {
    error_at (loc,
-    "builtin %qF is for GCC internal use only.",
+    "builtin %qF is for GCC internal use only",
  ob_fndecl);
    return error_mark_node;
  }
@@ -913,7 +914,7 @@ s390_resolve_overloaded_builtin (location_t loc,
  }

    if (ob_flags & B_DEP)
-    warning_at (loc, 0, "builtin %qF is deprecated.", ob_fndecl);
+    warning_at (loc, 0, "builtin %qF is deprecated", ob_fndecl);

    if (!TARGET_VX && (ob_flags & B_VX))
  {
@@ -1021,7 +1022,7 @@ s390_resolve_overloaded_builtin (location_t loc,
  }

    if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
-    warning_at (loc, 0, "%qs matching variant is deprecated.",
+    warning_at (loc, 0, "%qs matching variant is deprecated",
  IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));

    /* Overloaded variants which have MAX set as low level builtin are
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 056002e4a4a..bf96cbf7588 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -766,7 +766,7 @@ s390_const_operand_ok (tree arg, int argnum, int 
op_flags, tree decl)

   argnum, decl, values);
  }
    else
-    error ("constant argument %d for builtin %qF is out of range 
(0..%wu)",
+    error ("constant argument %d for builtin %qF is out of range 
(0-%wu)",

     argnum, decl, (HOST_WIDE_INT_1U << bitwidth) - 1);

    return false;
@@ -783,7 +783,7 @@ s390_const_operand_ok (tree arg, int argnum, int 
op_flags, tree decl)

    || tree_to_shwi (arg) > ((HOST_WIDE_INT_1 << (bitwidth - 1)) - 1))
  {
    error ("constant argument %d for builtin %qF is out of range "
- "(%wd..%wd)", argnum, decl,
+ "(%wd-%wd)", argnum, decl,
   -(HOST_WIDE_INT_1 << (bitwidth - 1)),
   (HOST_WIDE_INT_1 << (bitwidth - 1)) - 1);
    return false;
@@ -832,25 +832,25 @@ s390_expand_builtin (tree exp, rtx target, rtx 
subtarget ATTRIBUTE_UNUSED,

    if ((bflags & B_HTM) && !TARGET_HTM)
  {
    error ("builtin %qF is not supported without %<-mhtm%> "
- "(default with %<-march=zEC12%> and higher).", fndecl);
+ "(default with %<-march=zEC12%> and higher)", fndecl);
    return const0_rtx;
  }
    if (((bflags & B_VX) || (bflags & B_VXE)) && !TARGET_VX)
  {
    error ("builtin %qF requires 

Re: [PATCH] Fix -Wformat-diag for rs6000 target.

2022-01-12 Thread Martin Sebor via Gcc-patches

On 1/12/22 02:02, Martin Liška wrote:

Hello.

We've got -Wformat-diag for some time and I think we should start using it
in -Werror for GCC bootstrap. The following patch removes last pieces of 
the warning

for rs6000 target.

Ready to be installed?
Thanks,
Martin


gcc/ChangeLog:

 * config/rs6000/rs6000-call.c (rs6000_invalid_builtin): Wrap
 keywords and use %qs instead of %<%s%>.
 (rs6000_expand_builtin): Likewise.

gcc/testsuite/ChangeLog:

 * gcc.target/powerpc/bfp/scalar-extract-exp-5.c: Adjust scans in
 testcases.
 * gcc.target/powerpc/bfp/scalar-extract-sig-5.c: Likewise.
 * gcc.target/powerpc/bfp/scalar-insert-exp-11.c: Likewise.
---
  gcc/config/rs6000/rs6000-call.c   | 8 
  .../gcc.target/powerpc/bfp/scalar-extract-exp-5.c | 2 +-
  .../gcc.target/powerpc/bfp/scalar-extract-sig-5.c | 2 +-
  .../gcc.target/powerpc/bfp/scalar-insert-exp-11.c | 2 +-
  4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-call.c 
b/gcc/config/rs6000/rs6000-call.c

index c78b8b08c40..becdad73812 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -3307,7 +3307,7 @@ rs6000_invalid_builtin (enum rs6000_gen_builtins 
fncode)

   "-mvsx");
    break;
  case ENB_IEEE128_HW:
-  error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name);
+  error ("%qs requires ISA 3.0 IEEE 128-bit floating-point", name);


The instances of the warning where floating point is at the end
of a message aren't correct.  The warning should be relaxed to
allow unhyphenated floating point as a noun (as discussed briefly
last March:
https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566881.html)

Martin



    break;
  case ENB_DFP:
    error ("%qs requires the %qs option", name, "-mhard-dfp");
@@ -5589,20 +5589,20 @@ rs6000_expand_builtin (tree exp, rtx target, rtx 
/* subtarget */,

    if (bif_is_nosoft (*bifaddr)
    && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
  {
-  error ("%<%s%> not supported with %<-msoft-float%>",
+  error ("%qs not supported with %<-msoft-float%>",
   bifaddr->bifname);
    return const0_rtx;
  }

    if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
  {
-  error ("%<%s%> is not supported in 32-bit mode", bifaddr->bifname);
+  error ("%qs is not supported in 32-bit mode", bifaddr->bifname);
    return const0_rtx;
  }

    if (bif_is_ibmld (*bifaddr) && !FLOAT128_2REG_P (TFmode))
  {
-  error ("%<%s%> requires % to be IBM 128-bit format",
+  error ("%qs requires % to be IBM 128-bit format",
   bifaddr->bifname);
    return const0_rtx;
  }
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c

index 34184812dc5..1225613b275 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
@@ -14,7 +14,7 @@ get_exponent (__ieee128 *p)
  {
    __ieee128 source = *p;

-  return scalar_extract_exp (source);    /* { dg-error "requires ISA 
3.0 IEEE 128-bit floating point" } */
+  return scalar_extract_exp (source);    /* { dg-error "requires ISA 
3.0 IEEE 128-bit floating-point" } */

  }


diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c

index 13c64fc3acf..adf0e4f99df 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
@@ -12,5 +12,5 @@ get_significand (__ieee128 *p)
  {
    __ieee128 source = *p;

-  return (long long int) __builtin_vec_scalar_extract_sig (source); /* 
{ dg-error "requires ISA 3.0 IEEE 128-bit floating point" } */
+  return (long long int) __builtin_vec_scalar_extract_sig (source); /* 
{ dg-error "requires ISA 3.0 IEEE 128-bit floating-point" } */

  }
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c 
b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c

index a5dd852e60f..6787a67950b 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
@@ -16,5 +16,5 @@ insert_exponent (__ieee128 *significand_p,
    __ieee128 significand = *significand_p;
    unsigned long long int exponent = *exponent_p;

-  return scalar_insert_exp (significand, exponent); /* { dg-error 
"requires ISA 3.0 IEEE 128-bit floating point" } */
+  return scalar_insert_exp (significand, exponent); /* { dg-error 
"requires ISA 3.0 IEEE 128-bit floating-point" } */

  }




PING 4 [PATCH v2 1/2] add -Wuse-after-free

2022-01-10 Thread Martin Sebor via Gcc-patches

Last ping before stage 3 ends:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 1/4/22 11:01, Martin Sebor wrote:

Ping.  (CC'ing Jason as requested.)

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 12/13/21 9:48 AM, Martin Sebor wrote:

Ping.

Jeff, I addressed your comments in the updated patch.  If there
are no other changes is the last revision okay to commit?

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 12/6/21 5:50 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 11/30/21 3:32 PM, Martin Sebor wrote:

Attached is a revised patch with the following changes based
on your comments:

1) Set and use statement uids to determine which statement
    precedes which in the same basic block.
2) Avoid testing flag_isolate_erroneous_paths_dereference.
3) Use post-dominance to decide whether to use the "maybe"
    phrasing vs a definite form.

David raised (and in our offline discussion today reiterated)
an objection to the default setting of the option being
the strictest.  I have not changed that in this revision.
See my rationale for this choice in my reply below:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/583176.html

Martin

On 11/23/21 2:16 PM, Martin Sebor wrote:

On 11/22/21 6:32 PM, Jeff Law wrote:



On 11/1/2021 4:17 PM, Martin Sebor via Gcc-patches wrote:

Patch 1 in the series detects a small subset of uses of pointers
made indeterminate by calls to deallocation functions like free
or C++ operator delete.  To control the conditions the warnings
are issued under the new -Wuse-after-free= option provides three
levels.  At the lowest level the warning triggers only for
unconditional uses of freed pointers and doesn't warn for uses
in equality expressions.  Level 2 warns also for come conditional
uses, and level 3 also for uses in equality expressions.

I debated whether to make level 2 or 3 the default included in
-Wall.  I decided on 3 for two reasons: 1) to raise awareness
of both the problem and GCC's new ability to detect it: using
a pointer after it's been freed, even only in principle, by
a successful call to realloc, is undefined, and 2) because
it's trivial to lower the level either globally, or locally
by suppressing the warning around such misuses.

I've tested the patch on x86_64-linux and by building Glibc
and Binutils/GDB.  It triggers a number of times in each, all
due to comparing invalidated pointers for equality (i.e., level
3).  I have suppressed these in GCC (libiberty) by a #pragma,
and will see how the Glibc folks want to deal with theirs (I
track them in BZ #28521).

The tests contain a number of xfails due to limitations I'm
aware of.  I marked them pr?? until the patch is approved.
I will open bugs for them before committing if I don't resolve
them in a followup.

Martin

gcc-63272-1.diff

Add -Wuse-after-free.

gcc/c-family/ChangeLog

* c.opt (-Wuse-after-free): New options.

gcc/ChangeLog:

* diagnostic-spec.c (nowarn_spec_t::nowarn_spec_t): Handle
OPT_Wreturn_local_addr and OPT_Wuse_after_free_.
* diagnostic-spec.h (NW_DANGLING): New enumerator.
* doc/invoke.texi (-Wuse-after-free): Document new option.
* gimple-ssa-warn-access.cc (pass_waccess::check_call): 
Rename...

(pass_waccess::check_call_access): ...to this.
(pass_waccess::check): Rename...
(pass_waccess::check_block): ...to this.
(pass_waccess::check_pointer_uses): New function.
(pass_waccess::gimple_call_return_arg): New function.
(pass_waccess::warn_invalid_pointer): New function.
(pass_waccess::check_builtin): Handle free and realloc.
(gimple_use_after_inval_p): New function.
(get_realloc_lhs): New function.
(maybe_warn_mismatched_realloc): New function.
(pointers_related_p): New function.
(pass_waccess::check_call): Call check_pointer_uses.
(pass_waccess::execute): Compute and free dominance info.

libcpp/ChangeLog:

* files.c (_cpp_find_file): Substitute a valid pointer for
an invalid one to avoid -Wuse-0after-free.

libiberty/ChangeLog:

* regex.c: Suppress -Wuse-after-free.

gcc/testsuite/ChangeLog:

* gcc.dg/Wmismatched-dealloc-2.c: Avoid -Wuse-after-free.
* gcc.dg/Wmismatched-dealloc-3.c: Same.
* gcc.dg/attr-alloc_size-6.c: Disable -Wuse-after-free.
* gcc.dg/attr-alloc_size-7.c: Same.
* c-c++-common/Wuse-after-free-2.c: New test.
* c-c++-common/Wuse-after-free-3.c: New test.
* c-c++-common/Wuse-after-free-4.c: New test.
* c-c++-common/Wuse-after-free-5.c: New test.
* c-c++-common/Wuse-after-free-6.c: New test.
* c-c++-common/Wuse-after-free-7.c: New test.
* c-c++-common/Wuse-after-free.c: New test.
* g++.dg/warn/Wdangling-pointer.C: New test.
* g++.dg/warn/Wmismatched-dealloc-3.C: New test.
* g++.dg/warn/Wuse-after-free.C: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc 
b/gcc/gimple-ssa-warn-access

PING [PATCH] Use enclosing object size if it's smaller than member [PR 101475]

2022-01-10 Thread Martin Sebor via Gcc-patches

Ping (CC'ing Jason as requested):
https://gcc.gnu.org/pipermail/gcc-patches/2021-December/587033.html

On 1/4/22 10:28, Martin Sebor wrote:

On 12/20/21 12:29 PM, Jeff Law wrote:



On 12/16/2021 12:56 PM, Martin Sebor via Gcc-patches wrote:

Enabling vectorization at -O2 caused quite a few tests for
warnings to start failing in GCC 12.  These tests were xfailed
and bugs were opened to track the problems until they can be
fully analyzed and ultimately fixed before GCC 12 is released.

I've now started going through these and the first such bug
I tackled is PR 102944.  As it turns out, the xfails there
are all due to a known limitation tracked in PR 101475: when
determining the size of a destination for A COMPONENT_REF,
unless asked for the size of the complete object,
compute_objsize() only considers the size of the referenced
member, even when the member is larger than the object would
allow.  This prevents warnings from diagnosing unvectorized
past-the-end accesses to objects in backing buffers (such as
in character arrays or allocated chunks of memory).

Many (though not all) accesses that are vectorized are diagnosed
because there the COMPONENT_REF is replaced by a MEM_REF.  But
because vectorization depends on target-specific things like
alignment requirements, what is and isn't diagnosed also tends
to be target-specific, making these tests quite brittle..

The attached patch corrects this oversight by using the complete
object's size instead of the member when the former is smaller.
Besides improving the out-of-bounds access detection it also
makes the tests behave more consistently across targets.

Tested on x86_64-linux and by building Glibc and verifying
that the change triggers no new warnings.
I must be missing something here.  How can the enclosing object be 
smaller than a member?


When the enclosing object is backed by a buffer of insufficient
size.  The buffer might be a declared character array such as
in the the tests added and modified by the patch, or it might
be dynamically allocated.

Martin




PING 4 [PATCH v2 2/2] add -Wdangling-pointer [PR #63272]

2022-01-10 Thread Martin Sebor via Gcc-patches

Last ping for this stage 1 feature before stage 3 ends:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 1/4/22 11:02, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 12/13/21 9:50 AM, Martin Sebor wrote:

Ping.  This patch, originally submitted on Nov. 1, has not been
reviewed yet.

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 12/6/21 5:51 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 11/30/21 3:55 PM, Martin Sebor wrote:

Attached is a revision of this patch with adjustments for
the changes to the prerequisite patch 1 in the series and
a couple of minor simplifications and slightly improved
test coverage, rested on x86_64-linux.

On 11/1/21 4:18 PM, Martin Sebor wrote:

Patch 2 in this series adds support for detecting the uses of
dangling pointers: those to auto objects that have gone out of
scope.  Like patch 1, to minimize false positives this detection
is very simplistic.  However, thanks to the more deterministic
nature of the problem (all local objects go out of scope) is able
to detect more instances of it.  The approach I used is to simply
search the IL for clobbers that dominate uses of pointers to
the clobbered objects.  If such a use is found that's not
followed by a clobber of the same object the warning triggers.
Similar to -Wuse-after-free, the new -Wdangling-pointer option
has multiple levels: level 1 to detect unconditional uses and
level 2 to flag conditional ones.  Unlike with -Wuse-after-free
there is no use case for testing dangling pointers for
equality, so there is no level 3.

Tested on x86_64-linux and  by building Glibc and Binutils/GDB.
It found no problems outside of the GCC test suite.

As with the first patch in this series, the tests contain a number
of xfails due to known limitations marked with pr??.  I'll
open bugs for them before committing the patch if I don't resolve
them first in a followup.

Martin












Re: [PATCH 1b/6] Add __attribute__((untrusted))

2022-01-06 Thread Martin Sebor via Gcc-patches

On 1/6/22 8:10 AM, David Malcolm wrote:

On Thu, 2021-12-09 at 15:54 -0700, Martin Sebor wrote:

On 11/13/21 1:37 PM, David Malcolm via Gcc-patches wrote:

This patch adds a new:

    __attribute__((untrusted))

for use by the C front-end, intended for use by the Linux kernel for
use with "__user", but which could be used by other operating system
kernels, and potentialy by other projects.


It looks like untrusted is a type attribute (rather than one
that applies to variables and/or function return values or
writeable by-reference arguments).  I find that quite surprising.


FWIW I initially tried implementing it on pointer types, but doing it
on the underlying type was much cleaner.


   I'm used to thinking of trusted vs tainted as dynamic properties
of data so I'm having trouble deciding what to think about
the attribute applying to types.  Can you explain why it's
useful on types?


A type system *is* a way of detecting problems involving dynamic
properties of data.  Ultimately all we have at runtime is a collection
of bits; the toolchain has the concept of types as a way to allow us to
reason about properies of those bits without requiring a full cross-TU
analysis (to try to figure out that e.g. x is, say, a 32 bit unsigned
integer), and to document these properties clearly to human readers of
the code.


I understand that relying on the type system is a way to do it.
It just doesn't seem like a very good way in a loosely typed
language like C (or C++).



I see this as working like a qualifier (rather like "const" and
"volatile"), in that an
   untrusted char *
when dereferenced gives you an
   untrusted char


Dereferencing a const char* yields a const char lvalue that
implicitly converts to an unqualified value of the referenced
object.  The qualifier is lost in the conversion, so modeling
taint/trust this way will also lose the property in the same
contexts.  It sounds to me like the concept you're modeling
might be more akin to a type specifier (maybe like _Atomic,
although that still converts to the underlying type).



The intent is to have a way of treating the values as "actively
hostile", so that code analyzers can assume the worst possible values
for such types (or more glibly, that we're dealing with data from Satan
rather than from Murphy).

Such types are also relevant to infoleaks: writing sensitive
information to an untrusted value can be detected relatively easily
with this approach, by checking the type of the value - the types
express the trust boundary

Doing this with qualifiers allows us to use the C type system to detect
these kinds of issues without having to add a full cross-TU
interprocedural analysis, and documents it to human readers of the
code.   Compare with const-correctness; we can have an analogous
"trust-correctness".


The problem with const-correctness in C is that it's so easily
lost (like with strchr, or in the lvalue-rvalue conversion).
This is also why I'm skeptical of the type-based approach here.





I'd expect the taint property of a type to be quickly lost as
an object of the type is passed through existing APIs (e.g.,
a char array manipulated by string functions like strchr).


FWIW you can't directly pass an attacker-controlled buffer to strchr:
strchr requires there to be a 0-terminator to the array; if the array's
content is untrusted then the attacker might not have 0-terminated it.


strchr is just an example of the many functions that in my mind
make the type-based approach less than ideal.  If the untrusted
string was known to be nul-teminated, strchr still couldn't be
used without losing the property.  Ditto for memchr.  It seems
that all sanitization would either have to be written from
scratch, without relying on existing utility functions, or by
providing wrappers that called the common utility functions
after removing the qualifier from the tainted data even before
the santization was complete.  That would obviously be error-
prone, but it's something that would be made much more robust
by tracking the taint independently of the data type.

Martin



As implemented, the patch doesn't complain about this, though maybe it
should.

The main point here is to support the existing __user annotation used
by the Linux kernel, in particular, copy_from_user and copy_to_user.



(I usually look at tests to help me understand the design of
a change but I couldn't find an answer to my question in those
in the patch.)


The patch kit was rather unclear on this, due to the use of two
different approaches (custom address spaces vs this untrusted
attribute).  Sorry about this.

Patches 4a and 4b in the kit add test-uaccess.h (to
gcc/testsuite/gcc.dg/analyzer) which supplies "__user"; see the tests
that use "test-uaccess.h" in patch 3:
  [PATCH 3/6] analyzer: implement infoleak detection
 https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584377.html
and in patch 5:
  [PATCH 5/6] analyzer: use region::untrusted_p in taint detection

Re: [PATCH] enable -Winvalid-memory-order for C++ [PR99612]

2022-01-05 Thread Martin Sebor via Gcc-patches

On 1/5/22 1:45 AM, Martin Liška wrote:

On 12/8/21 17:49, Martin Sebor via Gcc-patches wrote:

Even with -Wno-system-headers enabled, the -Winvalid-memory-order
code tries to make sure calls to atomic functions with invalid
memory orders are diagnosed even though the C atomic functions
are defined as macros in the  system header.
The warning triggers at all optimization levels, including -O0.

Independently, the core diagnostic enhancements implemented earlier
this year (the warning group control) enable warnings for functions
defined in system headers that are inlined into user code.  This
was done for similar reason as above: because it's desirable to
diagnose invalid calls made from user code to system functions
(e.g., buffer overflows, invalid or mismatched deallocations,
etc.)

However, the C macro solution interferes with the code diagnostic
changes and prevents the invalid memory model warnings from being
issued for the same problems in C++.  In addition, because C++
atomics are ordinary (inline) functions that call the underlying
__atomic_xxx built-ins, the invalid memory orders can only be
detected with both inlining and constant propagation enabled.

The attached patch removes these limitations and enables
-Winvalid-memory-order to trigger even for C++ std::atomic,
(almost) just like it does in C, at all optimization levels
including -O0.

To make that possible I had to move -Winvalid-memory-order from
builtins.c to a GIMPLE pass where it can use context-sensitive
range info at -O0, instead of relying on constant propagation
(only available at -O1 and above).  Although the same approach
could be used to emit better object code for C++ atomics at -O0
(i.e., use the right memory order instead of dropping to seq_cst),
this patch doesn't do that.)

In addition to enabling the warning I've also enhanced it to
include the memory models involved in the diagnosed call (both
the problem ones and the viable alternatives).

Tested on x86_64-linux.

Jonathan, I CC you for two reasons: a) because this solution
is based on your (as well as my own) preference for handling
C++ system headers, and because of our last week's discussion
of the false positives in std::string resulting from the same
choice there.

I don't anticipate this change to lead to the same fallout
because it's unlikely for GCC to synthesize invalid memory
orders out of thin air; and b) because the current solution
can only detect the problems in calls to atomic functions at
-O0 that are declared with attribute always_inline.  This
includes member functions defined in the enclosing atomic
class but not namespace-scope functions.  To make
the detection possible those would also have to be
always_inline.  If that's a change you'd like to see I can
look into making it happen.

Martin


Hello.

I think the patch caused:

gcc/gimple-ssa-warn-access.cc:2844:30: warning: quoted ‘%s’ directive in 
format; use ‘%qs’ instead [-Wformat-diag]


Can you please take a look?


I've fixed it in r12-6271.

Thanks
Martin


PING 3 [PATCH v2 2/2] add -Wdangling-pointer [PR #63272]

2022-01-04 Thread Martin Sebor via Gcc-patches

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 12/13/21 9:50 AM, Martin Sebor wrote:

Ping.  This patch, originally submitted on Nov. 1, has not been
reviewed yet.

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 12/6/21 5:51 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 11/30/21 3:55 PM, Martin Sebor wrote:

Attached is a revision of this patch with adjustments for
the changes to the prerequisite patch 1 in the series and
a couple of minor simplifications and slightly improved
test coverage, rested on x86_64-linux.

On 11/1/21 4:18 PM, Martin Sebor wrote:

Patch 2 in this series adds support for detecting the uses of
dangling pointers: those to auto objects that have gone out of
scope.  Like patch 1, to minimize false positives this detection
is very simplistic.  However, thanks to the more deterministic
nature of the problem (all local objects go out of scope) is able
to detect more instances of it.  The approach I used is to simply
search the IL for clobbers that dominate uses of pointers to
the clobbered objects.  If such a use is found that's not
followed by a clobber of the same object the warning triggers.
Similar to -Wuse-after-free, the new -Wdangling-pointer option
has multiple levels: level 1 to detect unconditional uses and
level 2 to flag conditional ones.  Unlike with -Wuse-after-free
there is no use case for testing dangling pointers for
equality, so there is no level 3.

Tested on x86_64-linux and  by building Glibc and Binutils/GDB.
It found no problems outside of the GCC test suite.

As with the first patch in this series, the tests contain a number
of xfails due to known limitations marked with pr??.  I'll
open bugs for them before committing the patch if I don't resolve
them first in a followup.

Martin










PING 3 [PATCH v2 1/2] add -Wuse-after-free

2022-01-04 Thread Martin Sebor via Gcc-patches

Ping.  (CC'ing Jason as requested.)

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 12/13/21 9:48 AM, Martin Sebor wrote:

Ping.

Jeff, I addressed your comments in the updated patch.  If there
are no other changes is the last revision okay to commit?

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 12/6/21 5:50 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 11/30/21 3:32 PM, Martin Sebor wrote:

Attached is a revised patch with the following changes based
on your comments:

1) Set and use statement uids to determine which statement
    precedes which in the same basic block.
2) Avoid testing flag_isolate_erroneous_paths_dereference.
3) Use post-dominance to decide whether to use the "maybe"
    phrasing vs a definite form.

David raised (and in our offline discussion today reiterated)
an objection to the default setting of the option being
the strictest.  I have not changed that in this revision.
See my rationale for this choice in my reply below:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/583176.html

Martin

On 11/23/21 2:16 PM, Martin Sebor wrote:

On 11/22/21 6:32 PM, Jeff Law wrote:



On 11/1/2021 4:17 PM, Martin Sebor via Gcc-patches wrote:

Patch 1 in the series detects a small subset of uses of pointers
made indeterminate by calls to deallocation functions like free
or C++ operator delete.  To control the conditions the warnings
are issued under the new -Wuse-after-free= option provides three
levels.  At the lowest level the warning triggers only for
unconditional uses of freed pointers and doesn't warn for uses
in equality expressions.  Level 2 warns also for come conditional
uses, and level 3 also for uses in equality expressions.

I debated whether to make level 2 or 3 the default included in
-Wall.  I decided on 3 for two reasons: 1) to raise awareness
of both the problem and GCC's new ability to detect it: using
a pointer after it's been freed, even only in principle, by
a successful call to realloc, is undefined, and 2) because
it's trivial to lower the level either globally, or locally
by suppressing the warning around such misuses.

I've tested the patch on x86_64-linux and by building Glibc
and Binutils/GDB.  It triggers a number of times in each, all
due to comparing invalidated pointers for equality (i.e., level
3).  I have suppressed these in GCC (libiberty) by a #pragma,
and will see how the Glibc folks want to deal with theirs (I
track them in BZ #28521).

The tests contain a number of xfails due to limitations I'm
aware of.  I marked them pr?? until the patch is approved.
I will open bugs for them before committing if I don't resolve
them in a followup.

Martin

gcc-63272-1.diff

Add -Wuse-after-free.

gcc/c-family/ChangeLog

* c.opt (-Wuse-after-free): New options.

gcc/ChangeLog:

* diagnostic-spec.c (nowarn_spec_t::nowarn_spec_t): Handle
OPT_Wreturn_local_addr and OPT_Wuse_after_free_.
* diagnostic-spec.h (NW_DANGLING): New enumerator.
* doc/invoke.texi (-Wuse-after-free): Document new option.
* gimple-ssa-warn-access.cc (pass_waccess::check_call): Rename...
(pass_waccess::check_call_access): ...to this.
(pass_waccess::check): Rename...
(pass_waccess::check_block): ...to this.
(pass_waccess::check_pointer_uses): New function.
(pass_waccess::gimple_call_return_arg): New function.
(pass_waccess::warn_invalid_pointer): New function.
(pass_waccess::check_builtin): Handle free and realloc.
(gimple_use_after_inval_p): New function.
(get_realloc_lhs): New function.
(maybe_warn_mismatched_realloc): New function.
(pointers_related_p): New function.
(pass_waccess::check_call): Call check_pointer_uses.
(pass_waccess::execute): Compute and free dominance info.

libcpp/ChangeLog:

* files.c (_cpp_find_file): Substitute a valid pointer for
an invalid one to avoid -Wuse-0after-free.

libiberty/ChangeLog:

* regex.c: Suppress -Wuse-after-free.

gcc/testsuite/ChangeLog:

* gcc.dg/Wmismatched-dealloc-2.c: Avoid -Wuse-after-free.
* gcc.dg/Wmismatched-dealloc-3.c: Same.
* gcc.dg/attr-alloc_size-6.c: Disable -Wuse-after-free.
* gcc.dg/attr-alloc_size-7.c: Same.
* c-c++-common/Wuse-after-free-2.c: New test.
* c-c++-common/Wuse-after-free-3.c: New test.
* c-c++-common/Wuse-after-free-4.c: New test.
* c-c++-common/Wuse-after-free-5.c: New test.
* c-c++-common/Wuse-after-free-6.c: New test.
* c-c++-common/Wuse-after-free-7.c: New test.
* c-c++-common/Wuse-after-free.c: New test.
* g++.dg/warn/Wdangling-pointer.C: New test.
* g++.dg/warn/Wmismatched-dealloc-3.C: New test.
* g++.dg/warn/Wuse-after-free.C: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc 
b/gcc/gimple-ssa-warn-access.cc

index 63fc27a1487..2065402a2b9 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc

@@ -3397,33 +3417,460 @@ pa

Re: [PATCH] Use enclosing object size if it's smaller than member [PR 101475]

2022-01-04 Thread Martin Sebor via Gcc-patches

On 12/20/21 12:29 PM, Jeff Law wrote:



On 12/16/2021 12:56 PM, Martin Sebor via Gcc-patches wrote:

Enabling vectorization at -O2 caused quite a few tests for
warnings to start failing in GCC 12.  These tests were xfailed
and bugs were opened to track the problems until they can be
fully analyzed and ultimately fixed before GCC 12 is released.

I've now started going through these and the first such bug
I tackled is PR 102944.  As it turns out, the xfails there
are all due to a known limitation tracked in PR 101475: when
determining the size of a destination for A COMPONENT_REF,
unless asked for the size of the complete object,
compute_objsize() only considers the size of the referenced
member, even when the member is larger than the object would
allow.  This prevents warnings from diagnosing unvectorized
past-the-end accesses to objects in backing buffers (such as
in character arrays or allocated chunks of memory).

Many (though not all) accesses that are vectorized are diagnosed
because there the COMPONENT_REF is replaced by a MEM_REF.  But
because vectorization depends on target-specific things like
alignment requirements, what is and isn't diagnosed also tends
to be target-specific, making these tests quite brittle..

The attached patch corrects this oversight by using the complete
object's size instead of the member when the former is smaller.
Besides improving the out-of-bounds access detection it also
makes the tests behave more consistently across targets.

Tested on x86_64-linux and by building Glibc and verifying
that the change triggers no new warnings.
I must be missing something here.  How can the enclosing object be 
smaller than a member?


When the enclosing object is backed by a buffer of insufficient
size.  The buffer might be a declared character array such as
in the the tests added and modified by the patch, or it might
be dynamically allocated.

Martin


[PATCH] Use enclosing object size if it's smaller than member [PR 101475]

2021-12-16 Thread Martin Sebor via Gcc-patches

Enabling vectorization at -O2 caused quite a few tests for
warnings to start failing in GCC 12.  These tests were xfailed
and bugs were opened to track the problems until they can be
fully analyzed and ultimately fixed before GCC 12 is released.

I've now started going through these and the first such bug
I tackled is PR 102944.  As it turns out, the xfails there
are all due to a known limitation tracked in PR 101475: when
determining the size of a destination for A COMPONENT_REF,
unless asked for the size of the complete object,
compute_objsize() only considers the size of the referenced
member, even when the member is larger than the object would
allow.  This prevents warnings from diagnosing unvectorized
past-the-end accesses to objects in backing buffers (such as
in character arrays or allocated chunks of memory).

Many (though not all) accesses that are vectorized are diagnosed
because there the COMPONENT_REF is replaced by a MEM_REF.  But
because vectorization depends on target-specific things like
alignment requirements, what is and isn't diagnosed also tends
to be target-specific, making these tests quite brittle..

The attached patch corrects this oversight by using the complete
object's size instead of the member when the former is smaller.
Besides improving the out-of-bounds access detection it also
makes the tests behave more consistently across targets.

Tested on x86_64-linux and by building Glibc and verifying
that the change triggers no new warnings.

Martin
Use enclosing object size if it's smaller than member [PR 101475].

Resolves:
PR middle-end/101475 - missing -Wstringop-overflow storing a compound literal

gcc/ChangeLog:

	PR middle-end/101475
	* pointer-query.cc (handle_component_ref): Use the size of
	the enclosing object if it's smaller than the member.

gcc/testsuite/ChangeLog:

	PR middle-end/101475
	* gcc.dg/Wstringop-overflow-68.c: Adjust, remove xfails.
	* gcc.dg/Wstringop-overflow-88.c: New test.

diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc
index 4bedf7fca47..644b4de9bcb 100644
--- a/gcc/pointer-query.cc
+++ b/gcc/pointer-query.cc
@@ -1914,36 +1914,40 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype,
   gcc_assert (TREE_CODE (cref) == COMPONENT_REF);
 
   const tree base = TREE_OPERAND (cref, 0);
+  const tree field = TREE_OPERAND (cref, 1);
+  access_ref base_ref = *pref;
+
+  /* Unconditionally determine the size of the base object (it could
+ be smaller than the referenced member).  */
+  if (!compute_objsize_r (base, stmt, addr, 0, _ref, snlim, qry))
+return false;
+
+  /* Add the offset of the member to the offset into the object computed
+ so far.  */
+  tree offset = byte_position (field);
+  if (TREE_CODE (offset) == INTEGER_CST)
+base_ref.add_offset (wi::to_offset (offset));
+  else
+base_ref.add_max_offset ();
+
+  if (!base_ref.ref)
+/* PREF->REF may have been already set to an SSA_NAME earlier
+   to provide better context for diagnostics.  In that case,
+   leave it unchanged.  */
+base_ref.ref = base;
+
   const tree base_type = TREE_TYPE (base);
   if (TREE_CODE (base_type) == UNION_TYPE)
 /* In accesses through union types consider the entire unions
rather than just their members.  */
 ostype = 0;
 
-  tree field = TREE_OPERAND (cref, 1);
-
   if (ostype == 0)
 {
   /* In OSTYPE zero (for raw memory functions like memcpy), use
 	 the maximum size instead if the identity of the enclosing
 	 object cannot be determined.  */
-  if (!compute_objsize_r (base, stmt, addr, ostype, pref, snlim, qry))
-	return false;
-
-  /* Otherwise, use the size of the enclosing object and add
-	 the offset of the member to the offset computed so far.  */
-  tree offset = byte_position (field);
-  if (TREE_CODE (offset) == INTEGER_CST)
-	pref->add_offset (wi::to_offset (offset));
-  else
-	pref->add_max_offset ();
-
-  if (!pref->ref)
-	/* PREF->REF may have been already set to an SSA_NAME earlier
-	   to provide better context for diagnostics.  In that case,
-	   leave it unchanged.  */
-	pref->ref = base;
-
+  *pref = base_ref;
   return true;
 }
 
@@ -1958,6 +1962,11 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype,
 }
 
   set_component_ref_size (cref, pref);
+
+  if (base_ref.size_remaining () < pref->size_remaining ())
+/* Use the base object if it's smaller than the member.  */
+*pref = base_ref;
+
   return true;
 }
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
index 05ea56fca67..4d132394f0f 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
@@ -2,7 +2,7 @@
a larger scalar into a smaller array
Verify overflow by aggregate stores.
{ dg-do compile }
-   { dg-options "-O2" } */
+   { dg-options "-O2 -fno-tree-vectorize" } */
 
 #define A(N) (A ## N)
 #define Ac1 (AC1){ 0 }
@@ -57,19 

PING [PATCH] enable -Winvalid-memory-order for C++ [PR99612]

2021-12-15 Thread Martin Sebor via Gcc-patches

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586402.html

Besides PR 99612 this also fixes the false positive reported
recently in PR 103372.

On 12/8/21 9:49 AM, Martin Sebor wrote:

Even with -Wno-system-headers enabled, the -Winvalid-memory-order
code tries to make sure calls to atomic functions with invalid
memory orders are diagnosed even though the C atomic functions
are defined as macros in the  system header.
The warning triggers at all optimization levels, including -O0.

Independently, the core diagnostic enhancements implemented earlier
this year (the warning group control) enable warnings for functions
defined in system headers that are inlined into user code.  This
was done for similar reason as above: because it's desirable to
diagnose invalid calls made from user code to system functions
(e.g., buffer overflows, invalid or mismatched deallocations,
etc.)

However, the C macro solution interferes with the code diagnostic
changes and prevents the invalid memory model warnings from being
issued for the same problems in C++.  In addition, because C++
atomics are ordinary (inline) functions that call the underlying
__atomic_xxx built-ins, the invalid memory orders can only be
detected with both inlining and constant propagation enabled.

The attached patch removes these limitations and enables
-Winvalid-memory-order to trigger even for C++ std::atomic,
(almost) just like it does in C, at all optimization levels
including -O0.

To make that possible I had to move -Winvalid-memory-order from
builtins.c to a GIMPLE pass where it can use context-sensitive
range info at -O0, instead of relying on constant propagation
(only available at -O1 and above).  Although the same approach
could be used to emit better object code for C++ atomics at -O0
(i.e., use the right memory order instead of dropping to seq_cst),
this patch doesn't do that.)

In addition to enabling the warning I've also enhanced it to
include the memory models involved in the diagnosed call (both
the problem ones and the viable alternatives).

Tested on x86_64-linux.

Jonathan, I CC you for two reasons: a) because this solution
is based on your (as well as my own) preference for handling
C++ system headers, and because of our last week's discussion
of the false positives in std::string resulting from the same
choice there.

I don't anticipate this change to lead to the same fallout
because it's unlikely for GCC to synthesize invalid memory
orders out of thin air; and b) because the current solution
can only detect the problems in calls to atomic functions at
-O0 that are declared with attribute always_inline.  This
includes member functions defined in the enclosing atomic
class but not namespace-scope functions.  To make
the detection possible those would also have to be
always_inline.  If that's a change you'd like to see I can
look into making it happen.

Martin




[PATCH] Check for class type before assuming a type is one [PR103703]

2021-12-14 Thread Martin Sebor via Gcc-patches

The attached patch avoids an ICE when using
the CLASSTYPE_IMPLICIT_INSTANTIATION() macro with an argument
that is not a class type but rather a typename_type.

The test case should trigger a warning but doesn't because
the code doesn't fully handle explicit instantiations.

Martin
Check for class type before assuming a type is one [PR103703].

Resolves:
PR c++/103703 - ICE with -Wmismatched-tags with friends and templates

gcc/cp/ChangeLog:

	PR c++/103703
	* parser.c (class_decl_loc_t::diag_mismatched_tags):

gcc/testsuite/ChangeLog:

	PR c++/103703
	* g++.dg/warn/Wmismatched-tags-9.C: New test.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 52225d46d4e..d21e1d9de6d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -33536,7 +33536,7 @@ class_decl_loc_t::diag_mismatched_tags (tree type_decl)
   class_decl_loc_t *cdlguide = this;
 
   tree type = TREE_TYPE (type_decl);
-  if (CLASSTYPE_IMPLICIT_INSTANTIATION (type))
+  if (CLASS_TYPE_P (type) && CLASSTYPE_IMPLICIT_INSTANTIATION (type))
 {
   /* For implicit instantiations of a primary template look up
 	 the primary or partial specialization and use it as
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C
new file mode 100644
index 000..2712c4de1f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C
@@ -0,0 +1,32 @@
+/* PR c++/103703 - ICE with -Wmismatched-tags with friends and templates
+   { dg-do compile }
+   { dg-options "-Wall -Wmismatched-tags" } */
+
+template 
+struct A
+{
+  struct B { };
+};
+
+template 
+struct C
+{
+  friend class A::B;   // { dg-warning "-Wmismatched-tags" "pr102036" { xfail *-*-* } }
+};
+
+template struct C;
+
+
+template 
+struct D
+{
+  friend class A::B;   // okay, specialized as class below
+};
+
+template <>
+struct A
+{
+  class B { };
+};
+
+template struct D;


Re: [Patch]Enable -Wuninitialized + -ftrivial-auto-var-init for address taken variables

2021-12-14 Thread Martin Sebor via Gcc-patches

On 12/14/21 9:43 AM, Qing Zhao wrote:

Hi,


On Dec 9, 2021, at 12:13 PM, Qing Zhao via Gcc-patches 
 wrote:



+ return;
+
+ /* Get the variable declaration location from the def_stmt.  */
+ var_decl_loc = gimple_location (def_stmt);
+
+ /* The LHS of the call is a temporary variable, we use it as a
+placeholder to record the information on whether the warning
+has been issued or not.  */
+ repl_var = gimple_call_lhs (def_stmt);
+   }
 }
-  if (var == NULL_TREE)
+  if (var == NULL_TREE && var_name == NULL_TREE)
 return;
 /* Avoid warning if we've already done so or if the warning has been
@@ -207,36 +245,56 @@ warn_uninit (opt_code opt, tree t, tree var, const char 
*gmsgid,
   if (((warning_suppressed_p (context, OPT_Wuninitialized)
|| (gimple_assign_single_p (context)
&& get_no_uninit_warning (gimple_assign_rhs1 (context)
-  || get_no_uninit_warning (var))
+  || (var && get_no_uninit_warning (var))
+  || (repl_var && get_no_uninit_warning (repl_var)))
 return;
 /* Use either the location of the read statement or that of the PHI
  argument, or that of the uninitialized variable, in that order,
  whichever is valid.  */
-  location_t location;
+  location_t location = UNKNOWN_LOCATION;
   if (gimple_has_location (context))
 location = gimple_location (context);
   else if (phi_arg_loc != UNKNOWN_LOCATION)
 location = phi_arg_loc;
-  else
+  else if (var)
 location = DECL_SOURCE_LOCATION (var);
+  else if (var_name)
+location = var_decl_loc;
+
   location = linemap_resolve_location (line_table, location,
   LRK_SPELLING_LOCATION, NULL);
 auto_diagnostic_group d;
-  if (!warning_at (location, opt, gmsgid, var))
+  char *gmsgid_final = XNEWVEC (char, strlen (gmsgid) + 5);
+  gmsgid_final[0] = 0;
+  if (var)
+strcat (gmsgid_final, "%qD ");
+  else if (var_name)
+strcat (gmsgid_final, "%qs ");
+  strcat (gmsgid_final, gmsgid);
+
+  if (var && !warning_at (location, opt, gmsgid_final, var))
+return;
+  else if (var_name && !warning_at (location, opt, gmsgid_final, var_name_str))
 return;


Dynamically creating the string seems quite cumbersome here, and
it leaks the allocated block.  I wonder if it might be better to
remove the gmsgid argument from the function and assign it to
one of the literals based on the other arguments.

Since only one of var and var_name is used, I also wonder if
the %qs form could be used for both to simplify the overall
logic.  (I.e., get the IDENTIFIER_POINTER string from var and
use it instead of %qD).


Looks like that using “%qs” + get the IDENTIFIER_POINTER string from var did 
not work very well for the following testing case:

   1 /* PR tree-optimization/45083 */
   2 /* { dg-do compile } */
   3 /* { dg-options "-O2 -Wuninitialized" } */
   4
   5 struct S { char *a; unsigned b; unsigned c; };
   6 extern int foo (const char *);
   7 extern void bar (int, int);
   8
   9 static void
  10 baz (void)
  11 {
  12   struct S cs[1];   /* { dg-message "was declared here" } */
  13   switch (cs->b)/* { dg-warning "cs\[^\n\r\]*\\.b\[^\n\r\]*is used 
uninitialized" } */
  14 {
  15 case 101:
  16   if (foo (cs->a))  /* { dg-warning "cs\[^\n\r\]*\\.a\[^\n\r\]*may be used 
uninitialized" } */
  17 bar (cs->c, cs->b); /* { dg-warning "cs\[^\n\r\]*\\.c\[^\n\r\]*may 
be used uninitialized" } */
  18 }
  19 }
  20
  21 void
  22 test (void)
  23 {
  24   baz ();
  25 }


For the uninitialized usages at line 13, 16, 17: the IDENTIFIER_POINTER string 
of var are:
cs$0$b, cs$0$a ,cs$0$c

However, with %qD, they are printed as cs[0].b, cs[0].a, cs[0].c
But with %qs, they are printed as cs$0$b, cs$0$a ,cs$0$c.

Looks like that %qD does not simplify print out the IDENTIFIER_POINTER string 
directly, it specially handle it for some cases.

I tried to see how %qD specially handle the strings, but didn’t get it so far.

Do you know where the %qD handle this case specially?


In the front end's pretty printer where it handles %D (e.g.,
for C in c_tree_printer in c/c-objc-common.c).  For VARs with
DECL_HAS_DEBUG_EXPR_P (temp) the code uses DECL_DEBUG_EXPR().

There's also print_generic_expr_to_str(tree) that formats a decl
or an expression to a dynamically allocated string (the string
needs to be freed).

Martin



Thanks.

Qing



Both are good suggestions, I will try to update the code based on this.

Thanks again.

Qing










Re: [PATCH RFC] c++: add color to function decl printing

2021-12-14 Thread Martin Sebor via Gcc-patches

On 12/13/21 10:41 PM, Jason Merrill wrote:

On 12/13/21 14:22, Martin Sebor wrote:

On 12/11/21 10:39 PM, Jason Merrill via Gcc-patches wrote:
In reading C++ diagnostics, it's often hard to find the name of the 
function
in the middle of the template header, return type, parameters, and 
template
arguments.  So let's colorize it, and maybe the template argument 
bindings

while we're at it.

I've somewhat arbitrarily chosen bold green for the function name, and
non-bold magenta for the template arguments.  I'm not at all attached to
these choices.

A side-effect is that when this happens in a quote (i.e. %qD), the
rest of the quote after the function name is no longer bold.  I think 
that's
acceptable; returning to the bold would require maintaining a 
colorize stack

instead of the on/off controls we have now.

Any thoughts?


I appreciate the problem but I can't say I find this solution
much of an improvement.  We end up with the same name in up to
four colors: cyan, magenta, green, and black, plus bold versions
of each, depending on where in the text the name appears.  It's
not apparent to me what the different colors mean or how they
help.


You can get the same name in different colors because the diagnostic is 
telling you something different about it, if it's e.g. the name of a 
function we're printing or the source text being indicated as the source 
of the problem.  Is it really unclear what the different colors mean?  I 
find it much easier to read the output for your testcase after this 
patch, as highlighting the function name and lowlighting the template 
args means that


map(_InputIterator, _InputIterator)

stands out as the problematic function.


I understand why you want to draw attention to some parts of
the message and I think that could be useful if done without
relying on color as the sole attribute (think of users of
monochrome or low color terminals or the color-blind), with
more consistency, and without "overloading" existing colors
to mean something subtly different in different contexts (green
is already used for insertion hints, and magenta for warnings).

Given a simple case like this:

  struct A
  {
A (T, T);
  };

  A a (1.0);

t.C:7:14: error: no matching function for call to ‘A::A(double)’
7 | A a (1.0);
  |  ^
t.C:4:3: note: candidate: ‘A::A(T, T) [with T = int]’
4 |   A (T, T);
  |   ^
t.C:4:3: note:   candidate expects 2 arguments, 1 provided
t.C:2:8: note: candidate: ‘constexpr A::A(const A&)’
2 | struct A
  |^
t.C:2:8: note:   no known conversion for argument 1 from ‘double’ to 
‘const A&’

t.C:2:8: note: candidate: ‘constexpr A::A(A&&)’
t.C:2:8: note:   no known conversion for argument 1 from ‘double’ to 
‘A&&’


In the attached screenshot of the output it's reasonably clear
that the green A in the messages names the candidate function.
But even there the function's name is rendered in three colors:
black in the error message, green in the notes, and cyan in
the source code quoted in the notes.  What is not clear is
why. (I can guess that it's simply an artifact of how the GCC
diagnostic machinery works, but that's neither intuitive to
users nor helpful.)

But simple cases are clear even with no colors.  What you'd like
to do is improve the not-so-simple cases like the one with
std::map and that's where the color choices become much less
clear: in long messages with lots of the same names highlighted
in different colors.  It seems especially unhelpful that some
of the text in the same color is bold while other such text is
not (the [with T = ...] parts).  Using the same (or very similar)
colors for entirely different things (warnings and fix-it hints)
compounds the problem.




IMO, the underlying root cause for why relevant details are so
hard to find in G++ messages is that there's so much redundancy
and irrelevant context in the output.  For instance, for this
test case:

#include 

std::map m ("123", "456");

GCC produces 10 screenfuls of output (more than 10 times as many
as Clang).  GCC produces so much more output because it repeats
the full set of included files before each candidate (even though
the headers are the same in each),


Yes, unfortunately the explanation of why each candidate is non-viable 
switches files.  Perhaps we should remember files that we've already 
listed the include path for and avoid repeating it.


I was thinking the same thing.  Paths to system headers could
also be abbreviated (or common prefixes replaced by some symbol).

Perhaps even the repetitive [with T = ...] could be removed in
subsequent messages to reduce the clutter (I notice Clang does
away with either all or most of it altogether in some messages
involving standard containers like std::string or std::vector).




and also because it repeats
the full set of template arguments each time.  E.g., like so:
In file included from 
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:64, 

 

Re: [PATCH] rs6000: Some builtins require IBM-128 long double format (PR103623)

2021-12-13 Thread Martin Sebor via Gcc-patches

On 12/13/21 8:55 AM, Bill Schmidt via Gcc-patches wrote:

Hi!

PR103623 shows that we ICE if __builtin_pack_longdouble or 
__builtin_unpack_longdouble
is used when long double is not defined to be the IBM-128 (double-double) 
format.
To solve this, I introduce a new built-in function attribute "ibmld" that 
enforces
this requirement.

Tested the fix on a powerpc-e300c3-linux-gnu cross.  Bootstrapped and tested on
powerpc64le-linux-gnu with no regressions.  Is this okay for trunk?


Just a minor note about the format of the new error message
below:

...

diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index d9736eaf21c..b6f0c6c4c08 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -15741,6 +15741,13 @@ rs6000_expand_new_builtin (tree exp, rtx target,
return const0_rtx;
  }
  
+  if (bif_is_ibmld (*bifaddr) && !FLOAT128_2REG_P (TFmode))

+{
+  error ("%<%s%> requires long double to be IBM 128-bit format",


as a keyword long double should be quoted in the message.

Martin


Re: [PATCH RFC] c++: add color to function decl printing

2021-12-13 Thread Martin Sebor via Gcc-patches

On 12/11/21 10:39 PM, Jason Merrill via Gcc-patches wrote:

In reading C++ diagnostics, it's often hard to find the name of the function
in the middle of the template header, return type, parameters, and template
arguments.  So let's colorize it, and maybe the template argument bindings
while we're at it.

I've somewhat arbitrarily chosen bold green for the function name, and
non-bold magenta for the template arguments.  I'm not at all attached to
these choices.

A side-effect is that when this happens in a quote (i.e. %qD), the
rest of the quote after the function name is no longer bold.  I think that's
acceptable; returning to the bold would require maintaining a colorize stack
instead of the on/off controls we have now.

Any thoughts?


I appreciate the problem but I can't say I find this solution
much of an improvement.  We end up with the same name in up to
four colors: cyan, magenta, green, and black, plus bold versions
of each, depending on where in the text the name appears.  It's
not apparent to me what the different colors mean or how they
help.

IMO, the underlying root cause for why relevant details are so
hard to find in G++ messages is that there's so much redundancy
and irrelevant context in the output.  For instance, for this
test case:

#include 

std::map m ("123", "456");

GCC produces 10 screenfuls of output (more than 10 times as many
as Clang).  GCC produces so much more output because it repeats
the full set of included files before each candidate (even though
the headers are the same in each), and also because it repeats
the full set of template arguments each time.  E.g., like so:
In file included from 
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:64,
 from 
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_tree.h:63,
 from 
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/map:60,

 from t.C:1:
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_pair.h:558:28: 
note: candidate: ‘templatestd::enable_if<(std::_PCC<((! std::is_same_U1>::value) || (! std::is_same::value)), const char* 
const, const char*>::_MoveConstructiblePair<_U1, _U2>() && (! 
std::_PCC<((! std::is_same::value) || (! 
std::is_same::value)), const char* const, const 
char*>::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type 
 > constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&) 
[with _U2 = _U1; typename std::enable_if<(std::_PCC<((! 
std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), 
_T1, _T2>::_MoveConstructiblePair<_U1, _U2>() && (! std::_PCC<((! 
std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), 
_T1, _T2>::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type 
 = _U2; _T1 = const char* const; _T2 = const char*]’

  558 | explicit constexpr pair(pair<_U1, _U2>&& __p)
  |^~~~

I suspect focusing on reducing the amount of superfluous output
would be a better approach than colorizing the precious nuggets
of useful information in it.

Martin

PS Years ago (in the early 2000's) when interviewing experienced
candidates for C++ template library positions, we'd sit them in
front of a machine with a few C++ compilers and the test case
above.  They were asked to find and explain and fix the problem
in the test case, using any or all of the compilers.  Of all
the people we interviewed only one guy was able to decipher
the errors enough to find the bug.  Looks like this could still
be a good exercise (though we might have to keep them from using
Clang ;)



gcc/cp/ChangeLog:

* error.c (decl_to_string): Add show_color parameter.
(cp_printer): Pass it.
(dump_function_name): Use "fnname" color.
(dump_template_bindings): Use "targs" color.
(struct colorize_guard): New.
(reinit_cxx_pp): Clear pp_show_color.
(cp_print_error_function): Use %qD.
(function_category): Use %qD.

gcc/ChangeLog:

* diagnostic-color.c: Add fnname and targs color entries.
* doc/invoke.texi: Document them.
---
  gcc/doc/invoke.texi|  8 ++
  gcc/cp/error.c | 64 ++
  gcc/diagnostic-color.c |  2 ++
  3 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9b4371b9213..cdfddd75343 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -4803,6 +4803,14 @@ SGR substring for location information, @samp{file:line} 
or
  @vindex quote GCC_COLORS @r{capability}
  SGR substring for information printed within quotes.
  
+@item fnname=

+@vindex fnname GCC_COLORS @r{capability}
+SGR substring for names of C++ functions.
+
+@item targs=
+@vindex targs GCC_COLORS @r{capability}
+SGR substring for C++ function template parameter bindings.
+
  @item fixit-insert=
  @vindex fixit-insert GCC_COLORS @r{capability}
  SGR substring for fix-it hints 

Re: [PATCH] gcc/diagnostic.c: make -Werror message more helpful

2021-12-13 Thread Martin Sebor via Gcc-patches

On 12/12/21 3:13 AM, Andrea Monaco via Gcc-patches wrote:


Hello.


I propose to make that message more verbose.  It sure would have helped
me once.  You don't always have a Web search available :)


Warnings turned into errors have the [-Werror=...] tag at the end
so I'm not sure I see when reiterating -Werror at the end of output
would be helpful.  Can you explain the circumstances when it would
have helped you?

For what it's worth, a change here that I think might be more useful
is printing the number of diagnostics of each kind (e.g., 2 warnings
and 5 errors found).


Andrea Monaco



diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 4ded1760705..8b67662390e 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -156,7 +156,7 @@ default_diagnostic_final_cb (diagnostic_context *context)
/* -Werror was given.  */
if (context->warning_as_error_requested)
 pp_verbatim (context->printer,
-_("%s: all warnings being treated as errors"),
+_("%s: all warnings being treated as errors (-Werror; disable 
with -Wno-error)"),


If this change should move forward, -Werror needs to be quoted
(e.g., passed as an argument to %qs or surrounded in a pair of
%< and %> directives).  The "disable with -Wno-error" part
is superfluous and would not be entirely accurate for warnings
promoted to errors by #pragma GCC diagnostic (those cannot be
demoted back to warnings by -Wno-error).

Martin


  progname);
/* At least one -Werror= was given.  */
else





Re: testsuite: Be more informative for ICEs

2021-12-13 Thread Martin Sebor via Gcc-patches

On 12/10/21 3:42 PM, Thomas Schwinge wrote:

Hi!

OK to push the attached "testsuite: Be more informative for ICEs"?


Adding more detail here seems like a useful improvement to me.

Martin




Grüße
  Thomas


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


0001-testsuite-Be-more-informative-for-ICEs.patch

 From 5ffc2cfc9c6ec6ed0937311377118efd648f0297 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge
Date: Fri, 10 Dec 2021 19:08:26 +0100
Subject: [PATCH] testsuite: Be more informative for ICEs

For example, for the two (FAIL, XFAIL)
'gcc/testsuite/lib/gcc-dg.exp:gcc-dg-test-1' cases:

 -FAIL: g++.dg/modules/xtreme-header-3_a.H -std=c++17 (internal compiler 
error)
 +FAIL: g++.dg/modules/xtreme-header-3_a.H -std=c++17 (internal compiler 
error: tree check: expected var_decl or function_decl or field_decl or 
type_decl or concept_decl or template_decl, have namespace_decl in 
get_merge_kind, at cp/module.cc:10072)

 -FAIL: gfortran.dg/gomp/clauses-1.f90   -O  (internal compiler error)
 +FAIL: gfortran.dg/gomp/clauses-1.f90   -O  (internal compiler error: 
Segmentation fault)

 -XFAIL: c-c++-common/goacc/kernels-decompose-ice-1.c (internal compiler 
error)
 +XFAIL: c-c++-common/goacc/kernels-decompose-ice-1.c (internal compiler 
error: in lower_omp_target, at omp-low.c:13147)

 -XFAIL: g++.dg/cpp1z/constexpr-lambda26.C  -std=c++17 (internal compiler 
error)
 +XFAIL: g++.dg/cpp1z/constexpr-lambda26.C  -std=c++17 (internal compiler 
error: in cxx_eval_constant_expression, at cp/constexpr.c:6954)

That allows for more easily spotting when during development you're trading one
ICE for another.

gcc/testsuite/
* lib/fortran-torture.exp (fortran-torture-compile)
(fortran-torture-execute): Be more informative for ICEs.
* lib/gcc-defs.exp (${tool}_check_compile): Likewise.
* lib/gcc-dg.exp (gcc-dg-test-1): Likewise.
* lib/go-torture.exp (go-torture-compile, go-torture-execute):
Likewise.
---
  gcc/testsuite/lib/fortran-torture.exp | 8 
  gcc/testsuite/lib/gcc-defs.exp| 4 ++--
  gcc/testsuite/lib/gcc-dg.exp  | 6 +++---
  gcc/testsuite/lib/go-torture.exp  | 8 
  4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/gcc/testsuite/lib/fortran-torture.exp 
b/gcc/testsuite/lib/fortran-torture.exp
index d6759aa0b4b..11d73d9f1f7 100644
--- a/gcc/testsuite/lib/fortran-torture.exp
+++ b/gcc/testsuite/lib/fortran-torture.exp
@@ -138,8 +138,8 @@ proc fortran-torture-compile { src option } {
return
  }
  
-if [string match "*internal compiler error*" $comp_output] then {

-   gfortran_fail $testcase "$option (internal compiler error)"
+if [regexp -line -- "internal compiler error.*" $comp_output ice] then {
+   gfortran_fail $testcase "$option ($ice)"
catch { remote_file build delete $output }
return
  }
@@ -263,8 +263,8 @@ proc fortran-torture-execute { src } {
continue
}
  
-	if [string match "*internal compiler error*" $comp_output] then {

-   gfortran_fail $testcase "$option (internal compiler error)"
+   if [regexp -line -- "internal compiler error.*" $comp_output ice] then {
+   gfortran_fail $testcase "$option ($ice)"
catch { remote_file build delete $executable }
continue
}
diff --git a/gcc/testsuite/lib/gcc-defs.exp b/gcc/testsuite/lib/gcc-defs.exp
index d17308d0f86..66df4e1c6aa 100644
--- a/gcc/testsuite/lib/gcc-defs.exp
+++ b/gcc/testsuite/lib/gcc-defs.exp
@@ -38,8 +38,8 @@ proc ${tool}_check_compile {testcase option objname 
gcc_output} {
return 0
  }
  
-if [string match "*internal compiler error*" $gcc_output] then {

-   ${tool}_fail $testcase "$option (internal compiler error)"
+if [regexp -line -- "internal compiler error.*" $gcc_output ice] then {
+   ${tool}_fail $testcase "$option ($ice)"
return 0
  }
  
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp

index 78a6c3651ef..464059608b8 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -315,13 +315,13 @@ proc gcc-dg-test-1 { target_compile prog do_what 
extra_tool_flags } {
  # to avoid a second failure for excess errors.
  # "Error reporting routines re-entered" ICE says "Internal" rather than
  # "internal", so match that too.
-if [string match {*[Ii]nternal compiler error*} $comp_output] {
+if [regexp -line -- {[Ii]nternal compiler error.*} $comp_output ice] {
upvar 2 name name
if { $expect_ice == 0 } {
- fail "$name (internal compiler error)"
+ fail "$name ($ice)"
} else {
  # We expected an ICE and we got it.
- xfail "$name 

PING 2 [PATCH v2 2/2] add -Wdangling-pointer [PR #63272]

2021-12-13 Thread Martin Sebor via Gcc-patches

Ping.  This patch, originally submitted on Nov. 1, has not been
reviewed yet.

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 12/6/21 5:51 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585819.html

On 11/30/21 3:55 PM, Martin Sebor wrote:

Attached is a revision of this patch with adjustments for
the changes to the prerequisite patch 1 in the series and
a couple of minor simplifications and slightly improved
test coverage, rested on x86_64-linux.

On 11/1/21 4:18 PM, Martin Sebor wrote:

Patch 2 in this series adds support for detecting the uses of
dangling pointers: those to auto objects that have gone out of
scope.  Like patch 1, to minimize false positives this detection
is very simplistic.  However, thanks to the more deterministic
nature of the problem (all local objects go out of scope) is able
to detect more instances of it.  The approach I used is to simply
search the IL for clobbers that dominate uses of pointers to
the clobbered objects.  If such a use is found that's not
followed by a clobber of the same object the warning triggers.
Similar to -Wuse-after-free, the new -Wdangling-pointer option
has multiple levels: level 1 to detect unconditional uses and
level 2 to flag conditional ones.  Unlike with -Wuse-after-free
there is no use case for testing dangling pointers for
equality, so there is no level 3.

Tested on x86_64-linux and  by building Glibc and Binutils/GDB.
It found no problems outside of the GCC test suite.

As with the first patch in this series, the tests contain a number
of xfails due to known limitations marked with pr??.  I'll
open bugs for them before committing the patch if I don't resolve
them first in a followup.

Martin








PING 2 [PATCH v2 1/2] add -Wuse-after-free

2021-12-13 Thread Martin Sebor via Gcc-patches

Ping.

Jeff, I addressed your comments in the updated patch.  If there
are no other changes is the last revision okay to commit?

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 12/6/21 5:50 PM, Martin Sebor wrote:

Ping:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585816.html

On 11/30/21 3:32 PM, Martin Sebor wrote:

Attached is a revised patch with the following changes based
on your comments:

1) Set and use statement uids to determine which statement
    precedes which in the same basic block.
2) Avoid testing flag_isolate_erroneous_paths_dereference.
3) Use post-dominance to decide whether to use the "maybe"
    phrasing vs a definite form.

David raised (and in our offline discussion today reiterated)
an objection to the default setting of the option being
the strictest.  I have not changed that in this revision.
See my rationale for this choice in my reply below:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/583176.html

Martin

On 11/23/21 2:16 PM, Martin Sebor wrote:

On 11/22/21 6:32 PM, Jeff Law wrote:



On 11/1/2021 4:17 PM, Martin Sebor via Gcc-patches wrote:

Patch 1 in the series detects a small subset of uses of pointers
made indeterminate by calls to deallocation functions like free
or C++ operator delete.  To control the conditions the warnings
are issued under the new -Wuse-after-free= option provides three
levels.  At the lowest level the warning triggers only for
unconditional uses of freed pointers and doesn't warn for uses
in equality expressions.  Level 2 warns also for come conditional
uses, and level 3 also for uses in equality expressions.

I debated whether to make level 2 or 3 the default included in
-Wall.  I decided on 3 for two reasons: 1) to raise awareness
of both the problem and GCC's new ability to detect it: using
a pointer after it's been freed, even only in principle, by
a successful call to realloc, is undefined, and 2) because
it's trivial to lower the level either globally, or locally
by suppressing the warning around such misuses.

I've tested the patch on x86_64-linux and by building Glibc
and Binutils/GDB.  It triggers a number of times in each, all
due to comparing invalidated pointers for equality (i.e., level
3).  I have suppressed these in GCC (libiberty) by a #pragma,
and will see how the Glibc folks want to deal with theirs (I
track them in BZ #28521).

The tests contain a number of xfails due to limitations I'm
aware of.  I marked them pr?? until the patch is approved.
I will open bugs for them before committing if I don't resolve
them in a followup.

Martin

gcc-63272-1.diff

Add -Wuse-after-free.

gcc/c-family/ChangeLog

* c.opt (-Wuse-after-free): New options.

gcc/ChangeLog:

* diagnostic-spec.c (nowarn_spec_t::nowarn_spec_t): Handle
OPT_Wreturn_local_addr and OPT_Wuse_after_free_.
* diagnostic-spec.h (NW_DANGLING): New enumerator.
* doc/invoke.texi (-Wuse-after-free): Document new option.
* gimple-ssa-warn-access.cc (pass_waccess::check_call): Rename...
(pass_waccess::check_call_access): ...to this.
(pass_waccess::check): Rename...
(pass_waccess::check_block): ...to this.
(pass_waccess::check_pointer_uses): New function.
(pass_waccess::gimple_call_return_arg): New function.
(pass_waccess::warn_invalid_pointer): New function.
(pass_waccess::check_builtin): Handle free and realloc.
(gimple_use_after_inval_p): New function.
(get_realloc_lhs): New function.
(maybe_warn_mismatched_realloc): New function.
(pointers_related_p): New function.
(pass_waccess::check_call): Call check_pointer_uses.
(pass_waccess::execute): Compute and free dominance info.

libcpp/ChangeLog:

* files.c (_cpp_find_file): Substitute a valid pointer for
an invalid one to avoid -Wuse-0after-free.

libiberty/ChangeLog:

* regex.c: Suppress -Wuse-after-free.

gcc/testsuite/ChangeLog:

* gcc.dg/Wmismatched-dealloc-2.c: Avoid -Wuse-after-free.
* gcc.dg/Wmismatched-dealloc-3.c: Same.
* gcc.dg/attr-alloc_size-6.c: Disable -Wuse-after-free.
* gcc.dg/attr-alloc_size-7.c: Same.
* c-c++-common/Wuse-after-free-2.c: New test.
* c-c++-common/Wuse-after-free-3.c: New test.
* c-c++-common/Wuse-after-free-4.c: New test.
* c-c++-common/Wuse-after-free-5.c: New test.
* c-c++-common/Wuse-after-free-6.c: New test.
* c-c++-common/Wuse-after-free-7.c: New test.
* c-c++-common/Wuse-after-free.c: New test.
* g++.dg/warn/Wdangling-pointer.C: New test.
* g++.dg/warn/Wmismatched-dealloc-3.C: New test.
* g++.dg/warn/Wuse-after-free.C: New test.

diff --git a/gcc/gimple-ssa-warn-access.cc 
b/gcc/gimple-ssa-warn-access.cc

index 63fc27a1487..2065402a2b9 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc

@@ -3397,33 +3417,460 @@ pass_waccess::maybe_check_dealloc_call 
(gcall *call)

  }
  }
+/* Return true if either USE_STMT's basic block (that of a 
pointer's use)
+   is

Re: [committed] libstdc++: Disable over-zealous warnings about std::string copies [PR103332]

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

On 12/10/21 9:41 AM, Jakub Jelinek wrote:

On Fri, Dec 10, 2021 at 09:35:50AM -0700, Martin Sebor via Gcc-patches wrote:

The above was just a quick proof of concept experiment.  You're
of course right that the final solution can't be so crude(*).
But if the required functions are always_inline (I think member
functions defined in the body of the class implicitly are


They are not, and can't be, nothing says that such member functions
can't use constructs that make it uninlinable (with always_inline
that would be an error), or are way too large that inlining is not
desirable, etc.  They are just implicitly inline.


The functions we're talking about are the trivial max_size()
members of std::string and allocator traits.  They just return
a constant.

But I see I was wrong, even member functions have to be explicitly
declared always_inline to be guaranteed to be inlined even at -O0.
I don't think that should be an issue for the trivial max_size()
(at least not for the std::string specialization).

Martin


Re: [committed] libstdc++: Disable over-zealous warnings about std::string copies [PR103332]

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

On 12/10/21 3:12 AM, Jonathan Wakely wrote:

On Fri, 10 Dec 2021 at 01:50, Martin Sebor via Libstdc++
 wrote:


On 12/9/21 5:38 PM, Martin Sebor wrote:

On 12/9/21 4:24 PM, Jonathan Wakely via Gcc-patches wrote:

These warnings are triggered by perfectly valid code using std::string.
They're particularly bad when --enable-fully-dynamic-string is used,
because even std::string().begin() will give a warning.

Use pragmas to stop the troublesome warnings for copies done by
std::char_traits.


I'm still experimenting with some of the approaches we discussed
last week, but based on my findings so far this was going to be
my suggestion at lest for now, until or unless the problem turns
out to affect more code than just std::string.


Just minutes after I wrote this I tried following the clue
in the note printed for the test case from PR 103534 with
an enhancement I'm experimenting with:

/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:426:56:
warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’
specified size between 18446744073709551600 and 18446744073709551615
exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
426 | return static_cast(__builtin_memcpy(__s1,
__s2, __n));
|
^
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:426:56:
note: when
‘(.std::__cxx11::basic_string::_M_string_length >
18446744073709551599)’

and adding an assert to string::size():

constexpr
size_type
size() const noexcept
{
  if (_M_string_length >= -1LU >> 1)


I think that will be wrong for 64-bit Windows, where long is 32-bit,
but the string's max size is closer to -1LLU >> 2, and we don't want
to just use -1LLU because that's wrong for 32-bit targets.

Technically the max size is (N - 1)/2 where N is the allocator's max
size, which is PTRDIFF_MAX for std::allocator, SIZE_MAX for allocators
that use the default value from std::allocator_traits, or some other
value that the allocator defines. And the value is reduced
appropriately if sizeof(char_type) > 1.

But if we call this->max_size() which calls _Alloc_traits::max_size()
which potentially calls allocator_type::max_size(), will the compiler
actually make those calls to mark the path unreachable, or will it
just ignore the unreachable if it can't fold all those calls at
compile time?


The above was just a quick proof of concept experiment.  You're
of course right that the final solution can't be so crude(*).
But if the required functions are always_inline (I think member
functions defined in the body of the class implicitly are) then
I'd expect them to be folded at compile time at all optimization
levels.  That's what makes -Winvalid-memory-order work in C++
even at -O0 in the patch I posted earlier this week.

If I still remember my C++-library-fu, even though the standard
requires containers to call max_size() etc., since std::string
is (or can be) an explicit specialization, there shouldn't be
a way for a conforming program to find out if it does, so it
could take shortcuts.  That makes me wonder if it could even
call malloc instead of operator new to get around the problem
with the operator's replaceability.



We could just use __SIZE_MAX__/2 which might be larger than the real
maximum, but will never be smaller.

Jason made a suggestion last week which was that if the warning code
has a range like [2,INT_MAX] or [2UL,ULONG_MAX] that it should assume
that is really [2,infinity] and so not warn. If the upper bound is the
maximum possible value for the type, that's effectively unbounded, and
the warning could assume it's simply not got enough information to
give a useful warning. If it has a range like [2,300] for a buffer of
length 100, that should warn. But [2,infinity] is effectively ranger
saying "I have no idea what this value is" and the warning machinery
should not be issuing warnings on the basis of "I have no idea what
this value is".


The warnings use the lower bound of the access size and ignore
the upper bound.  They use the upper bound of the space remaining
in the destination(s) and ignore the lower bound.

In a call to memcpy (P + I, s, N) the access size is N, and
the space remaining in A is the upper bound of the size of
the largest array A that P points to (it might point to any
number of them, and some might be dynamically allocated with
a size in some range) minus the lower bound of I or zero,
whichever is greater.

This is the most conservative strategy.  There are other
strategies where we could get more true positives but also
more false positives.  Those might be appropriate for
the "maybe" kind of warnings.

Martin


__builtin_unreachable ();
  return _M_string_length;
}

That gets rid of the false positive in this PR.  I realize
the others happen for other reasons but this approach at least
suggests that there might be other ways to 

  1   2   3   4   5   6   7   8   9   10   >