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

Ted Kremenek kremenek at apple.com
Thu Sep 11 10:51:35 PDT 2008

On Sep 11, 2008, at 5:53 AM, Argiris Kirtzidis wrote:

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

Hi Argiris,

This is an excellent point.  There are a couple reasons why I strongly  
don't believe that types should ever own elements of the AST.

 From an aesthetic perspective, declarations represent program syntax,  
while types are part of the program semantics.  I don't believe our  
data structures representing semantics should own the data structures  
that represent program syntax.  They can refer to each other, but  
there isn't an ownership relationship here.  Conceptually it just  
doesn't make much sense, and I believe that one of the goals of the  
ASTs is that they should be conceptually clean as possible.  This  
allows clients of the ASTs to understand their invariants much more  
easily.  This was actually one of the prime motivation of the  
DeclGroup idea that Daniel and I put forth.  Beyond cleaning up some  
ownership issues, DeclGroups really do capture more elements of C's  
actually syntax.

Another reason that having types own Decls is that it really makes  
things much more difficult for clients that wish to modify the AST.   
When is a Decl owned by a type?  With the idea you propose, a DeclStmt  
might own a TypeDecl if it isn't a RecordDecl, but in the case of a  
RecordType the type would own it.  There is also the problem that we  
now have multiple RecordDecls for a given RecordType.  Does the  
RecordType own all of those RecordDecls?  This actually makes  
manipulation of the AST really tricky and error prone.

 From my perspective, Decls just represent syntax, and if our current  
ASTs cannot adequately capture such elements of the syntax then they  
need to be augmented.  In the case of sizeof(type), it seems to me  
that a reasonable solution would be to have SizeOfAlignOfTypeExpr  
refer to a variant instead of a QualType.  In the common case the  
variant would just refer to a QualType, and in the other case it would  
refer to both a QualType and a TypeDecl (in which case it owns the  
TypeDecl).  Using either smart pointers or subclassing of  
SizeOfAlignOfTypeExpr, it seems that the storage of such extra  
information could readily be incorporated into the AST.   
getArgumentType() could then be made virtual (if necessary) to query  
the appropriate field.

The nice thing about this solution is that it isolates the ugliness of  
C's grammar for this particular problem into a few bits of code in the  
AST, rather than complicating the representation of the C type system  
or introducing hard to reason about ownership issues between Types and  
Decls.  Naturally the parser would need to be augmented to reason  
about variants as well; i.e., in the case of sizeof(type), the logic  
in the parser that returns the QualType for "type" actually may return  
a "type" or a "decl".  This seems fine to me; we're already passing  
variants around in the parser.  Another thing that's nice about this  
solution is that IMHO it is conceptually clean; the fact the sizeof  
can refer to a type or a decl is just a consequence of C's grammar  
that is represented faithfully in the AST itself; clients that care  
about whether or not sizeof(type) actually refers to a declaration  
will need to be able to distinguish between these cases, and other  
clients that just want the type that sizeof(type) refers to won't have  
to care at all.

There will likely be other corner cases like sizeof(type) that we will  
need to handle, but these all seem to me to be issues of syntax that  
require enhancements to the AST themselves.  Having the RecordTypes  
own RecordDecls really just seems like a short-term solution that  
muddles the conceptual cleanliness of the ASTs and introduces  
artificial ownership relationships between types and decls that we  
would only think about introducing in order to solve gross corner  
cases like these.  It just doesn't feel like the right solution to me.


More information about the cfe-dev mailing list