[cfe-dev] Type source info proposal
Argyrios Kyrtzidis
kyrtzidis at apple.com
Thu Aug 13 17:41:32 PDT 2009
Hi,
This is a more detailed proposal for adding source info about types.
The basic idea is that source information about a "declarator type" (a
type coming out of declarator parsing) will be stored in a flat
contiguous memory block
that will be interpreted based on the type. e.g for:
MyType **
we have a pointer -> pointer -> typedef and the flat memory block will
contain
-source location for pointer star
-source location for pointer star
-source location for typedef name
Source information will contain other stuff besides source locations,
e.g:
MyType * x[N+1]
the flat block will contain:
-source loc for '['
-source loc for ']'
-Expr* for size expression
-source loc for '*'
-source loc for typedef name
For function types:
void (*f1)(int *x, int *y); #1
void f1(int *x, int *y); #2
type source info will contain the ParmVarDecls.
We can probably have the FunctionDecl created from #2 share this
ParmVarDecls array with type source info.
Now where should this information be stored ?
One idea was having a special Type subclass that will also keep source
info for a declarator and will be non-canonical (like TypedefType).
It would also enter the type system, in that types of parameters of a
FunctionType will be this special Type (since a parameter comes out of
a declarator).
This was not a good idea because of 2 issues:
1) Types start being created & uniqued unnecessarily, e.g:
int *x; #1
int **y = &x; #2
For #1 we create a new PointerType to keep source info, and for the
"&x" expression we also create & unique another PointerType, instead
of using the unique "pointer to pointer to int" type.
2) Types change because of semantic analysis, they decay, merge,
change because of attributes, etc. You can't really have source info
"hanging off" a Type.
What I propose instead is that type source info is decoupled from the
actual Type that the declarator resolved to;
type source info should be stored into the Decls (FieldDecl, VarDecl,
etc.) and Exprs that contain types (like SizeofAlignofExpr).
We call "type source info" "DeclaratorInfo" and we create a new Decl
subclass "DeclaratorDecl", which contains a DeclaratorInfo* pointer.
It will enter the hierarchy like this:
ValueDecl -
EnumConstantDecl
DeclaratorDecl -
FieldDecl -
VarDecl -
FunctionDecl -
That way, EnumConstantDecl (which has no use for DeclaratorInfo* at
all) will not change size.
In order to read DeclaratorInfo, you will use "TypeLoc" wrappers to
get at the information, e.g:
DeclaratorDecl *DD = cast<DeclaratorDecl>(ASTLoc.getDecl());
DeclaratorInfo *DInfo = DD->getDeclaratorInfo();
TypeLoc TL = DInfo->getTypeLoc();
if (FunctionLoc *FTL = dyn_cast<FunctionLoc>(&TL)) {
// Print info about the function declarator
FTL->getLParenLoc().print(OS, SrcMgr);
FTL->getRParenLoc().print(OS, SrcMgr);
} else if (ArrayLoc *ATL = dyn_cast<ArrayLoc>(&TL)) {
// Print info about the array declarator
ATL->getLBracketLoc().print(OS, SrcMgr);
ATL->getRBracketLoc().print(OS, SrcMgr);
}
Now, for a given declarator we have both a QualType and a
DeclaratorInfo* and we want to pass them both to the Parser, while
the Parser operates on single pointers (e.g. will store the type
pointer that it got from Sema into an annotation token).
For that we create a "special" Type subclass ("LocInfoType") that
keeps DeclaratorInfo* and whose purpose is *only* for passing back and
forth between Parser & Sema,
in will *not* participate into the type system semantics at all.
Currently, LocInfoType gets created by ASTContext and consumes memory,
but since it is only "transient", intended for the Parser/Sema
interaction,
we can do clever stuff like destroy/cache them when Sema knows that a
declaration is finished so that they don't consume memory.
Ok, this is the high level overview, I've attached incremental patches
of this implementation:
typeinfo1.patch : Introduce TypeLoc and DeclaratorInfo
typeinfo2.patch : Introduce DeclaratorDecl and pass DeclaratorInfo
through the Decl & Sema interfaces.
typeinfo3.patch : Actually build the DeclaratorInfo out of a parsed
declarator
typeinfo4.patch : Introduce LocInfoType
typeinfo5.patch : Pass type source info through the Parser using
LocInfoType
Currently there is no flag to enable/disable type source info but can
be added easily. In general, I would strongly prefer that we always
keep type source info
since, apart from getting a complete AST, we will also be able to get
rid of the "type specifier start location" SourceLocation that Field/
Var/Functions have,
get rid of ConstantArrayWithExprType, and maybe simplify other things
that I'm missing.
I'd really appreciate any feedback that you may have on the above;
feel free to ask me any questions.
-Argiris
More information about the cfe-dev
mailing list