[cfe-dev] ElaboratedType, QualifiedNameType and TypenameType.

Enea Zaffanella zaffanella at cs.unipr.it
Mon Mar 22 03:58:13 PDT 2010


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.

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

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:

======================
namespace A {
template <typename T> struct v;
template <> struct v<double> { struct r {}; };
}

template <typename T>
void f() {
   typename A::v<T>::r x1;
   struct A::v<T>::r y1;
}

void g() {
   typename A::v<double>::r x2;
   struct A::v<double>::r y2;
   A::v<double>::r z2;
}
======================


The ast-print method prints:
======================
template <typename T> void f() {
     typename A::v<T>::r x1;
     struct typename A::v<T>::r y1;
}

;
void g() {
     typename A::v<double>::r x2;
     struct A::v<double>::r y2;
     A::v<double>::r z2;
}
======================
We can see a spurious occurrence of the 'typename' keyword for 'y1'.
Even though the *printing* for the non-dependent types looks OK, 
according to our understanding, even if the type of 'y1' is rendered as 
an ElaboratedType containing a TypenameType, it seems that the type of 
'y2' is rendered as an ElaboratedType containing a RecordType, so that 
the info for the name qualifier is lost in this case.
We also have a QualifiedNameType for x2 (info about the use of 
'typename' is lost).


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?

Cheers,
Enea Zaffanella




More information about the cfe-dev mailing list