On Thu, Jun 02, 2016 at 09:23:16AM +0200, Jakub Jelinek wrote: > Also, perhaps just a documentation thing, it would be good to clarify the > NULL last argument. From the POV of generating efficient code, I think we > should say something that the last argument (for the GNU builtins) must be > either a pointer to a valid object, or NULL/nullptr constant cast expression > cast to a pointer type, but nothing else. That is actually what your patch > implements. But, I'd like to make sure that > int *p = NULL; > if (__builtin_add_overflow (a, b, p)) > ... > is actually not valid, otherwise we unnecessarily pessimize many of the GNU > style calls (those that don't pass &var), where instead of > tem = ADD_OVERFLOW (a, b); > *p = REALPART_EXPR (tem); > ovf = IMAGPART_EXPR (tem); > we'd need to emit instead > tem = ADD_OVERFLOW (a, b); > ovf = IMAGPART_EXPR (tem); > if (p != NULL) > *p = REALPART_EXPR (tem);
Though, perhaps that is too ugly, that it has different semantics for __builtin_add_overflow (a, b, (int *) NULL) and for int *p = NULL; __builtin_add_overflow (a, b, p) Maybe the cleanest would be to just add 3 extra builtins, again, typegeneric, __builtin_{add,sub,mul}_overflow_p where either the arguments would be instead of integertype1, integertype2, integertype3 * rather integertype1, integertype2, integertype3 and we'd only care about the type, not value, of the last argument, so use it like __builtin_add_overflow_p (a, b, (__typeof ((a) + (b))) 0) or handle those 3 similarly to __builtin_va_arg, and use __builtin_add_overflow_p (a, b, int); I think I prefer the former though. Jakub