Quantcast

TypeLoc of a template class type in an uninstantiated template has incomplete type?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

TypeLoc of a template class type in an uninstantiated template has incomplete type?

Philip Reames via cfe-dev
Hi all,

I am trying to match type references of `class A` in the following code:
 template <typename T>
 class A {};
 template <typename T>
 class Temp {
   A<int> a;
   A<T> at;
 };
with matcher:
    typeLoc(loc(qualType(hasDeclaration(cxxRecordDecl(hasName("A"))))))

However, only `A<int>` matches, and `A<T>` only matches after I added an instantiation of the template (e.g. `Temp<int> t;`).

I also dumped the AST, and it seems that `A<T>` is only associated with the `class A` in `ClassTemplateSpecializationDecl` of `Temp` but not `ClassTemplateDecl` (highlighted below).

Is this expected? If so, could someone explain why TypeLoc `A<T>` in `ClassTemplateDecl` should not be associated with the actual class A? Thanks a lot!

|-ClassTemplateDecl 0x7f991815b5d8 <line:4:1, line:8:1> line:5:7 Temp | |-TemplateTypeParmDecl 0x7f991815b4c0 <line:4:11, col:20> col:20 referenced typename T | |-CXXRecordDecl 0x7f991815b540 <line:5:1, line:8:1> line:5:7 class Temp definition | | |-CXXRecordDecl 0x7f991815b848 <col:1, col:7> col:7 implicit class Temp | | |-FieldDecl 0x7f991815bbc0 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | | `-FieldDecl 0x7f991815bcc8 <line:7:3, col:8> col:8 at 'A<T>' | `-ClassTemplateSpecializationDecl 0x7f991815bd48 <line:4:1, line:8:1> line:5:7 class Temp definition | |-TemplateArgument type 'int' | |-CXXRecordDecl 0x7f991818c000 prev 0x7f991815bd48 <col:1, col:7> col:7 implicit class Temp | |-FieldDecl 0x7f991818c098 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | |-FieldDecl 0x7f991818c198 <line:7:3, col:8> col:8 at 'A<int>':'class A<int>' | |-CXXConstructorDecl 0x7f991818c220 <line:5:7> col:7 implicit used constexpr Temp 'void (void) noexcept' inline default trivial | | |-CXXCtorInitializer Field 0x7f991818c098 'a' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818cc68 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | |-CXXCtorInitializer Field 0x7f991818c198 'at' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818ccc0 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | `-CompoundStmt 0x7f991818cd28 <col:7> | |-CXXConstructorDecl 0x7f991818c8c8 <col:7> col:7 implicit constexpr Temp 'void (const class Temp<int> &)' inline default trivial noexcept-unevaluated 0x7f991818c8c8 | | `-ParmVarDecl 0x7f991818c9f0 <col:7> col:7 'const class Temp<int> &' | `-CXXConstructorDecl 0x7f991818ca88 <col:7> col:7 implicit constexpr Temp 'void (class Temp<int> &&)' inline default trivial noexcept-unevaluated 0x7f991818ca88 | `-ParmVarDecl 0x7f991818cbb0 <col:7> col:7 'class Temp<int> &&'

Regards,
Eric

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: TypeLoc of a template class type in an uninstantiated template has incomplete type?

Philip Reames via cfe-dev
Hi Eric,

