Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc

Hi Martin!

On 11/12/22 16:56, Martin Uecker wrote:

Am Samstag, den 12.11.2022, 14:54 + schrieb Joseph Myers:

On Sat, 12 Nov 2022, Alejandro Colomar via Gcc wrote:


Since it's to be used as an rvalue, not as a lvalue, I guess a
postfix-expression wouldn't be the right one.


Several forms of postfix-expression are only rvalues.


(with a special rule about how the identifier is interpreted, different
from the normal scope rules)?  If so, then ".a = 1" could either match
assignment-expression directly (assigning to the postfix-expression ".a").


No, assigning to a function parameter from within another parameter
declaration wouldn't make sense.  They should be readonly.  Side effects
should be forbidden, I think.


Such assignments are already allowed.  In a function definition, the side
effects (including in size expressions for array parameters adjusted to
pointers) take place before entry to the function body.

And, in any case, if you did have a constraint disallowing such
assignments, it wouldn't suffice for syntactic disambiguation (see the
previous point I made about that; I have some rough notes towards a WG14
paper on syntactic disambiguation, but haven't converted them into a
coherent paper).


My idea was to only allow

array-declarator : direct-declarator [ . identifier ]

and only for parameter (not nested inside structs declared
in parameter list) as a first step because it seems this
would exclude all difficult cases.

But if we need to allow more complicated expressions, then
it starts getting more complicated.


Ahh, I guess my work in documenting the man-pages prototypes got me thinking of 
those extensions to the idea.  I don't remember all the details :)




One could could allow more generic expressions, and
specify that the .identifier refers to a
parameter in
the nearest lexically enclosing parameter list or
struct/union.

Then

void foo(struct bar { int x; char c[.x] } a, int x);

would not be allowed (which is good because then we
could later use the syntax also inside structs). If
we apply scoping rules, the following would work:

struct bar { int y; };
void foo(char p[((struct bar){ .y = .x }).y], int x);


Makes sense.



But not:

struct bar { int y; };
void foo(char p[((struct bar){ .y = .y }).y], int y);


Although it clearly is nonsense, I'm not sure I'd make it a constraint 
violation, but rather Undefined Behavior.  How is it different than this?:


$ cat foo.c
int main(void)
{
int i = i;
return i;
}


$ gcc --version | head -n1
gcc (Debian 12.2.0-9) 12.2.0
$ gcc -Wall -Wextra -Werror foo.c
$

$ clang --version | head -n1
Debian clang version 14.0.6
$ clang -Wall -Wextra -Werror foo.c
foo.c:3:10: error: variable 'i' is uninitialized when used within its own 
initialization [-Werror,-Wuninitialized]

int i = i;
~   ^
1 error generated.


BTW, I just freaked out that GCC can't catch this trivial bug.  Should I open a 
bug report?





But there are not only syntactical problems, because
also the type of the parameter might become relevant
and then you can get circular dependencies:

void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);


This seems to be a difficult stone in the road.



I am not sure what would the best way to fix it. One
could specifiy that parameters referred to by
the .identifer syntax must of some integer type and
that the sub-expression .identifer is always
converted to a 'size_t'.


That makes sense, but then overnight some quite useful thing came to my mind 
that would not be possible with this limitation:





char *
stpecpy(char dst[.end - .dst], char *src, char end[1])
{
for (/* void */; dst <= end; dst++) {
*dst = *src++;
if (*dst == '\0')
return dst;
}
/* Truncation detected */
*end = '\0';

#if !defined(NDEBUG)
/* Consume the rest of the input string. */
while (*src++) {};
#endif

return end + 1;
}


stpecpy() is a function similar to strlcat(3) that gets a pointer to the end of 
the array instead of the size of the buffer.  This allows chaining without 
having performance issues[1].


[1]: 


Maybe allowing integral types and pointers would be enough.  However, foreseeing 
that the _Lengthof() proposal (BTW, which paper was it?) will succeed, and 
combining it with this one, _Lengthof(pointer) would ideally give the length of 
the array, so allowing pointers would conflict.


My solution is to disallow sizeof() and _Lengthof() on .identifier.  That could 
be done simply by saying that variably-modified types (VMT) are incomplete types 
until immediately after the comma that follows the parameter declaration. 
Therefore it would be allowed only in the same way as it is allowed right now 
with the normal syntax (i.e., after the parameter has been seen).


BTW, what was the number of

Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc

Hi Martin,

On 11/13/22 14:19, Alejandro Colomar wrote:

But there are not only syntactical problems, because
also the type of the parameter might become relevant
and then you can get circular dependencies:

void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);


This seems to be a difficult stone in the road.



I am not sure what would the best way to fix it. One
could specifiy that parameters referred to by
the .identifer syntax must of some integer type and
that the sub-expression .identifer is always
converted to a 'size_t'.


That makes sense, but then overnight some quite useful thing came to my mind 
that would not be possible with this limitation:





char *
stpecpy(char dst[.end - .dst], char *src, char end[1])
{
 for (/* void */; dst <= end; dst++) {
     *dst = *src++;
     if (*dst == '\0')
     return dst;
 }
 /* Truncation detected */
 *end = '\0';

#if !defined(NDEBUG)
 /* Consume the rest of the input string. */
 while (*src++) {};
#endif

 return end + 1;
}


And I forgot to say it:  Default promotions rank high (probably the highest) in 
my list of most hated features^Wbugs in C.  I wouldn't convert it to size_t, but 
rather follow normal promotion rules.


Since you can use anything between INTMAX_MIN and UINTMAX_MAX for accessing an 
array (which took me some time to understand), I'd also allow the same here. 
So, the type of the expression between [] could perfectly be signed or unsigned.


So, you could use size_t for very high indices, or e.g. ptrdiff_t if you want to 
allow negative numbers.  In the function above, since dst can be a pointer to 
one-past-the-end (it represents a previous truncation; that's why the test 
dst<=end), forcing a size_t conversion would disallow that syntax.


Cheers,

Alex

--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc



On 11/13/22 14:33, Alejandro Colomar wrote:

Hi Martin,

On 11/13/22 14:19, Alejandro Colomar wrote:

But there are not only syntactical problems, because
also the type of the parameter might become relevant
and then you can get circular dependencies:

void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);


This seems to be a difficult stone in the road.



I am not sure what would the best way to fix it. One
could specifiy that parameters referred to by
the .identifer syntax must of some integer type and
that the sub-expression .identifer is always
converted to a 'size_t'.


That makes sense, but then overnight some quite useful thing came to my mind 
that would not be possible with this limitation:





char *
stpecpy(char dst[.end - .dst], char *src, char end[1])


Heh, I got an off-by-one error.  It should be dst[.end - .dst + 1], of course, 
and then the result of the whole expression would be 0, which is fine as size_t.


So, never mind.


{
 for (/* void */; dst <= end; dst++) {
 *dst = *src++;
 if (*dst == '\0')
 return dst;
 }
 /* Truncation detected */
 *end = '\0';

#if !defined(NDEBUG)
 /* Consume the rest of the input string. */
 while (*src++) {};
#endif

 return end + 1;
}




And I forgot to say it:  Default promotions rank high (probably the highest) in 
my list of most hated features^Wbugs in C.  I wouldn't convert it to size_t, but 
rather follow normal promotion rules.


