[cfe-dev] Better type-specifier representation
Argiris Kirtzidis
akyrtzi at gmail.com
Fri Sep 12 07:38:26 PDT 2008
Here's a proposal, collecting the arguments into one post:
Modifying Type to better represent 'type-specifier' in the syntax:
As Ted mentioned, there's a problem on how we represent struct
declarations inside type-specifiers:
Example:
void f() {
typedef struct x { int y; } foo; // #1
}
Syntactically this is what we have for #1:
typedef struct x { int y; } foo; -> 'typedef' type-specifier 'foo' ';'
and we treat it as: 'typedef' ['struct x' reference] 'foo' ';'
There's no information that 'struct x' is defined inside the typedef
declaration. Also it's not clear who owns the RecordDecl.
I suggest that we treat it as:
'typedef' ['struct x' definition] 'foo' ';'
resulting in a RecordTypeDef Type for the TypedefDecl. This gives us the
information that we have a 'struct x' definition inside the
type-specifier of #1.
What about ownership of RecordDecl ?
There will be a 1-to-1 mapping between RecordTypes and RecordDecls,
struct x; -> A new incomplete RecordDecl is created here.
struct x {}; -> The previously created RecordDecl is fully defined.
and RecordType will own it. What is the advantage of that ? Ownership
matters when a client wants to modify the AST. When the client says "I
want to replace this RecordDecl with another one" it usually means
"Everywhere in this translation unit, if a Type references this
RecordDecl, I want it to reference this RecordDecl instead.". The client
will accomplish this by replacing the one RecordDecl owned by the
RecordType with another one.
The alternative would be replacing all the RecordDecls (forward decls
and defs) present, *and* replacing the RecordDecl that the RecordType
references.
Also, by having only one RecordDecl we avoid the overhead of creating
multiple RecordDecls.
If the two constructs above are not RecordDecls owned by the
translation unit, how are they represented in the AST ?
Syntactically they look like this:
struct x; -> type-specifier ';'
struct x {}; -> type-specifier ';'
similar to this, which we currently ignore:
int; -> type-specifier ';'
I suggest representing them with a kind of 'TypeSpecDecl' declaration
node. This will allow us to also capture "int;" in the AST:
int; -> TypeSpecDecl with type 'int'
struct x {}; -> TypeSpecDecl with type RecordTypeDef defining
RecordDecl 'x'
struct x; -> TypeSpecDecl with type RecordTypeRef, referencing
RecordDecl 'x'
Other occurences of type-specifier are represented in a consistent way:
int foo(int x, struct { int a; } y);
'y' gets a new RecordTypeDef type, which owns the RecordDecl. We avoid
the overhead of using multiple DeclGroups for the parameters.
sizeof (struct { int x;}) -> 'sizeof' '(' type-specifier ')' -> A new
RecordTypeDef type passed to sizeof.
This approach of handling records will also apply to enums, basically
it's about handling the tag declarations appearing inside
type-specifiers. Consequently, this approach does not apply to typedefs:
typedef int x; -> syntactically (and semantically) 'typedef'
type-specifier 'x' ';' -> a TypedefDecl 'x'
Typedefs don't have the complications of tag types, they will be handled
the same way as now.
Any thoughts?
-Argiris
More information about the cfe-dev
mailing list