`A<T>` in `class Temp` definition is a dependent name (see http://eel.is/c++draft/temp.dep) whereas in `class Temp` specialization it is not (it is instantiated as `A<int>`). In case of dependent names, clang will not offer you any additional details about the construct because semantics of such a construct may differ from one instantiation to another.

I had a very similar question few days ago (http://lists.llvm.org/pipermail/cfe-dev/2017-January/052376.html). Although I am not using AST matcher, but rather libclang directly, I did end up implementing heuristic method for extracting the details that I needed and which seems to be quite applicable in my target use-case. I am not sure about your use-case and how flexible AST matcher is but you might want to try to jump to the declaration of dependent-name node and then walk through it to get more details which you need.

Cheers,
Adi

On 8 February 2017 at 18:55, Eric Liu via cfe-dev <[hidden email]> wrote:
Hi all,

I am trying to match type references of `class A` in the following code:
 template <typename T>
 class A {};
 template <typename T>
 class Temp {
   A<int> a;
   A<T> at;
 };
with matcher:
    typeLoc(loc(qualType(hasDeclaration(cxxRecordDecl(hasName("A"))))))

However, only `A<int>` matches, and `A<T>` only matches after I added an instantiation of the template (e.g. `Temp<int> t;`).

I also dumped the AST, and it seems that `A<T>` is only associated with the `class A` in `ClassTemplateSpecializationDecl` of `Temp` but not `ClassTemplateDecl` (highlighted below).

Is this expected? If so, could someone explain why TypeLoc `A<T>` in `ClassTemplateDecl` should not be associated with the actual class A? Thanks a lot!

|-ClassTemplateDecl 0x7f991815b5d8 <line:4:1, line:8:1> line:5:7 Temp | |-TemplateTypeParmDecl 0x7f991815b4c0 <line:4:11, col:20> col:20 referenced typename T | |-CXXRecordDecl 0x7f991815b540 <line:5:1, line:8:1> line:5:7 class Temp definition | | |-CXXRecordDecl 0x7f991815b848 <col:1, col:7> col:7 implicit class Temp | | |-FieldDecl 0x7f991815bbc0 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | | `-FieldDecl 0x7f991815bcc8 <line:7:3, col:8> col:8 at 'A<T>' | `-ClassTemplateSpecializationDecl 0x7f991815bd48 <line:4:1, line:8:1> line:5:7 class Temp definition | |-TemplateArgument type 'int' | |-CXXRecordDecl 0x7f991818c000 prev 0x7f991815bd48 <col:1, col:7> col:7 implicit class Temp | |-FieldDecl 0x7f991818c098 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | |-FieldDecl 0x7f991818c198 <line:7:3, col:8> col:8 at 'A<int>':'class A<int>' | |-CXXConstructorDecl 0x7f991818c220 <line:5:7> col:7 implicit used constexpr Temp 'void (void) noexcept' inline default trivial | | |-CXXCtorInitializer Field 0x7f991818c098 'a' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818cc68 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | |-CXXCtorInitializer Field 0x7f991818c198 'at' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818ccc0 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | `-CompoundStmt 0x7f991818cd28 <col:7> | |-CXXConstructorDecl 0x7f991818c8c8 <col:7> col:7 implicit constexpr Temp 'void (const class Temp<int> &)' inline default trivial noexcept-unevaluated 0x7f991818c8c8 | | `-ParmVarDecl 0x7f991818c9f0 <col:7> col:7 'const class Temp<int> &' | `-CXXConstructorDecl 0x7f991818ca88 <col:7> col:7 implicit constexpr Temp 'void (class Temp<int> &&)' inline default trivial noexcept-unevaluated 0x7f991818ca88 | `-ParmVarDecl 0x7f991818cbb0 <col:7> col:7 'class Temp<int> &&'

Regards,
Eric

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: TypeLoc of a template class type in an uninstantiated template has incomplete type?

Philip Reames via cfe-dev
Thank you for the explanation, Jusufadis! I am just trying to see if I can match a class template reference in a template declaration without going into `ClassTemplateSpecializationDecl` so that I don't need to worry about parameter substitution. But looks like I have to deal with the substitutions.

On Wed, Feb 8, 2017 at 9:31 PM Jusufadis Bakamovic <[hidden email]> wrote:
Hi Eric,

`A<T>` in `class Temp` definition is a dependent name (see http://eel.is/c++draft/temp.dep) whereas in `class Temp` specialization it is not (it is instantiated as `A<int>`). In case of dependent names, clang will not offer you any additional details about the construct because semantics of such a construct may differ from one instantiation to another.

I had a very similar question few days ago (http://lists.llvm.org/pipermail/cfe-dev/2017-January/052376.html). Although I am not using AST matcher, but rather libclang directly, I did end up implementing heuristic method for extracting the details that I needed and which seems to be quite applicable in my target use-case. I am not sure about your use-case and how flexible AST matcher is but you might want to try to jump to the declaration of dependent-name node and then walk through it to get more details which you need.

Cheers,
Adi

On 8 February 2017 at 18:55, Eric Liu via cfe-dev <[hidden email]> wrote:
Hi all,

I am trying to match type references of `class A` in the following code:
 template <typename T>
 class A {};
 template <typename T>
 class Temp {
   A<int> a;
   A<T> at;
 };
with matcher:
    typeLoc(loc(qualType(hasDeclaration(cxxRecordDecl(hasName("A"))))))

However, only `A<int>` matches, and `A<T>` only matches after I added an instantiation of the template (e.g. `Temp<int> t;`).

I also dumped the AST, and it seems that `A<T>` is only associated with the `class A` in `ClassTemplateSpecializationDecl` of `Temp` but not `ClassTemplateDecl` (highlighted below).

Is this expected? If so, could someone explain why TypeLoc `A<T>` in `ClassTemplateDecl` should not be associated with the actual class A? Thanks a lot!

|-ClassTemplateDecl 0x7f991815b5d8 <line:4:1, line:8:1> line:5:7 Temp | |-TemplateTypeParmDecl 0x7f991815b4c0 <line:4:11, col:20> col:20 referenced typename T | |-CXXRecordDecl 0x7f991815b540 <line:5:1, line:8:1> line:5:7 class Temp definition | | |-CXXRecordDecl 0x7f991815b848 <col:1, col:7> col:7 implicit class Temp | | |-FieldDecl 0x7f991815bbc0 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | | `-FieldDecl 0x7f991815bcc8 <line:7:3, col:8> col:8 at 'A<T>' | `-ClassTemplateSpecializationDecl 0x7f991815bd48 <line:4:1, line:8:1> line:5:7 class Temp definition | |-TemplateArgument type 'int' | |-CXXRecordDecl 0x7f991818c000 prev 0x7f991815bd48 <col:1, col:7> col:7 implicit class Temp | |-FieldDecl 0x7f991818c098 <line:6:3, col:10> col:10 a 'A<int>':'class A<int>' | |-FieldDecl 0x7f991818c198 <line:7:3, col:8> col:8 at 'A<int>':'class A<int>' | |-CXXConstructorDecl 0x7f991818c220 <line:5:7> col:7 implicit used constexpr Temp 'void (void) noexcept' inline default trivial | | |-CXXCtorInitializer Field 0x7f991818c098 'a' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818cc68 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | |-CXXCtorInitializer Field 0x7f991818c198 'at' 'A<int>':'class A<int>' | | | `-CXXConstructExpr 0x7f991818ccc0 <col:7> 'A<int>':'class A<int>' 'void (void) noexcept' | | `-CompoundStmt 0x7f991818cd28 <col:7> | |-CXXConstructorDecl 0x7f991818c8c8 <col:7> col:7 implicit constexpr Temp 'void (const class Temp<int> &)' inline default trivial noexcept-unevaluated 0x7f991818c8c8 | | `-ParmVarDecl 0x7f991818c9f0 <col:7> col:7 'const class Temp<int> &' | `-CXXConstructorDecl 0x7f991818ca88 <col:7> col:7 implicit constexpr Temp 'void (class Temp<int> &&)' inline default trivial noexcept-unevaluated 0x7f991818ca88 | `-ParmVarDecl 0x7f991818cbb0 <col:7> col:7 'class Temp<int> &&'

Regards,
Eric

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...