Re: [PATCH v5 0/2] Remove false-positive VLAs when using max()
From: Miguel Ojeda <hidden>
Date: 2018-03-16 20:03:13
Also in:
lkml, netdev
On Fri, Mar 16, 2018 at 8:27 PM, Linus Torvalds [off-list ref] wrote:
On Fri, Mar 16, 2018 at 10:55 AM, Al Viro [off-list ref] wrote:quoted
That's not them, that's C standard regarding ICE.Yes. The C standard talks about "integer constant expression". I know. It's come up in this very thread before. The C standard at no point talks about - or forbids - "variable length arrays". That never comes up in the whole standard, I checked. So we are right now hindered by a _syntactic_ check, without any way to have a _semantic_ check. That's my problem. The warnings are misleading and imply semantics. And apparently there is no way to actually check semantics.quoted
1,100 is *not* a constant expression as far as the standard is concerned,I very much know. But it sure isn't "variable" either as far as the standard is concerned, because the standard doesn't even have that concept (it uses "variable" for argument numbers and for variables). So being pedantic doesn't really change anything.quoted
Would you argue that in void foo(char c) { int a[(c<<1) + 10 - c + 2 - c];Yeah, I don't think that even counts as a constant value, even if it can be optimized to one. I would not at all be unhppy to see __builtin_constant_p() to return zero. But that is very much different from the syntax issue. So I would like to get some way to get both type-checking and constant checking without the annoying syntax issue.quoted
expr, constant_expression is not a constant_expression. And in this particular case the standard is not insane - the only reason for using that is typechecking and _that_ can be achieved without violating 6.6p6: sizeof(expr,0) * 0 + ICE *is* an integer constant expression, and it gives you exact same typechecking. So if somebody wants to play odd games, they can do that just fine, without complicating the logics for compilers...Now that actually looks like a good trick. Maybe we can use that instead of the comma expression that causes problems. And using sizeof() to make sure that __builtin_choose_expression() really gets an integer constant expression and that there should be no ambiguity looks good. Hmm. This works for me, and I'm being *very* careful (those casts to pointer types are inside that sizeof, because it's not an integral type, and non-integral casts are not valid in an ICE either) but somebody needs to check gcc-4.4: #define __typecheck(a,b) \ (!!(sizeof((typeof(a)*)1==(typeof(b)*)1))) #define __no_side_effects(a,b) \ (__builtin_constant_p(a)&&__builtin_constant_p(b)) #define __safe_cmp(a,b) \ (__typecheck(a,b) && __no_side_effects(a,b)) #define __cmp(a,b,op) ((a)op(b)?(a):(b)) #define __cmp_once(a,b,op) ({ \ typeof(a) __a = (a); \ typeof(b) __b = (b); \ __cmp(__a,__b,op); }) #define __careful_cmp(a,b,op) \ __builtin_choose_expr(__safe_cmp(a,b), __cmp(a,b,op), __cmp_once(a,b,op)) #define min(a,b) __careful_cmp(a,b,<) #define max(a,b) __careful_cmp(a,b,>) #define min_t(t,a,b) __careful_cmp((t)(a),(t)(b),<) #define max_t(t,a,b) __careful_cmp((t)(a),(t)(b),>) and yes, it does cause new warnings for that comparison between ‘enum tis_defaults’ and ‘enum tpm2_const’ in drivers/char/tpm/tpm_tis_core.h due to #define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) but technically that warning is actually correct, I'm just confused why gcc cares about the cast placement or something. That warning is easy to fix by turning it into a "max_t(int, enum1, enum2)' and that is technically the right thing to do, it's just not warned about for some odd reason with the current code. Kees - is there some online "gcc-4.4 checker" somewhere? This does seem to work with my gcc. I actually tested some of those files you pointed at now.
I use this one: https://godbolt.org/ Cheers, Miguel