Since you can use anything between INTMAX_MIN and UINTMAX_MAX for accessing an 
array (which took me some time to understand), I'd also allow the same here. So, 
the type of the expression between [] could perfectly be signed or unsigned.


So, you could use size_t for very high indices, or e.g. ptrdiff_t if you want to 
allow negative numbers.  In the function above, since dst can be a pointer to 
one-past-the-end (it represents a previous truncation; that's why the test 
dst<=end), forcing a size_t conversion would disallow that syntax.


Cheers,

Alex



--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Martin Uecker via Gcc
Am Sonntag, den 13.11.2022, 15:02 +0100 schrieb Alejandro Colomar:
> 
> On 11/13/22 14:33, Alejandro Colomar wrote:
> > Hi Martin,
> > 
> > On 11/13/22 14:19, Alejandro Colomar wrote:
> > > > But there are not only syntactical problems, because
> > > > also the type of the parameter might become relevant
> > > > and then you can get circular dependencies:
> > > > 
> > > > void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);
> > > 
> > > This seems to be a difficult stone in the road.

But note that GNU forward declarations solve this nicely.

> > > 
> > > > I am not sure what would the best way to fix it. One
> > > > could specifiy that parameters referred to by
> > > > the .identifer syntax must of some integer type and
> > > > that the sub-expression .identifer is always
> > > > converted to a 'size_t'.
> > > 
> > > That makes sense, but then overnight some quite useful thing came to my 
> > > mind 
> > > that would not be possible with this limitation:
> > > 
> > > 
> > > 
> > > 
> > > char *
> > > stpecpy(char dst[.end - .dst], char *src, char end[1])
> 
> Heh, I got an off-by-one error.  It should be dst[.end - .dst + 1], of 
> course, 
> and then the result of the whole expression would be 0, which is fine as 
> size_t.
> 
> So, never mind.

.end and .dst would have pointer size though.

> > > {
> > >  for (/* void */; dst <= end; dst++) {
> > >  *dst = *src++;
> > >  if (*dst == '\0')
> > >  return dst;
> > >  }
> > >  /* Truncation detected */
> > >  *end = '\0';
> > > 
> > > #if !defined(NDEBUG)
> > >  /* Consume the rest of the input string. */
> > >  while (*src++) {};
> > > #endif
> > > 
> > >  return end + 1;
> > > }
> > And I forgot to say it:  Default promotions rank high (probably the 
> > highest) in 
> > my list of most hated features^Wbugs in C. 

If you replaced them with explicit conversion you then have
to add by hand all the time, I am pretty sure most people
would hate this more. (and it could also hide bugs)

> > I wouldn't convert it to size_t, but 
> > rather follow normal promotion rules.

The point of making it size_t is that you then
do need to know the type of the parameter to make
sense of the expression. If the type matters, then you get
mutual dependencies as in the example above. 

> > Since you can use anything between INTMAX_MIN and UINTMAX_MAX for accessing 
> > an 
> > array (which took me some time to understand), I'd also allow the same 
> > here. So, 
> > the type of the expression between [] could perfectly be signed or unsigned.
> > 
> > So, you could use size_t for very high indices, or e.g. ptrdiff_t if you 
> > want to 
> > allow negative numbers.  In the function above, since dst can be a pointer 
> > to 
> > one-past-the-end (it represents a previous truncation; that's why the test 
> > dst<=end), forcing a size_t conversion would disallow that syntax.

Yes, this then does not work.

Martin


> > Cheers,
> > 
> > Alex
> > 
> 
> -- 
> 



Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc

Hi Martin,

On 11/13/22 15:58, Martin Uecker wrote:

Am Sonntag, den 13.11.2022, 15:02 +0100 schrieb Alejandro Colomar:


On 11/13/22 14:33, Alejandro Colomar wrote:


On 11/13/22 14:19, Alejandro Colomar wrote:

But there are not only syntactical problems, because
also the type of the parameter might become relevant
and then you can get circular dependencies:

void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);


This seems to be a difficult stone in the road.


But note that GNU forward declarations solve this nicely.


How would that above be solved with GNU fwd decl?  I'm guessing that it can't. 
How do you forward declare incomplete VMTs?.







I am not sure what would the best way to fix it. One
could specifiy that parameters referred to by
the .identifer syntax must of some integer type and
that the sub-expression .identifer is always
converted to a 'size_t'.


That makes sense, but then overnight some quite useful thing came to my mind
that would not be possible with this limitation:




char *
stpecpy(char dst[.end - .dst], char *src, char end[1])


Heh, I got an off-by-one error.  It should be dst[.end - .dst + 1], of course,
and then the result of the whole expression would be 0, which is fine as size_t.

So, never mind.


.end and .dst would have pointer size though.


{
  for (/* void */; dst <= end; dst++) {
  *dst = *src++;
  if (*dst == '\0')
  return dst;
  }
  /* Truncation detected */
  *end = '\0';

#if !defined(NDEBUG)
  /* Consume the rest of the input string. */
  while (*src++) {};
#endif

  return end + 1;
}

And I forgot to say it:  Default promotions rank high (probably the highest) in
my list of most hated features^Wbugs in C.


If you replaced them with explicit conversion you then have
to add by hand all the time, I am pretty sure most people
would hate this more. (and it could also hide bugs)


Yeah, casts are also in my top 3 list of things to avoid (although in this case 
there's no bug); maybe a bit over default promotions :)


I didn't mean that all promotions are bad.  Just the gratuitous ones, like 
promoting everything to int before even needing it.  That makes uint16_t a 
theoretical type, because whenever you try to use it, you end up with a signed 
32-bit type; fun heh? :P  _BitInt() solves that for me.


But sure, in (1u + 1l), promotions are fine to get a common type.




I wouldn't convert it to size_t, but
rather follow normal promotion rules.


The point of making it size_t is that you then
do need to know the type of the parameter to make
sense of the expression. If the type matters, then you get
mutual dependencies as in the example above.


Except if you treat incomplete types as... incomplete types (for which sizeof() 
is disallowed by the standard).  And the issue we're having is that the types 
are not yet complete at the time we're using them, aren't they?


Kind of like the initialization order fiasco, but since we're in a limited 
scope, we can detect it.


Cheers,

Alex

--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Martin Uecker via Gcc
Am Sonntag, den 13.11.2022, 16:15 +0100 schrieb Alejandro Colomar:
> Hi Martin,
> 
> On 11/13/22 15:58, Martin Uecker wrote:
> > Am Sonntag, den 13.11.2022, 15:02 +0100 schrieb Alejandro Colomar:
> > > On 11/13/22 14:33, Alejandro Colomar wrote:
> > > > On 11/13/22 14:19, Alejandro Colomar wrote:
> > > > > > But there are not only syntactical problems, because
> > > > > > also the type of the parameter might become relevant
> > > > > > and then you can get circular dependencies:
> > > > > > 
> > > > > > void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);
> > > > > 
> > > > > This seems to be a difficult stone in the road.
> > 
> > But note that GNU forward declarations solve this nicely.
> 
> How would that above be solved with GNU fwd decl?  I'm guessing that it 
> can't. 
> How do you forward declare incomplete VMTs?.

You can't express it. This was my point: it is impossible
to create circular dependencies.

...

