[LLVMdev] [ast-dump] Class template partial specializations missing from an implicit class template instantiation?
Joshua Naismith
fakju666 at o2.pl
Thu Sep 5 06:59:47 PDT 2013
I was looking at the ClassTemplatePartialSpecializationDecl::getInstantiatedFromMember documentation, in the included example it says: "(..) the instantiation of Outer<float>::Inner<int*> will end up instantiating the partial specialization Outer<float>::Inner<U*> (...)".
To understand the concept better, I dumped the AST for the following code:
template<typename T>
struct Outer {
template<typename U> struct Inner {float f(){};};
template<typename U> struct Inner<U*> {int f(){};};
};
int main() {
Outer<float>::Inner<int*> ii;
ii.f();
Outer<float>::Inner<int> i2;
i2.f();
}
The tree looks as expected for the template:
|-ClassTemplateDecl 0x38e1de0 <test-src/main.cpp:1:2, line:5:2> Outer
| |-TemplateTypeParmDecl 0x38e1ca0 <line:1:11, col:20> typename T
| |-CXXRecordDecl 0x38e1d50 <line:2:2, line:5:2> struct Outer definition
| | |-CXXRecordDecl 0x390eab0 <line:2:2, col:9> struct Outer
| | |-ClassTemplateDecl 0x390ec80 <line:3:4, col:51> Inner
| | | |-TemplateTypeParmDecl 0x390eb40 <col:13, col:22> typename U
| | | `-CXXRecordDecl 0x390ebf0 <col:25, col:51> struct Inner definition
| | | |-CXXRecordDecl 0x390ef00 <col:25, col:32> struct Inner
| | | `-CXXMethodDecl 0x390f010 <col:39, col:49> f 'float (void)'
| | | `-CompoundStmt 0x390f668 <col:48, col:49>
| | `-ClassTemplatePartialSpecializationDecl 0x390f280 <line:4:4, col:53> struct Inner definition
| | |-TemplateArgument type 'type-parameter-1-0 *'
| | |-TemplateTypeParmDecl 0x390f0b0 <col:13, col:22> typename U
| | |-CXXRecordDecl 0x390f490 <col:25, col:32> struct Inner
| | `-CXXMethodDecl 0x390f5a0 <col:43, col:51> f 'int (void)'
| | `-CompoundStmt 0x390f680 <col:50, col:51>
Both ClassTemplateDecl "Inner" and ClassTemplatePartialSpecializationDecl "Inner" are descendants of ClassTemplateDecl "Outer". However, for an instantiation, it looks like this:
| `-ClassTemplateSpecializationDecl 0x390f7d0 <line:1:2, line:5:2> struct Outer definition
| |-TemplateArgument type 'float'
| |-CXXRecordDecl 0x3916990 prev 0x390f7d0 <line:2:2, col:9> struct Outer
| `-ClassTemplateDecl 0x3916b30 <line:3:4, col:32> Inner
| |-TemplateTypeParmDecl 0x3916a20 <col:13, col:22> typename U
| |-CXXRecordDecl 0x3916aa0 <col:25, col:32> struct Inner
| |-ClassTemplateSpecializationDecl 0x3917130 <line:4:4, col:53> struct Inner definition
| | |-TemplateArgument type 'int *'
| | |-CXXRecordDecl 0x39174b0 prev 0x3917130 <col:25, col:32> struct Inner
| | |-CXXMethodDecl 0x3917540 <col:43, col:51> f 'int (void)'
| | | `-CompoundStmt 0x390f680 <col:50, col:51>
| | |-CXXConstructorDecl 0x3917610 <col:32> Inner 'void (void)' inline noexcept-unevaluated 0x3917610
| | | `-CompoundStmt 0x3918370 <col:32>
| | |-CXXConstructorDecl 0x3917770 <col:32> Inner 'void (const struct Outer<float>::Inner<int *> &)' inline noexcept-unevaluated 0x3917770
| | | `-ParmVarDecl 0x39178b0 <col:32> 'const struct Outer<float>::Inner<int *> &'
| | `-CXXConstructorDecl 0x39181d0 <col:32> Inner 'void (struct Outer<float>::Inner<int *> &&)' inline noexcept-unevaluated 0x39181d0
| | `-ParmVarDecl 0x3918310 <col:32> 'struct Outer<float>::Inner<int *> &&'
| `-ClassTemplateSpecializationDecl 0x3918540 <line:3:4, col:32> struct Inner definition
| |-TemplateArgument type 'int'
| |-CXXRecordDecl 0x3918840 prev 0x3918540 <col:25, col:32> struct Inner
| |-CXXMethodDecl 0x39188d0 <col:39, col:49> f 'float (void)'
| | `-CompoundStmt 0x390f668 <col:48, col:49>
| |-CXXConstructorDecl 0x39189a0 <col:32> Inner 'void (void)' inline noexcept-unevaluated 0x39189a0
| | `-CompoundStmt 0x3918e40 <col:32>
| |-CXXConstructorDecl 0x3918ad0 <col:32> Inner 'void (const struct Outer<float>::Inner<int> &)' inline noexcept-unevaluated 0x3918ad0
| | `-ParmVarDecl 0x3918c10 <col:32> 'const struct Outer<float>::Inner<int> &'
| `-CXXConstructorDecl 0x3918ca0 <col:32> Inner 'void (struct Outer<float>::Inner<int> &&)' inline noexcept-unevaluated 0x3918ca0
| `-ParmVarDecl 0x3918de0 <col:32> 'struct Outer<float>::Inner<int> &&'
Here, both Inner instantiations are descendants of 1 ClassTemplateDecl. I expected that there'd be a node for ClassTemplatePartialSpecializationDecl corresponding to Outer<float>::Inner<U*>, and Outer<float>::Inner<int *> would derive from that.
Which option is true?
1. This is a bug in -ast-dump.
2. This is a bug in the clang AST code.
3. This is expected.
More information about the llvm-dev
mailing list