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] - 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/>
Attachment:
signature.asc
Description: PGP signature