> > > > > {
> > > > >   for (/* void */; dst <= end; dst++) {
> > > > >   *dst = *src++;
> > > > >   if (*dst == '\0')
> > > > >   return dst;
> > > > >   }
> > > > >   /* Truncation detected */
> > > > >   *end = '\0';
> > > > > 
> > > > > #if !defined(NDEBUG)
> > > > >   /* Consume the rest of the input string. */
> > > > >   while (*src++) {};
> > > > > #endif
> > > > > 
> > > > >   return end + 1;
> > > > > }
> > > > And I forgot to say it:  Default promotions rank high (probably the 
> > > > highest) in
> > > > my list of most hated features^Wbugs in C.
> > 
> > If you replaced them with explicit conversion you then have
> > to add by hand all the time, I am pretty sure most people
> > would hate this more. (and it could also hide bugs)
> 
> Yeah, casts are also in my top 3 list of things to avoid (although in this 
> case 
> there's no bug); maybe a bit over default promotions :)
> 
> I didn't mean that all promotions are bad.  Just the gratuitous ones, like 
> promoting everything to int before even needing it.  That makes uint16_t a 
> theoretical type, because whenever you try to use it, you end up with a 
> signed 
> 32-bit type; fun heh? :P  _BitInt() solves that for me.

uint16_t is for storing data.  My expectation is that people
will find _BitInt() difficult and error-prone to use for
small sizes.  But maybe I am wrong...

> But sure, in (1u + 1l), promotions are fine to get a common type.
> 
> > > > I wouldn't convert it to size_t, but
> > > > rather follow normal promotion rules.
> > 
> > The point of making it size_t is that you then
> > do need to know the type of the parameter to make
> > sense of the expression. If the type matters, then you get
> > mutual dependencies as in the example above.
> 
> Except if you treat incomplete types as... incomplete types (for which 
> sizeof() 
> is disallowed by the standard).  And the issue we're having is that the types 
> are not yet complete at the time we're using them, aren't they?

It is not an incomplete type. When doing parsing and do not have
a declaration we know nothing about it (not just not the size).
If we assume we know the type (by looking ahead) we get mutual
dependencies.

Also the capability to parse, fold, and do type checking
in one go is something worth preserving in my opinion. 

Martin


> Kind of like the initialization order fiasco, but since we're in a limited 
> scope, we can detect it.






Re: Announcement: Porting the Docs to Sphinx - tomorrow

2022-11-13 Thread Martin Liška
On 11/11/22 22:10, Sandra Loosemore wrote:
> On 11/11/22 13:52, Gerald Pfeifer wrote:
>> On Tue, 8 Nov 2022, Martin Liška wrote:
>>> After the migration, people should be able to build (and install) GCC
>>> even if they miss Sphinx (similar happens now if you miss makeinfo).
>>
>> My nightly *install* (not build) on amd64-unknown-freebsd12.2 broke
>> (from what I can tell due to this - it's been working fine most of
>> the last several 1000 days):
>>
>>    if [ -f doc/g++.1 ]; then rm -f 
>> /home/gerald/gcc-ref12-amd64/share/man/man1/g++.1; /usr/bin/install -c -m 
>> 644 doc/g++.1 /home/gerald/gcc-ref12-amd64/share/man/man1/g++.1; chmod a-x 
>> /home/gerald/gcc-ref12-amd64/share/man/man1/g++.1; fimake -C 
>> /scratch/tmp/gerald/GCC-HEAD/gcc/../doc man 
>> SOURCEDIR=/scratch/tmp/gerald/GCC-HEAD/gcc/fortran/doc/gfortran 
>> BUILDDIR=/scratch/tmp/gerald/OBJ--0954/gcc/doc/gfortran/man SPHINXBUILD=
>>    make[3]: make[3]: don't know how to make w. Stop
>>    make[3]: stopped in /scratch/tmp/gerald/GCC-HEAD/doc
>>    gmake[2]: *** [/scratch/tmp/gerald/GCC-HEAD/gcc/fortran/Make-lang.in:164: 
>> doc/gfortran/man/man/gfortran.1] Error 2
>>    gmake[2]: Leaving directory '/scratch/tmp/gerald/OBJ--0954/gcc'
>>    gmake[1]: *** [Makefile:5310: install-strip-gcc] Error 2
>>    gmake[1]: Leaving directory '/scratch/tmp/gerald/OBJ--0954'
>>    gmake: *** [Makefile:2734: install-strip] Error 2
>>
>> (This appears to be the case with "make -j1 install-strip". Not sure where
>> that "w" target is coming from?)
> 
> I've seen something similar:  "make install" seems to be passing an empty 
> SPHINXBUILD= option to the docs Makefile which is not equipped to handle 
> that.  I know the fix is to get a recent-enough version of Sphinx installed 
> (and I'm going to work on that over the weekend), but it ought to fail more 
> gracefully, or not try to install docs that cannot be built without Sphinx.
> 
> -Sandra
> 

Can you please update the current master, you should get a proper error message.

I'm going to take a look at make install-strip target.

Martin


are most floating point cases in tree_call_nonnegative_warnv_p() wrong for HONOR_NANS?

2022-11-13 Thread Aldy Hernandez via Gcc
Based on discussions in the last few weeks, aren't most of the cases in 
tree_call_nonnegative_warnv_p() wrong when honoring NANS?


For example:
CASE_CFN_ACOS:
CASE_CFN_ACOS_FN:
CASE_CFN_ACOSH:
CASE_CFN_ACOSH_FN:
...
...
  /* Always true.  */
  return true;

But are we guaranteed a +NAN for any NAN input?  I thought we were only 
guaranteed the NAN sign for abs, copysign, assignment, etc?  Similarly 
for most other cases in this function.


Hmmm.  I really think a good chunk of fold-const.cc should live in 
range-ops.  It seems we're duplicating a lot of functionality. 
Similarly to bit-CCP as I've mentioned.


Aldy



Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc

Hi Martin,

On 11/13/22 16:32, Martin Uecker wrote:

Am Sonntag, den 13.11.2022, 16:15 +0100 schrieb Alejandro Colomar:

Hi Martin,

On 11/13/22 15:58, Martin Uecker wrote:

Am Sonntag, den 13.11.2022, 15:02 +0100 schrieb Alejandro Colomar:

On 11/13/22 14:33, Alejandro Colomar wrote:

On 11/13/22 14:19, Alejandro Colomar wrote:

But there are not only syntactical problems, because
also the type of the parameter might become relevant
and then you can get circular dependencies:

void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);


This seems to be a difficult stone in the road.


But note that GNU forward declarations solve this nicely.


How would that above be solved with GNU fwd decl?  I'm guessing that it can't.
How do you forward declare incomplete VMTs?.


You can't express it. This was my point: it is impossible
to create circular dependencies.

...


{
   for (/* void */; dst <= end; dst++) {
   *dst = *src++;
   if (*dst == '\0')
   return dst;
   }
   /* Truncation detected */
   *end = '\0';

#if !defined(NDEBUG)
   /* Consume the rest of the input string. */
   while (*src++) {};
#endif

   return end + 1;
}

And I forgot to say it:  Default promotions rank high (probably the highest) in
my list of most hated features^Wbugs in C.


If you replaced them with explicit conversion you then have
to add by hand all the time, I am pretty sure most people
would hate this more. (and it could also hide bugs)


Yeah, casts are also in my top 3 list of things to avoid (although in this case
there's no bug); maybe a bit over default promotions :)

I didn't mean that all promotions are bad.  Just the gratuitous ones, like
promoting everything to int before even needing it.  That makes uint16_t a
theoretical type, because whenever you try to use it, you end up with a signed
32-bit type; fun heh? :P  _BitInt() solves that for me.


uint16_t is for storing data.  My expectation is that people
will find _BitInt() difficult and error-prone to use for
small sizes.  But maybe I am wrong...


I'm a bit concerned about the suffix to create literals.  I'd have preferred a 
suffix that allowed creating a specific size (instead of the minimum one.  i.e., 
1u16 or something like that.  But otherwise I think it can be better.  I don't 
have in mind a big issue I had a year ago with uint16_t, but it required 3 casts 
in a line.  With _BitInt() I think none (or maybe one, for giving 1 the 
appropriate size) would have been needed.  But we'll see how it works out.






But sure, in (1u + 1l), promotions are fine to get a common type.


I wouldn't convert it to size_t, but
rather follow normal promotion rules.


The point of making it size_t is that you then
do need to know the type of the parameter to make
sense of the expression. If the type matters, then you get
mutual dependencies as in the example above.


Except if you treat incomplete types as... incomplete types (for which sizeof()
is disallowed by the standard).  And the issue we're having is that the types
are not yet complete at the time we're using them, aren't they?


It is not an incomplete type. When doing parsing and do not have
a declaration we know nothing about it (not just not the size).
If we assume we know the type (by looking ahead) we get mutual
dependencies.


Then I'd do the following:  .identifier always has an incomplete type.

I'm preparing a complete description of what I think of the feature.  I'll add 
that.



Also the capability to parse, fold, and do type checking
in one go is something worth preserving in my opinion.


Makes sense.

Thanks for all the help, both!

Cheers,

Alex

--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc

SYNOPSIS:

unary-operator:  . identifier


DESCRIPTION:

-  It is not an lvalue.

   -  This means sizeof() and _Lengthof() cannot be applied to them.
   -  This prevents ambiguity with a designator in an initializer-list within a 
nested braced-initializer.


-  The type of a .identifier is always an incomplete type.

   -  This prevents circular dependencies involving sizeof() or _Lengthof().

-  Shadowing rules apply.

   -  This prevents ambiguity.


EXAMPLES:


-  Valid examples (libc):

   int
   strncmp(const char s1[.n],
   const char s2[.n],
   size_t n);

   int
   cacheflush(void addr[.nbytes],
  int nbytes,
  int cache);

   long
   mbind(void addr[.len],
 unsigned long len,
 int mode,
 const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
  / ULONG_WIDTH],
 unsigned long maxnode, unsigned int flags);

   void *
   bsearch(const void key[.size],
   const void base[.size * .nmemb],
   size_t nmemb,
   size_t size,
   int (*compar)(const void [.size], const void [.size]));

-  Valid examples (my own):

   void
   ustr2str(char dst[restrict .len + 1],
const char src[restrict .len],
size_t len);

   char *
   stpecpy(char dst[.end - .dst + 1],
   char *restrict src,
   char end[1]);

-  Valid examples (from this thread):

   -
   struct s { int a; };
   void f(int a, int b[((struct s) { .a = 1 }).a]);

   Explanation:
   -  Because of shadowing rules, .a=1 refers to the struct member.
  -  Also, if .a referred to the parameter, it would be an rvalue, so 
it wouldn't be valid to assign to it.
   -  (...).a refers to the struct member too, since otherwise an rvalue is 
not expected there.


   -
   void foo(struct bar { int x; char c[.x] } a, int x);

   Explanation:
   -  Because of shadowing rules, [.x] refers to the struct member.

   -
   struct bar { int y; };
   void foo(char p[((struct bar){ .y = .x }).y], int x);

   Explanation:
   -  .x unambiguously refers to the parameter.

-  Undefined behavior:

   -
   struct bar { int y; };
   void foo(char p[((struct bar){ .y = .y }).y], int y);

   Explanation:
   -  Because of shadowing rules, =.y refers to the struct member.
   -  .y=.y means initialize the member with itself (uninitialized use).
   -  (...).y refers to the struct member, since otherwise an rvalue is not 
expected there.


-  Constraint violations:

   -
   void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);

   Explanation:
   -  sizeof(*.b): Cannot get size of incomplete type.
   -  sizeof(*.a): Cannot get size of incomplete type.

   -
   void f(size_t s, int a[sizeof(1) = 1]);

   Explanation:
   -  Cannot assign to rvalue.

   -
   void f(size_t s, int a[.s = 1]);

   Explanation:
   -  Cannot assign to rvalue.

   -
   void f(size_t s, int a[sizeof(.s)]);

   Explanation:
   -  sizeof(.s): Cannot get size of incomplete type.


Does this idea make sense to you?


Cheers,
Alex
--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc



On 11/13/22 17:28, Alejandro Colomar wrote:

SYNOPSIS:

unary-operator:  . identifier


DESCRIPTION:

-  It is not an lvalue.

    -  This means sizeof() and _Lengthof() cannot be applied to them.


Sorry, the above is a thinko.

I wanted to say that, like sizeof() and _Lengthof(), you can't assign to it.

    -  This prevents ambiguity with a designator in an initializer-list within a 
nested braced-initializer.


-  The type of a .identifier is always an incomplete type.

    -  This prevents circular dependencies involving sizeof() or _Lengthof().

-  Shadowing rules apply.

    -  This prevents ambiguity.


EXAMPLES:


-  Valid examples (libc):

    int
    strncmp(const char s1[.n],
    const char s2[.n],
    size_t n);

    int
    cacheflush(void addr[.nbytes],
   int nbytes,
   int cache);

    long
    mbind(void addr[.len],
  unsigned long len,
  int mode,
  const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
   / ULONG_WIDTH],
  unsigned long maxnode, unsigned int flags);

    void *
    bsearch(const void key[.size],
    const void base[.size * .nmemb],
    size_t nmemb,
    size_t size,
    int (*compar)(const void [.size], const void [.size]));

