[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