[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:


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 
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?


More information about the cfe-dev mailing list