-  Valid examples (my own):

    void
    ustr2str(char dst[restrict .len + 1],
     const char src[restrict .len],
     size_t len);

    char *
    stpecpy(char dst[.end - .dst + 1],
    char *restrict src,
    char end[1]);

-  Valid examples (from this thread):

    -
    struct s { int a; };
    void f(int a, int b[((struct s) { .a = 1 }).a]);

    Explanation:
    -  Because of shadowing rules, .a=1 refers to the struct member.
   -  Also, if .a referred to the parameter, it would be an rvalue, so 
it wouldn't be valid to assign to it.
    -  (...).a refers to the struct member too, since otherwise an rvalue is 
not expected there.


    -
    void foo(struct bar { int x; char c[.x] } a, int x);

    Explanation:
    -  Because of shadowing rules, [.x] refers to the struct member.

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .x }).y], int x);

    Explanation:
    -  .x unambiguously refers to the parameter.

-  Undefined behavior:

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .y }).y], int y);

    Explanation:
    -  Because of shadowing rules, =.y refers to the struct member.
    -  .y=.y means initialize the member with itself (uninitialized use).
    -  (...).y refers to the struct member, since otherwise an rvalue is not 
expected there.


-  Constraint violations:

    -
    void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);

    Explanation:
    -  sizeof(*.b): Cannot get size of incomplete type.
    -  sizeof(*.a): Cannot get size of incomplete type.

    -
    void f(size_t s, int a[sizeof(1) = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[.s = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[sizeof(.s)]);

    Explanation:
    -  sizeof(.s): Cannot get size of incomplete type.


Does this idea make sense to you?


Cheers,
Alex


--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc



On 11/13/22 17:31, Alejandro Colomar wrote:



On 11/13/22 17:28, Alejandro Colomar wrote:

SYNOPSIS:

unary-operator:  . identifier


DESCRIPTION:

-  It is not an lvalue.

    -  This means sizeof() and _Lengthof() cannot be applied to them.


Sorry, the above is a thinko.

I wanted to say that, like sizeof() and _Lengthof(), you can't assign to it.

    -  This prevents ambiguity with a designator in an initializer-list within 
a nested braced-initializer.


-  The type of a .identifier is always an incomplete type.


Or rather, more easily prohibit explicitly using typeof(), sizeof(), and 
_Lengthof() to it.




    -  This prevents circular dependencies involving sizeof() or _Lengthof().

-  Shadowing rules apply.

    -  This prevents ambiguity.


EXAMPLES:


-  Valid examples (libc):

    int
    strncmp(const char s1[.n],
    const char s2[.n],
    size_t n);

    int
    cacheflush(void addr[.nbytes],
   int nbytes,
   int cache);

    long
    mbind(void addr[.len],
  unsigned long len,
  int mode,
  const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
   / ULONG_WIDTH],
  unsigned long maxnode, unsigned int flags);

    void *
    bsearch(const void key[.size],
    const void base[.size * .nmemb],
    size_t nmemb,
    size_t size,
    int (*compar)(const void [.size], const void [.size]));

-  Valid examples (my own):

    void
    ustr2str(char dst[restrict .len + 1],
 const char src[restrict .len],
 size_t len);

    char *
    stpecpy(char dst[.end - .dst + 1],
    char *restrict src,
    char end[1]);

-  Valid examples (from this thread):

    -
    struct s { int a; };
    void f(int a, int b[((struct s) { .a = 1 }).a]);

    Explanation:
    -  Because of shadowing rules, .a=1 refers to the struct member.
   -  Also, if .a referred to the parameter, it would be an rvalue, so 
it wouldn't be valid to assign to it.
    -  (...).a refers to the struct member too, since otherwise an rvalue 
is not expected there.


    -
    void foo(struct bar { int x; char c[.x] } a, int x);

    Explanation:
    -  Because of shadowing rules, [.x] refers to the struct member.

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .x }).y], int x);

    Explanation:
    -  .x unambiguously refers to the parameter.

