Hi Xi,

On Fri, Jul 05, 2024 at 11:55:05PM GMT, Xi Ruoyao wrote:
> On Fri, 2024-07-05 at 17:23 +0200, Alejandro Colomar wrote:
> > > strtol does have  a "char * restrict * restrict" though, so the
> > > situation is different.   A "char **" and a "const char *"
> > > shouldn't alias anyway. 
> > 
> > Pedantically, it is actually declared as 'char **restrict' (the inner
> > one is not declared as restrict, even though it will be restricted,
> > since there are no other unrestricted pointers).
> 
> So how's the following implementation of strtol (10-based, no negative
> number handling, no overflow handling, ASCII-only) wrong?
> 
> long int my_strtol(const char *restrict nptr, char **restrict endptr)
> {
>   long ret = 0;
> 
>   while (isdigit(*nptr))
>     ret = ret * 10 + (*nptr++ - '0');
> 
>   *endptr = (char *)nptr;
>   return ret;
> }
> 
> There's no dumb thing, there's no restrict violation (unless it's called
> in a stupid way, see below), and there **shouldn't** be a -Wrestrict
> warning.
> 
> If you do
> 
> char *x = NULL;
> strtol((char *)&x, &x, 10);

The restrict in `char **restrict endptr` already protects you from this.
You don't need to make the first parameter also restricted.  See:

        $ cat r.c 
        long alx_strtol(const char *nptr, char **restrict endp);

        int main(void)
        {
                char x = 3;
                char *xp = &x;

                alx_strtol(xp, &xp);  // Fine.
                alx_strtol(xp, (char **) xp);  // Bug.
                alx_strtol((char *) &xp, &xp);  // Bug.
        }
        $ cc -Wall -Wextra -S r.c 
        r.c: In function ‘main’:
        r.c:9:24: warning: passing argument 2 to ‘restrict’-qualified parameter 
aliases with argument 1 [-Wrestrict]
            9 |         alx_strtol(xp, (char **) xp);  // Bug.
              |                        ^~~~~~~~~~~~
        r.c:10:34: warning: passing argument 2 to ‘restrict’-qualified 
parameter aliases with argument 1 [-Wrestrict]
           10 |         alx_strtol((char *) &xp, &xp);  // Bug.
              |                    ~~~~~~~~~~~~  ^~~

Using my proposed prototype wouldn't case any warnings with a powerful
-fanalyzer that would be able to emit diagnostics with the current
prototype.

In strtol(3), there are 3 pointers:

-  nptr
-  *endptr
-  endptr

The first two should be allowed to alias each other (and at the end of
the call, they definitely alias each other).  It is only the third one
which must not alias any of the other, which is why my patch (v2) keeps
that restrict, but removes the other one.

Does that make sense?

Cheers,
Alex

> 
> it'll violate restrict.  Nobody sane should write this, and it's warned
> anyway:
> 
> t.c: In function 'main':
> t.c:6:28: warning: passing argument 2 to 'restrict'-qualified parameter
> aliases with argument 1 [-Wrestrict]
>     6 |         strtol((char *)&x, &x, 10);
>       |                ~~~~~~~~~~  ^~
> 
> -- 
> Xi Ruoyao <xry...@xry111.site>
> School of Aerospace Science and Technology, Xidian University

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature

Reply via email to