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