-  Undefined behavior:

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .y }).y], int y);

    Explanation:
    -  Because of shadowing rules, =.y refers to the struct member.
    -  .y=.y means initialize the member with itself (uninitialized use).
    -  (...).y refers to the struct member, since otherwise an rvalue is 
not expected there.


-  Constraint violations:

    -
    void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);

    Explanation:
    -  sizeof(*.b): Cannot get size of incomplete type.
    -  sizeof(*.a): Cannot get size of incomplete type.

    -
    void f(size_t s, int a[sizeof(1) = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[.s = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[sizeof(.s)]);

    Explanation:
    -  sizeof(.s): Cannot get size of incomplete type.


Does this idea make sense to you?


Cheers,
Alex




--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc



On 11/13/22 17:34, Alejandro Colomar wrote:



On 11/13/22 17:31, Alejandro Colomar wrote:



On 11/13/22 17:28, Alejandro Colomar wrote:

SYNOPSIS:

unary-operator:  . identifier


DESCRIPTION:

-  It is not an lvalue.

    -  This means sizeof() and _Lengthof() cannot be applied to them.


Sorry, the above is a thinko.

I wanted to say that, like sizeof() and _Lengthof(), you can't assign to it.

    -  This prevents ambiguity with a designator in an initializer-list 
within a nested braced-initializer.


-  The type of a .identifier is always an incomplete type.


Or rather, more easily prohibit explicitly using typeof(), sizeof(), and 
_Lengthof() to it.


Hmm, this is not enough.  Pointer arithmetics are interesting, and for that, you 
need to implicitly know the sizeof(*.p).


How about allowing only integral types or pointers to integral types?





    -  This prevents circular dependencies involving sizeof() or _Lengthof().

-  Shadowing rules apply.

    -  This prevents ambiguity.


EXAMPLES:


-  Valid examples (libc):

    int
    strncmp(const char s1[.n],
    const char s2[.n],
    size_t n);

    int
    cacheflush(void addr[.nbytes],
   int nbytes,
   int cache);

    long
    mbind(void addr[.len],
  unsigned long len,
  int mode,
  const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
   / ULONG_WIDTH],
  unsigned long maxnode, unsigned int flags);

    void *
    bsearch(const void key[.size],
    const void base[.size * .nmemb],
    size_t nmemb,
    size_t size,
    int (*compar)(const void [.size], const void [.size]));

-  Valid examples (my own):

    void
    ustr2str(char dst[restrict .len + 1],
 const char src[restrict .len],
 size_t len);

    char *
    stpecpy(char dst[.end - .dst + 1],
    char *restrict src,
    char end[1]);

-  Valid examples (from this thread):

    -
    struct s { int a; };
    void f(int a, int b[((struct s) { .a = 1 }).a]);

    Explanation:
    -  Because of shadowing rules, .a=1 refers to the struct member.
   -  Also, if .a referred to the parameter, it would be an rvalue, 
so it wouldn't be valid to assign to it.
    -  (...).a refers to the struct member too, since otherwise an rvalue 
is not expected there.


    -
    void foo(struct bar { int x; char c[.x] } a, int x);

    Explanation:
    -  Because of shadowing rules, [.x] refers to the struct member.

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .x }).y], int x);

    Explanation:
    -  .x unambiguously refers to the parameter.

-  Undefined behavior:

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .y }).y], int y);

    Explanation:
    -  Because of shadowing rules, =.y refers to the struct member.
    -  .y=.y means initialize the member with itself (uninitialized use).
    -  (...).y refers to the struct member, since otherwise an rvalue is 
not expected there.


