[cfe-dev] Cleaning up the representation of Decls in the AST

Argiris Kirtzidis akyrtzi at gmail.com
Thu Sep 11 05:53:58 PDT 2008


Ted Kremenek wrote:
> Note that this completely resolves the ownership issues with anonymous
> structs and similar constructs.  It also means that Types no longer
> own Decls (a good thing).
>   

There's an ownership issue that is not mentioned:

x = sizeof( struct { int z; } );   // who owns this RecordDecl ?

This may indicate that RecordDecls are fundamentally part of Type and 
should be owned by a Type.

In a somewhat related note, consider this:

struct A {};
x = sizeof ( struct A ); #1
x = sizeof ( struct B {} ); #2

C++ Sema needs to know whether the Type passed to sizeof is a type 
reference or a definition (the type definition would be illegal) and 
currently it seems that there isn't a way to do that.

If we modify RecordType to own RecordDecls and be able to provide the 
information of type reference or type definition, these examples would 
be handled:

> [EXAMPLE 1]
>
> void f() {
>    typedef struct x { int y; } foo;
> }
> struct x { int y; };
> void g() {
>    typedef struct x foo;
> }
>
> clang -ast-print currently pretty-prints this as:
>
> void f() {
>    typedef struct x foo;
> }
> ...
> void g() {
>    typedef struct x foo;
> }
>
> Currently both f() and g() appear the same during printing because
> their is no reference from either the TypedefDecl or the DeclStmt to
> the RecordDecl for 'struct x'.  Only the RecordType for 'struct x'
> refers to the RecordDecl, which means in this case the RecordType
> actually *owns* the RecordDecl.  This is horrible, not only because a
> Type object should not own Decls, but that a RecordDecl can sometimes
> be owned by a DeclStmt or be a top-level declaration:

The semantics would be that RecordDecls are always owned by RecordTypes.
clang -ast-print would be able to print the above correctly because:
-Type of f()::foo would indicate a struct definition.
-Type of g()::foo would indicate a struct reference.

>
> [EXAMPLE 2]
>
> struct x { int y; }; // GOOD: The TranslationUnit owns the RecordDecl.
> struct z { int y; } z; // BAD: The RecordType owns the RecordDecl.
>
> The lack of clear ownership semantics, along with the loss of
> information that it implies, makes it very difficult to always
> faithfully pretty-print code that actually compiles, or compiles with
> the same semantics:
>   

The ownership semantics would be that both RecordDecls are owned by 
RecordTypes.
The first one can be a DeclGroup with no declarators.

> [EXAMPLE 3]
>
> void f() {
>    struct { int x; } a, b, *c;
> }
>
> clang -ast-print:
>
> void f() {
>    struct <anonymous> a;
>    struct <anonymous> b;
>    struct <anonymous> *c;
> }
>
> clang -ast-dump:
>
> void f()
> (CompoundStmt 0xc070f0 <<stdin>:3:12, line:5:3>
>    (DeclStmt 0xc070d0 <line:4:5>
>      0xc06ff0 "struct <anonymous> a"
>      0xc07050 "struct <anonymous> b"
>      0xc070a0 "struct <anonymous> *c")
>
> As before, in this case the RecordType owns the RecordDecl.  Not only
> that, but -ast-print pretty-prints the variable declaration in a
> completely broken way.

The above would be printed correctly since the RecordType would indicate 
a struct definition.


Any thoughts ?


-Argiris



More information about the cfe-dev mailing list