Closed tjpalmer closed 6 years ago
That's a cool initiative!
Yeah, this has been a pain point. I want to support this eventually but I haven't found a design I'm totally happy about. It's the flattening of namespaces combined with the distinct types that's particularly awkward for C11-style anon structs/unions. You can treat it as a low-level feature that defines a single flat type but with offsets computed in a nonstandard way, but that wouldn't jive with the C backend, although it would be a good fit for a machine code backend.
Now that I'm writing more code in Ion, I'm starting to feel the pain, so I'll probably start thinking harder about how I want to solve it.
This is particularly easy one. Just do the deep search for the field on anon types. And leave everything left the sizes and alignment to the prev compiler. What you even do?
Yes, of course everything is "easy", but you are ignoring the cases that make it attractive to treat a struct with anonymous substructs/subunions as flat. E.g. aggregate initializers/compound literals. I'm pretty sure the flat approach is the right one, where the anon structs/unions just alter the memory layout. The only thing that really has to change is then the code that constructs a type from a type decl and completes a type with field offsets and size, and then everything else will work exactly as before.
will work exactly as before
Just FYI, C appears to support a non-flattened syntax for initializing a struct with an anonymous struct inside it. When struct foo
is defined as below, (struct foo){ 1, {2, 3} }
is the same as (struct foo){ 1, 2, 3 }
. I don't know if this is a compiler extension or part of the C language, and of course Ion doesn't have to support it since it does seem a bit redundant.
Here is the code I tested at godbolt.org:
struct foo {
int x;
struct {
int y;
int z;
};
};
struct foo x(int x) {
if (x)
return (struct foo){ 1, {2, 3} };
else
return (struct foo){ 1, 2, 3 };
}
Yeah, I think that reflects how C actually represents them and the flattened initializer version is the thing C always lets you do for nested aggregate initializers, e.g. you can initialize an array of structs with a flat initializer as well.
Oh, I get the point about compound literals. Right now I do not support those. And question was about anonymous aggregates. Of course if you want to support flattened compound literals, one will need to write code for it.
By the way, anon aggregates should be called unnamed. Anonymous is narrow case of a unnamed member of struct whose type is struct without name. But there are unnamed structs as itself.
struct {
int x;
int y;
};
Will get you compile error: unnamed struct/union that defines no instances
, but
struct {
int x;
int y;
} <variable definitions, pointers, arrays>;
is absolutely legal.
As you stated highly opinionated versus C is non-goal, you should know that in C structs/unions/bit-fields is not just nice low-level features. It is at the core of language, the memory management thing. And be aware of alignment thing https://gcc.gnu.org/onlinedocs/gcc/Structure-Layout-Pragmas.html#Structure-Layout-Pragmas
Particularly in the networking highly useful one:
struct {
int a;
char b;
} x;
// sizeof(x) == 8
#pragma pack(push, 1)
struct {
int a;
char b;
} y;
// sizeof(y) == 5
#pragma pack(pop)
This should be implemented now.
For kicks, I've been porting the ion compiler to ion. Mostly trying to retain things unchanged.
As far as I can tell, ion doesn't currently support anonymous and/or ad hoc aggregates, such as the following:
I could imagine expressing that like so in ion:
Meanwhile, I've been pulling out the nested types and giving the fields names where missing. That's doable, but some things, like Expr, get pretty intense about it. Do you have the intention to add these features to ion?
(And macros are another matter, but I've been working around those for now, too.)