-  Constraint violations:

    -
    void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);

    Explanation:
    -  sizeof(*.b): Cannot get size of incomplete type.
    -  sizeof(*.a): Cannot get size of incomplete type.

    -
    void f(size_t s, int a[sizeof(1) = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[.s = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[sizeof(.s)]);

    Explanation:
    -  sizeof(.s): Cannot get size of incomplete type.


Does this idea make sense to you?


Cheers,
Alex






--



OpenPGP_signature
Description: OpenPGP digital signature


[BUG] -Wuninitialized: initialize variable with itself

2022-11-13 Thread Alejandro Colomar via Gcc

Hi,

While discussing some idea for a new feature, I tested the following example 
program:



int main(void)
{
int i = i;
return i;
}


It seems obvious that it should give a warning, and in Clang it does:


$ clang --version | head -n1
Debian clang version 14.0.6

$ clang -Wall -Wextra foo.c
foo.c:3:10: warning: variable 'i' is uninitialized when used within its own 
initialization [-Wuninitialized]

int i = i;
~   ^
1 warning generated.


But for GCC it looks fine:

$ gcc --version | head -n1
gcc (Debian 12.2.0-9) 12.2.0

$ gcc -Wall -Wextra foo.c
$


Until you enable the analyzer, which catches the uninitialized use:


$ gcc -fanalyzer foo.c
foo.c: In function ‘main’:
foo.c:3:13: warning: use of uninitialized value ‘i’ [CWE-457] 
[-Wanalyzer-use-of-uninitialized-value]

3 | int i = i;
  | ^
  ‘main’: events 1-2
|
|3 | int i = i;
|  | ^
|  | |
|  | (1) region created on stack here
|  | (2) use of uninitialized value ‘i’ here
|



I expect that GCC should be able to detect this bug with a simple warning.  The 
analyzer is quite unreadable compared to normal warnings.


Cheers,
Alex

--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [BUG] -Wuninitialized: initialize variable with itself

2022-11-13 Thread Andrew Pinski via Gcc
On Sun, Nov 13, 2022 at 10:36 AM Alejandro Colomar via Gcc
 wrote:
>
> Hi,
>
> While discussing some idea for a new feature, I tested the following example
> program:
>
>
>  int main(void)
>  {
>  int i = i;
>  return i;
>  }

This is NOT a bug but a documented way of having the warning not being there.
See 
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Winit-self
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Wuninitialized
"If you want to warn about code that uses the uninitialized value of
the variable in its own initializer, use the -Winit-self option."

Thanks,
Andrew Pinski

>
>
> It seems obvious that it should give a warning, and in Clang it does:
>
>
>  $ clang --version | head -n1
>  Debian clang version 14.0.6
>
>  $ clang -Wall -Wextra foo.c
>  foo.c:3:10: warning: variable 'i' is uninitialized when used within its 
> own
> initialization [-Wuninitialized]
>  int i = i;
>  ~   ^
>  1 warning generated.
>
>
> But for GCC it looks fine:
>
>  $ gcc --version | head -n1
>  gcc (Debian 12.2.0-9) 12.2.0
>
>  $ gcc -Wall -Wextra foo.c
>  $
>
>
> Until you enable the analyzer, which catches the uninitialized use:
>
>
>  $ gcc -fanalyzer foo.c
>  foo.c: In function ‘main’:
>  foo.c:3:13: warning: use of uninitialized value ‘i’ [CWE-457]
> [-Wanalyzer-use-of-uninitialized-value]
>  3 | int i = i;
>| ^
>‘main’: events 1-2
>  |
>  |3 | int i = i;
>  |  | ^
>  |  | |
>  |  | (1) region created on stack here
>  |  | (2) use of uninitialized value ‘i’ here
>  |
>
>
>
> I expect that GCC should be able to detect this bug with a simple warning.  
> The
> analyzer is quite unreadable compared to normal warnings.
>
> Cheers,
> Alex
>
> --
> 


Re: [BUG] -Wuninitialized: initialize variable with itself

2022-11-13 Thread Andrew Pinski via Gcc
On Sun, Nov 13, 2022 at 10:40 AM Andrew Pinski  wrote:
>
> On Sun, Nov 13, 2022 at 10:36 AM Alejandro Colomar via Gcc
>  wrote:
> >
> > Hi,
> >
> > While discussing some idea for a new feature, I tested the following example
> > program:
> >
> >
> >  int main(void)
> >  {
> >  int i = i;
> >  return i;
> >  }
>
> This is NOT a bug but a documented way of having the warning not being there.
> See 
> https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Winit-self
> https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Wuninitialized
> "If you want to warn about code that uses the uninitialized value of
> the variable in its own initializer, use the -Winit-self option."

I should note the main reason why I Know about this is because I fixed
this feature years ago (at least for C front-end)
and added the option to disable the feature.

>
> Thanks,
> Andrew Pinski
>
> >
> >
> > It seems obvious that it should give a warning, and in Clang it does:
> >
> >
> >  $ clang --version | head -n1
> >  Debian clang version 14.0.6
> >
> >  $ clang -Wall -Wextra foo.c
> >  foo.c:3:10: warning: variable 'i' is uninitialized when used within 
> > its own
> > initialization [-Wuninitialized]
> >  int i = i;
> >  ~   ^
> >  1 warning generated.
> >
> >
> > But for GCC it looks fine:
> >
> >  $ gcc --version | head -n1
> >  gcc (Debian 12.2.0-9) 12.2.0
> >
> >  $ gcc -Wall -Wextra foo.c
> >  $
> >
> >
> > Until you enable the analyzer, which catches the uninitialized use:
> >
> >
> >  $ gcc -fanalyzer foo.c
> >  foo.c: In function ‘main’:
> >  foo.c:3:13: warning: use of uninitialized value ‘i’ [CWE-457]
> > [-Wanalyzer-use-of-uninitialized-value]
> >  3 | int i = i;
> >| ^
> >‘main’: events 1-2
> >  |
> >  |3 | int i = i;
> >  |  | ^
> >  |  | |
> >  |  | (1) region created on stack here
> >  |  | (2) use of uninitialized value ‘i’ here
> >  |
> >
> >
> >
> > I expect that GCC should be able to detect this bug with a simple warning.  
> > The
> > analyzer is quite unreadable compared to normal warnings.
> >
> > Cheers,
> > Alex
> >
> > --
> > 


Re: [BUG] -Wuninitialized: initialize variable with itself

2022-11-13 Thread Alejandro Colomar via Gcc

Hi Andrew!

On 11/13/22 19:41, Andrew Pinski wrote:

On Sun, Nov 13, 2022 at 10:40 AM Andrew Pinski  wrote:


On Sun, Nov 13, 2022 at 10:36 AM Alejandro Colomar via Gcc
 wrote:


Hi,

While discussing some idea for a new feature, I tested the following example
program:


  int main(void)
  {
  int i = i;
  return i;
  }


This is NOT a bug but a documented way of having the warning not being there.
See 
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Winit-self
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Wuninitialized
"If you want to warn about code that uses the uninitialized value of
the variable in its own initializer, use the -Winit-self option."


I should note the main reason why I Know about this is because I fixed
this feature years ago (at least for C front-end)
and added the option to disable the feature.


I'm curious: what are the reasons why one would want to disable such a warning?
Why is it not in -Wall or -Wextra?

Thanks,

Alex

--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [BUG] -Wuninitialized: initialize variable with itself

2022-11-13 Thread Andrew Pinski via Gcc
On Sun, Nov 13, 2022 at 10:41 AM Andrew Pinski  wrote:
>
> On Sun, Nov 13, 2022 at 10:40 AM Andrew Pinski  wrote:
> >
> > On Sun, Nov 13, 2022 at 10:36 AM Alejandro Colomar via Gcc
> >  wrote:
> > >
> > > Hi,
> > >
> > > While discussing some idea for a new feature, I tested the following 
> > > example
> > > program:
> > >
> > >
> > >  int main(void)
> > >  {
> > >  int i = i;
> > >  return i;
> > >  }
> >
> > This is NOT a bug but a documented way of having the warning not being 
> > there.
> > See 
> > https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Winit-self
> > https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#index-Wuninitialized
> > "If you want to warn about code that uses the uninitialized value of
> > the variable in its own initializer, use the -Winit-self option."
>
> I should note the main reason why I Know about this is because I fixed
> this feature years ago (at least for C front-end)
> and added the option to disable the feature.

When I says years, it was 19 years ago even, see
https://gcc.gnu.org/PR5582
and
https://gcc.gnu.org/PR10538
and
https://gcc.gnu.org/r0-52301-g3390f9c9bef0be

Thanks,


>
> >
> > Thanks,
> > Andrew Pinski
> >
> > >
> > >
> > > It seems obvious that it should give a warning, and in Clang it does:
> > >
> > >
> > >  $ clang --version | head -n1
> > >  Debian clang version 14.0.6
> > >
> > >  $ clang -Wall -Wextra foo.c
> > >  foo.c:3:10: warning: variable 'i' is uninitialized when used within 
> > > its own
> > > initialization [-Wuninitialized]
> > >  int i = i;
> > >  ~   ^
> > >  1 warning generated.
> > >
> > >
> > > But for GCC it looks fine:
> > >
> > >  $ gcc --version | head -n1
> > >  gcc (Debian 12.2.0-9) 12.2.0
> > >
> > >  $ gcc -Wall -Wextra foo.c
> > >  $
> > >
> > >
> > > Until you enable the analyzer, which catches the uninitialized use:
> > >
> > >
> > >  $ gcc -fanalyzer foo.c
> > >  foo.c: In function ‘main’:
> > >  foo.c:3:13: warning: use of uninitialized value ‘i’ [CWE-457]
> > > [-Wanalyzer-use-of-uninitialized-value]
> > >  3 | int i = i;
> > >| ^
> > >‘main’: events 1-2
> > >  |
> > >  |3 | int i = i;
> > >  |  | ^
> > >  |  | |
> > >  |  | (1) region created on stack here
> > >  |  | (2) use of uninitialized value ‘i’ here
> > >  |
> > >
> > >
> > >
> > > I expect that GCC should be able to detect this bug with a simple 
> > > warning.  The
> > > analyzer is quite unreadable compared to normal warnings.
> > >
> > > Cheers,
> > > Alex
> > >
> > > --
> > > 


Re: are most floating point cases in tree_call_nonnegative_warnv_p() wrong for HONOR_NANS?

2022-11-13 Thread Aldy Hernandez via Gcc
I suppose most of the calls to tree_expr_nonnegative_p that apply to
floats in match.pd and tree-ssa-math-opts.cc are guarded by
!HONOR_NANS || tree_expr_nonnegative_p.  Still feels kinda delicate...

Aldy

On Sun, Nov 13, 2022 at 4:56 PM Aldy Hernandez  wrote:
>
> Based on discussions in the last few weeks, aren't most of the cases in
> tree_call_nonnegative_warnv_p() wrong when honoring NANS?
>
> For example:
>  CASE_CFN_ACOS:
>  CASE_CFN_ACOS_FN:
>  CASE_CFN_ACOSH:
>  CASE_CFN_ACOSH_FN:
> ...
> ...
>/* Always true.  */
>return true;
>
> But are we guaranteed a +NAN for any NAN input?  I thought we were only
> guaranteed the NAN sign for abs, copysign, assignment, etc?  Similarly
> for most other cases in this function.
>
> Hmmm.  I really think a good chunk of fold-const.cc should live in
> range-ops.  It seems we're duplicating a lot of functionality.
> Similarly to bit-CCP as I've mentioned.
>
> Aldy



Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

2022-11-13 Thread Alejandro Colomar via Gcc
On 11/13/22 17:56, Alejandro Colomar wrote:>>> On 11/13/22 17:28, Alejandro 
Colomar wrote:

SYNOPSIS:

unary-operator:  . identifier


DESCRIPTION:

-  It is not an lvalue.

    -  This means sizeof() and _Lengthof() cannot be applied to them.


Sorry, the above is a thinko.

I wanted to say that, like sizeof() and _Lengthof(), you can't assign to it.

    -  This prevents ambiguity with a designator in an initializer-list 
within a nested braced-initializer.


-  The type of a .identifier is always an incomplete type.


Or rather, more easily prohibit explicitly using typeof(), sizeof(), and 
_Lengthof() to it.


Hmm, this is not enough.  Pointer arithmetics are interesting, and for that, you 
need to implicitly know the sizeof(*.p).


How about allowing only integral types or pointers to integral types?


I've been thinking about keeping the number of passes as low as possible, while 
allowing most useful expressions:


Maybe forcing some ordering can help:

-  The type of a .initializer is complete after the opening parenthesis of the 
function-declarator (if it refers to a parameter) or after the opening brace of 
a braced-initializer, if it refers to a struct/union member, except when the 
type is a variably-modified type, which will be complete after the closing 
parenthesis or brace respectively.


I'm not sure I got the wording precisely, or if I covered all cases (like types 
that cannot be completed for other reasons, even after the closing ')' or '}'.








    -  This prevents circular dependencies involving sizeof() or _Lengthof().

-  Shadowing rules apply.

    -  This prevents ambiguity.


EXAMPLES:


-  Valid examples (libc):

    int
    strncmp(const char s1[.n],
    const char s2[.n],
    size_t n);

    int
    cacheflush(void addr[.nbytes],
   int nbytes,
   int cache);

    long
    mbind(void addr[.len],
  unsigned long len,
  int mode,
  const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
   / ULONG_WIDTH],
  unsigned long maxnode, unsigned int flags);

    void *
    bsearch(const void key[.size],
    const void base[.size * .nmemb],
    size_t nmemb,
    size_t size,
    int (*compar)(const void [.size], const void [.size]));

-  Valid examples (my own):

    void
    ustr2str(char dst[restrict .len + 1],
 const char src[restrict .len],
 size_t len);

    char *
    stpecpy(char dst[.end - .dst + 1],
    char *restrict src,
    char end[1]);

-  Valid examples (from this thread):

    -
    struct s { int a; };
    void f(int a, int b[((struct s) { .a = 1 }).a]);

    Explanation:
    -  Because of shadowing rules, .a=1 refers to the struct member.
   -  Also, if .a referred to the parameter, it would be an rvalue, 
so it wouldn't be valid to assign to it.
    -  (...).a refers to the struct member too, since otherwise an 
rvalue is not expected there.


    -
    void foo(struct bar { int x; char c[.x] } a, int x);

    Explanation:
    -  Because of shadowing rules, [.x] refers to the struct member.

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .x }).y], int x);

    Explanation:
    -  .x unambiguously refers to the parameter.

