On Fri, Sep 18, 2020 at 12:33:56PM -0700, Linus Torvalds wrote: > Luc, > we've been making kernel structures use flexible arrays as a > cleanliness thing, but it turns out that it doesn't find bugs that it > _should_ find. > > We have that nice "struct_size()" macro to determine the size of the > flexible structure given the number of elements, which uses "offsetof > + n*members". But sadly standard C still allows the (nonsensical) > 'sizeof()' to be used - and I merged another fix for that just today. > > Ok, so that's a C standard problem, but it's something that sparse > *could* warn about. Yes, sure. I think that sparse treats flexible arrays exactly as if zero-sized, without the notion of 'incomplete type' and without check that it is the last member, so without any warnings. This, I think, explains the results in your tests here under. I'll look to add some warnings for array declaration and sizeof() (explicit or implicit). > Comments? Appended is a kind of test-case for odd situations that > sparse happily and silently generates nonsensical code for (just > tested with test-linearize). Thanks, these tests make a lot of sense. It should be noted, though, that test-linearize gives exactly the same result as GCC & clang (sparse IR 100% matches x86 & ARM64 here). I also have 2 questions here under. > struct bad { > unsigned long long a; > char b[]; > }; ... > // The layout is odd > // The code does "info->align_size = 0" for unsized arrays, but it > still works? > int odd(struct bad *a) > { > return __alignof__(*a); > } This returns 8. What's odd here? The 0 align_size is only for the member 'b' and shouldn't have any effect on the alignment of the whole struct. What am I missing? > // Arrays of flexible-array structures are pretty nonsensical > // Plus we don't even optimize the constant return. Sad. > int not_nice(struct bad p[2]) > { > return (void *)(p+1) - (void *)p; > } I don't understand what you mean by 'optimize the constant return'. test-linearize returns the only possible sensical answer (if the size of the structure is accepted to be 8): not_nice: .L2: <entry-point> ret.32 $8 What could be optimized here? -- Luc