On Sat, Jul 06, 2024 at 08:10:28AM GMT, Alejandro Colomar wrote:
> Hi Xi,
> 
> On Sat, Jul 06, 2024 at 10:24:16AM GMT, Xi Ruoyao wrote:
> > On Sat, 2024-07-06 at 00:02 +0200, Alejandro Colomar wrote:
> > > That's precisely the case with strtol(3): it doesn't access any objects
> > > through *endptr, and so that pointer need not be restrict.
> > > 
> > > Then, nptr is a read-only pointer, so is doesn't matter either if it's
> > > accessed or not.
> > 
> > Restrict allows to reorder any writes to other objects with an read from
> > nptr then. In strtol at least errno can be written, and depending on the
> > implementation of locale things there may be more.
> 
> This does not apply here, I think.  Let's include errno in the list of
> objects that strtol(3) takes, and list their access modes:
> 
> -  nptr               access(read_only)
> -  *endptr    access(none)
> -  endptr     access(read_write) [it checks for NULL; I had forgotten]

Sorry, I was right the first time; it's write_only.  The NULL check is
on the pointer; not the pointee.

> -  errno      access(read_write)
> 
> In the callee:
> ~~~~~~~~~~~~~~
> 
> The access modes are known by the callee, because of course it knows
> what it does, so even without the attributes, it knows that.
> 
> strtol(3) cannot write to errno until it has parsed the string.  And
> once it knows it has failed (so wants to set errno), it has no reasons
> to read nptr again.  Thus, even without knowing if 'errno' and 'nptr'
> are the same thing, there's nothing that could be optimized.
> 
> *endptr is access(none), so it is implicitly restricted even without
> specifying restrict on it; the callee couldn't care less about it.
> 
> endptr is 'restrict', so it can be treated separately from the rest.
> 
> In the caller:
> ~~~~~~~~~~~~~~
> 
> We can't specify the access mode of *endptr nor errno, so the caller
> must assume they are read_write.
> 
> endptr is 'restrict', but this is only useful for having warnings
> against dumb things such as strtol(x, x, 0).  Other than that, the
> caller knows what it has passed in endptr, so it knows it's a different
> thing.
> 
> The caller also knows that it hasn't passed errno as nptr.
> 
> Then we must make a distinction in what the caller passes in *endptr:
> 
> *endptr is uninitialized:
> ~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> The caller knows that nptr is restricted even without the qualifier,
> since all other objects are either restricted, or known to be different.
> 
> *endptr points to the same thing as nptr:
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> Regardless of the 'restrict' qualifier being specified or not, the
> caller has no way to determine if the callee accesses the object via
> nptr or via *endptr, so it must assume the worst case: *endptr; and so
> it must assume it could have written to it (since *endptr is non-const
> --and even if it were const, as you said, it means nothing--).
> 
> 
> So, even considering errno in the game, I don't see any difference if we
> specify nptr to be restrict or not.
> 
> Thanks for the feedback!  I'll incorporate the discussion about errno in
> the paper for WG14.
> 
> Have a lovely day!
> Alex
> 
> > 
> > TBAA does not help here because char aliases with anything.
> 
> -- 
> <https://www.alejandro-colomar.es/>



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

Attachment: signature.asc
Description: PGP signature

Reply via email to