-  Undefined behavior:

    -
    struct bar { int y; };
    void foo(char p[((struct bar){ .y = .y }).y], int y);

    Explanation:
    -  Because of shadowing rules, =.y refers to the struct member.
    -  .y=.y means initialize the member with itself (uninitialized use).
    -  (...).y refers to the struct member, since otherwise an rvalue is 
not expected there.


-  Constraint violations:

    -
    void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);

    Explanation:
    -  sizeof(*.b): Cannot get size of incomplete type.
    -  sizeof(*.a): Cannot get size of incomplete type.

    -
    void f(size_t s, int a[sizeof(1) = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[.s = 1]);

    Explanation:
    -  Cannot assign to rvalue.

    -
    void f(size_t s, int a[sizeof(.s)]);


This should actually be valid.



    Explanation:
    -  sizeof(.s): Cannot get size of incomplete type.


Does this idea make sense to you?


Cheers,
Alex








--



OpenPGP_signature
Description: OpenPGP digital signature


[whish] -Wunterminated-string-initialization: new warning

2022-11-13 Thread Alejandro Colomar via Gcc

Hi!

I'd like to get warnings if I write the following code:

char foo[3] = "foo";

It's hard to keep track of sizes to make sure that the string literals always 
initialize to terminated strings.  It seems something that should be easy to 
implement in the compiler.


A morecomplex case where it's harder to keep track of sizes is:

static const char  log_levels[][8] = {
"alert",
"error",
"warn",
"notice",
"info",
"debug",
};

Here, 8 works now (and 7 too, but for aligmnent reasons I chose 8).  If tomorrow 
we add or change an entry, It'll be hard to keep it safe.  Such a warning would 
help a lot.



An example program is:

$ cat str.c
char two[2] = "foo";   // 'f' 'o'
char   three[3] = "foo";   // 'f' 'o' 'o'
charfour[4] = "foo";   // 'f' 'o' 'o' '\0'
charfive[5] = "foo";   // 'f' 'o' 'o' '\0' '\0'
char implicit[] = "foo";   // 'f' 'o' 'o' '\0'

$ cc -Wall -Wextra str.c
str.c:1:19: warning: initializer-string for array of ‘char’ is too long
1 | char two[2] = "foo";   // 'f' 'o'
  |   ^
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/Scrt1.o: 
in function `_start':

(.text+0x17): undefined reference to `main'
collect2: error: ld returned 1 exit status


Here, I'd like that with the new warning, 'three' would also get warned.

Cheers,

Alex
--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [whish] -Wunterminated-string-initialization: new warning

2022-11-13 Thread Andrew Pinski via Gcc
On Sun, Nov 13, 2022 at 1:57 PM Alejandro Colomar via Gcc
 wrote:
>
> Hi!
>
> I'd like to get warnings if I write the following code:
>
> char foo[3] = "foo";

This should be easy to add as it is already part of the -Wc++-compat
option as for C++ it is invalid code.

:2:19: warning: initializer-string for array of 'char' is too long
2 | char two[2] = "foo";   // 'f' 'o'
  |   ^
:3:19: warning: initializer-string for array of 'char' is too
long for C++ [-Wc++-compat]
3 | char   three[3] = "foo";   // 'f' 'o' 'o'
  |   ^


... (for your more complex case [though I needed to modify one of the
strings to exactly 8]

:5:7: warning: initializer-string for array of 'char' is too
long for C++ [-Wc++-compat]
5 |   "01234567",
  |   ^~

  else if (warn_cxx_compat
   && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
warning_at (init_loc, OPT_Wc___compat,
("initializer-string for array of %qT "
 "is too long for C++"), typ1);

That is the current code which does this warning even so it is just a
matter of adding an option to c-family/c.opt and then having
c++-compat enable it and using that new option here.

Thanks,
Andrew Pinski

>
> It's hard to keep track of sizes to make sure that the string literals always
> initialize to terminated strings.  It seems something that should be easy to
> implement in the compiler.
>
> A morecomplex case where it's harder to keep track of sizes is:
>
> static const char  log_levels[][8] = {
>  "alert",
>  "error",
>  "warn",
>  "notice",
>  "info",
>  "debug",
> };
>
> Here, 8 works now (and 7 too, but for aligmnent reasons I chose 8).  If 
> tomorrow
> we add or change an entry, It'll be hard to keep it safe.  Such a warning 
> would
> help a lot.
>
>
> An example program is:
>
> $ cat str.c
> char two[2] = "foo";   // 'f' 'o'
> char   three[3] = "foo";   // 'f' 'o' 'o'
> charfour[4] = "foo";   // 'f' 'o' 'o' '\0'
> charfive[5] = "foo";   // 'f' 'o' 'o' '\0' '\0'
> char implicit[] = "foo";   // 'f' 'o' 'o' '\0'
>
> $ cc -Wall -Wextra str.c
> str.c:1:19: warning: initializer-string for array of ‘char’ is too long
>  1 | char two[2] = "foo";   // 'f' 'o'
>|   ^
> /usr/bin/ld: 
> /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/Scrt1.o:
> in function `_start':
> (.text+0x17): undefined reference to `main'
> collect2: error: ld returned 1 exit status
>
>
> Here, I'd like that with the new warning, 'three' would also get warned.
>
> Cheers,
>
> Alex
> --
> 


gcc-13-20221113 is now available

2022-11-13 Thread GCC Administrator via Gcc
Snapshot gcc-13-20221113 is now available on
  https://gcc.gnu.org/pub/gcc/snapshots/13-20221113/
and on various mirrors, see http://gcc.gnu.org/mirrors.html for details.

This snapshot has been generated from the GCC 13 git branch
with the following options: git://gcc.gnu.org/git/gcc.git branch master 
revision 58e7732a2feddf475e72b232bf16494d84a41acf

You'll find:

 gcc-13-20221113.tar.xz   Complete GCC

  SHA256=689a917fba115df44842a4d2d84ee6860f0e9971dfc6f9bc20d6dbebf51d6fea
  SHA1=1feb2da292354ff311dc52b4251b3e8815d283a9

Diffs from 13-20221106 are available in the diffs/ subdirectory.

When a particular snapshot is ready for public consumption the LATEST-13
link is updated and a message is sent to the gcc list.  Please do not use
a snapshot before it has been announced that way.


Revert Sphinx documentation [Was: Issues with Sphinx]

2022-11-13 Thread Martin Liška
Hi.

The situation with the Sphinx migration went out of control. The TODO list
overwhelmed me and there are road-blocks that can't be easily fixed with what
Sphinx currently supports. That would require addition of an upstream support 
and
a possible new Sphinx release.

Let me summarize the biggest road blocks:

1) PR107634 - documentation is divided among much files than it used to be; plus
   the current filenames tend to be very long
2) Index page regressions: PR107643 and PR107651
3) PR107656 - c::macro and c::function does replace [Macro:], [Target Hook:] 
well
4) Makefile.am, build system issues: missing support for lib*/Makefile.am and 
various
   limitation when it comes to 'make install-*'. Moreover, gcc_release 
