So the kernel was trying to use a unnamed struct to mark a group of fields as being 'const', and while gcc is perfectly happy with that, it turns out clang is not. And while testing, I notice that sparse is also not happy with it. Stupid test-case: struct dummy { const struct { int a, b; }; int c; }; void test(struct dummy *a) { a->a = a->c; } and gcc will report t.c: In function ‘test’: t.c:10:7: error: assignment of member ‘a’ in read-only object 10 | a->a = a->c; | ^ which is the helpful message we're looking for in the kernel, but clang and sparse both silently accept this. Presumably for very similar reasons. (And when I talk about 'const', obviously all the same issues hold wrt 'volatile' too) Basically, I see two possibilities (a) since the const is there in the unnamed sub-struct, we can "fix" it at evaluate lo time, in find_identifier(). We'd have to add a "unsigned int qual" as an argument - initially zero - to "find_identifier()", and then in the recursive unnamed union/struct case we'd or in the qualifiers for this one. And then we'd modify the symbol result as per the qualifier when we return it. Honestly, (a) strikes me as ugly and wrong, but it might be simpler than what I think might be the right model: (b) examine_struct_union_type() knows when it is traversing an unnamed union, and when it does that examine_symbol_type(member); it would then add the modifiers after-the-fact. Obviously, the third possibility is to say "ok, clang also gets this wrong, the clang people are trying to argue that the standard is not clear about it, and sparse might as well ignore this until it's a bigger problem". Linus