[cfe-dev] ElaboratedType, QualifiedNameType and TypenameType.

Douglas Gregor dgregor at apple.com
Mon Mar 22 13:10:42 PDT 2010


On Mar 22, 2010, at 3:58 AM, Enea Zaffanella wrote:

> Hello.
> 
> We were looking into these three AST classes (while wearing the glasses 
> of applications working at the source code level) and we ended up with 
> the following picture:
> 
> 1) An ElaboratedType is a type name prefixed by a tag keyword.
> The current clang implementation requires that this tag keyword is taken 
> from the set { struct, class, union, enum }. This differs from the 
> standard (C++98 7.1.5.3), where also the keyword 'typename' is allowed.
> The (optional) name qualifier is not directly encoded in the AST node.

The C++98/03 standard is very, very confusing here. The intent was not to make 'typename' abide by the rules in 7.1.5.3 [dcl.type.elab]; it was a syntactic convenience in the grammar.

I suggest that you instead look at C++0x, which has a "typename-specifier" grammar production for typename types that is completely distinct from elaborated-type-specifiers. 

> 2) A QualifiedNameType is a non-dependent type name provided with a 
> (mandatory) name qualifier. The current implementation does not encode 
> the (optional) tag keyword, but there is a FIXME noting that, e.g., the 
> 'typename' keyword could be used even though the name is not dependent 
> (C++98 14.6p5).

The intent of QualifiedNameType is that it never have a tag; that should be handled by ElaboratedType.

> 3) A TypenameType is a dependent type name provided with a (mandatory) 
> name qualifier. The current implementation does not encode the 
> (mandatory) tag keyword, which will be tipically be 'typename', but 
> could also be another one, as in the following example:
[snip]
> We would like to improve things in order to have an exact picture of 
> what was written in the program. We have two options:
> 
> A) allow for 'typename' in ElaboratedType and let these keywords be 
> *always* encoded by ElaboratedType nodes. That is, variable x1, x2, y1 
> and y2 will all have ElaboratedType, containing a TypenameType (x1 and 
> y1) or a QualifiedNameType (x2 and y2). One may also consider the 
> possibility of renaming class "TypenameType" to become 
> "DependentNameType" (since the typename keyword is not actually implied).
> 
> B) get rid of ElaboratedType nodes and push the corresponding info about 
> the tag keyword down into QualifiedNameType (where the name qualifier 
> would become optional) and TypenameType.
> 
> To our eyes, option A) is closer to what is said in the C++ standard; 
> however, option B would maybe require less AST nodes (of course, the 
> inner nodes would become bigger).
> What is the opinion of clang developers?
> Is there an option C which is even better?


There is an option (C). Here's what I think each of the types should do:

ElaboratedType: Should handle all elaborated-type-specifiers in the C++0x sense, which means a type referenced via the enum/class/struct/union keyword. This class should be extended with an optional NestedNameSpecifier to handle qualified elaborated-type-specifiers, ideally in a implementation-detail base class so that we don't pay a size penalty for "struct X". Getting this right should make fixing PR5681 trivial.

QualifiedNameType: Should handle all type references that involve qualified names but for which we can resolve the name lookup to actually refer to a specific type. These could actually have "typename" qualifiers on them, but the point is that QualifiedNameType is always sugar.

TypenameType: Should handle all type references that involve qualified names where the name it refers to is a dependent name. May or may not actually have the "typename" keyword.

	- Doug



More information about the cfe-dev mailing list