--enable-generated-files-in-srcdir
   is not supported yet.

Plus, there are other issues linked in PR107655 and we face the issue that
many web links (to GCC documentation) are in the wild and should not become 404.

I would like to apologize to anybody who wasted a time with adoption to the 
Sphinx format
which we be reverted eventually. Special thanks belongs to all people who 
helped me and
prepared various patches.

I'm going to revert the patchset during today (Monday) and I'll send a patch 
with a couple
of new changes that landed in the period of time we used Sphinx.

Thank you for your understanding.
Martin


Re: C89isms in the test suite

2022-11-13 Thread Sam James via Gcc


> On 21 Oct 2022, at 09:40, Florian Weimer via Gcc  wrote:
> 
> What should we do about these when they are not relevant to what's being
> tested?  For example, gcc/testsuite/gcc.c-torture/execute/ieee/mzero6.c
> has this:
> 
>  int main ()
>  {
>if (__builtin_copysign (1.0, func (0.0 / -5.0, 10)) != -1.0)
>  abort ();
>exit (0);
>  }
> 
> but no include files, so abort and exit are implicitly declared.
> 
> Should we inject a header with -include with the most common
> declarations (which includes at least abort and exit)?  Or add the
> missing #include directives?  But the latter might not work for
> freestanding targets.
> 
> Implicit ints and function declarations without prototypes are also
> common (not just for main).
> 
> Other tests look like they might be intended to be built in C89 mode,
> e.g.  gcc/testsuite/gcc.c-torture/compile/386.c, although it's not
> immediately obvious to me what they test.

Would you be able to backport 6be2672e4ee41c566a9e072088a263bab5f7
and 885b6660c17fb91980b5682514ef54668e544b02 to the active <13
branches?

Thanks,
sam


signature.asc
Description: Message signed with OpenPGP