Hi Jonathan, On Fri, Jul 05, 2024 at 08:52:30PM GMT, Jonathan Wakely wrote: > > > > > > > It **shouldn't**. strtol will only violate restrict if it's wrongly > > > > > > > implemented, or something dumb is done like "strtol((const char*) &p, > > > > > > > &p, 0)". > > > > > > > > > > > > > > See my previous reply. > > > > > > > > That's not right. See my reply to yours, Xi. The restrict in > > > > > > > > char **endptr > > > > > > > > already prevents calls such as strtol(x, x, 0). > > > > > > That seems to contradict footnote 153 in C23. > > > > Did you mean a different footnote number? > > No. > > > > > Here's 153 in N3047: > > That draft is nearly two years old. > > > > > 153) An implementation can delay the choice of which integer type until > > all enumeration constants have been seen. > > > > which seems completely unrelated. > > Because you're looking at a draft from nearly two years ago. Try N3220. Ahhh, sorry! Indeed. Let's quote it here, for others to not need to find it: 153) In other words, E depends on the value of P itself rather than on the value of an object referenced indirectly through P. For example, if identifier p has type (int **restrict), then the pointer expressions p and p+1 are based on the restricted pointer object designated by p, but the pointer expressions *p and p[1] are not. I don't think footnote 153 is problematic here. Let's have this prototype: long int alx_strtol(const char *nptr, char **restrict endptr, int base); and let's discuss some example of bad usage: char str[] = "1"; s = str; alx_strtol(s, (char **)s, 0); According to 153, the pointer expression endptr is based on the restricted pointer object, but *endptr and nptr are not. The user has passed s as endptr, and also s as nptr. Thus, the object s is being accessed via a restricted pointer, endptr, and a non-restricted one, nptr. That's UB. Let's see a different example of bad usage: char str[] = "1"; s = str; alx_strtol((char *)&s, &s, 0); For similar reasons, it's also UB. The compiler diagnoses both: $ cat r.c long alx_strtol(const char *s, char **restrict endp, int base); int main(void) { char x = 3; char *xp = &x; alx_strtol(xp, &xp, 0); // Fine. alx_strtol(xp, (char **) xp, 0); // Bug. alx_strtol((char *) &xp, &xp, 0); // 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, 0); // Bug. | ^~~~~~~~~~~~ r.c:10:34: warning: passing argument 2 to ‘restrict’-qualified parameter aliases with argument 1 [-Wrestrict] 10 | alx_strtol((char *) &xp, &xp, 0); // Bug. | ~~~~~~~~~~~~ ^~~ Cheers, Alex -- <https://www.alejandro-colomar.es/>
Attachment:
signature.asc
Description: PGP signature