Getting template arguments from a clang::Type object

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

Getting template arguments from a clang::Type object

shirley breuer via cfe-dev

Hi All,

 

Can anyone tell me how to get the template arguments from a clang::Type object? For example, if I have clang::Type for “std::vector<int>”, how do I get to this “int” type?

 

When looking at the API reference I’m getting a bit lost with all the terminology I’m not yet familiar with, any good resources to that explains the terminology? Especially how templates are represented is still unclear to me.

 

Thanks in advanced for your help and a huge thanks to all the LLVM and clang contributes!

 

With Kind Regards,

Gert Massa

 


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

Re: Getting template arguments from a clang::Type object

shirley breuer via cfe-dev
You probably want to look at `ClassTemplatesSpecializationDecl`.  If you're doing this in the context of AST matchers, then something like the following is probably what you want:

```
AST_MATCHER_P(clang::TypeLoc, templateSpecializationTypeLoc,
              clang::ast_matchers::TypeLocMatcher, InnerMatcher) {
  auto L = Node.getAs<clang::TemplateSpecializationTypeLoc>();
  if (L.isNull()) return false;
  return InnerMatcher.matches(L, Finder, Builder);
}

AST_MATCHER_P(
    clang::TypeLoc, hasAnyTemplateArgumentLoc,
    clang::ast_matchers::internal::Matcher<clang::TemplateArgumentLoc>,
    InnerMatcher) {
  auto L = Node.getAs<clang::TemplateSpecializationTypeLoc>();
  if (L.isNull()) return false;
  for (unsigned Index = 0, N = L.getNumArgs(); Index < N; ++Index) {
    clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
    if (InnerMatcher.matches(L.getArgLoc(Index), Finder, &Result)) {
      *Builder = std::move(Result);
      return true;
    }
  }
  return false;
}

AST_MATCHER_P(clang::TemplateArgumentLoc, refersToTypeLoc,
              clang::ast_matchers::internal::Matcher<clang::TypeLoc>,
              InnerMatcher) {
  return Node.getArgument().getKind() == clang::TemplateArgument::Type &&
         InnerMatcher.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder,
                              Builder);
}
```

These could be used in a matcher, for example, to identify a type which is a template instantiation with any argument that refers to some type of interest (here, identified by `inner_matcher`).
```
auto template_instantiation =
            templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
                templateArgumentLoc(refersToTypeLoc(inner_matcher))));
```

As for AST guides, I don't know of any good ones, unfortunately. My first place to look is clang-query (especially in godbolt.org) -- I enter a code snippet and see what the resulting AST looks like.  To see the AST for types, try using something like this in godbolt.orghttps://godbolt.org/z/bTaoTE. (Kudos to Richard Smith for this one...).

On Mon, Dec 21, 2020 at 9:04 AM Massa, Gert via cfe-dev <[hidden email]> wrote:

Hi All,

 

Can anyone tell me how to get the template arguments from a clang::Type object? For example, if I have clang::Type for “std::vector<int>”, how do I get to this “int” type?

 

When looking at the API reference I’m getting a bit lost with all the terminology I’m not yet familiar with, any good resources to that explains the terminology? Especially how templates are represented is still unclear to me.

 

Thanks in advanced for your help and a huge thanks to all the LLVM and clang contributes!

 

With Kind Regards,

Gert Massa

 

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

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

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Getting template arguments from a clang::Type object

shirley breuer via cfe-dev

Hi Yitzhak

 

Thank you for pointing me in the right direction. The trick was to call getAsCXXRecordDecl on the type object first and then cast it to ClassTemplateSpecializationDecl .

 

clang::CXXRecordDecl * record = type->getAsCXXRecordDecl();

if (const auto * templateDecl = llvm::dyn_cast<ClassTemplateSpecializationDecl>(record))

{

    const TemplateArgumentList & argList = templateDecl->getTemplateArgs();

    for (uint i = 0; i < argList.size(); i++)

    {

        res.AddTemplateArg(ToSimpleAst(argList.get(i).getAsType()));

    }

}

 

From: Yitzhak Mandelbaum <[hidden email]>
Sent: Monday, December 21, 2020 16:41
To: Massa, Gert (DI SW STS R&D SIM ARCH) <[hidden email]>
Cc: [hidden email]
Subject: Re: [cfe-dev] Getting template arguments from a clang::Type object

 

You probably want to look at `ClassTemplatesSpecializationDecl`.  If you're doing this in the context of AST matchers, then something like the following is probably what you want:

 

```

AST_MATCHER_P(clang::TypeLoc, templateSpecializationTypeLoc,
              clang::ast_matchers::TypeLocMatcher, InnerMatcher) {
  auto L = Node.getAs<clang::TemplateSpecializationTypeLoc>();
  if (L.isNull()) return false;
  return InnerMatcher.matches(L, Finder, Builder);
}

AST_MATCHER_P(
    clang::TypeLoc, hasAnyTemplateArgumentLoc,
    clang::ast_matchers::internal::Matcher<clang::TemplateArgumentLoc>,
    InnerMatcher) {
  auto L = Node.getAs<clang::TemplateSpecializationTypeLoc>();
  if (L.isNull()) return false;
  for (unsigned Index = 0, N = L.getNumArgs(); Index < N; ++Index) {
    clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
    if (InnerMatcher.matches(L.getArgLoc(Index), Finder, &Result)) {
      *Builder = std::move(Result);
      return true;
    }
  }
  return false;
}

 

AST_MATCHER_P(clang::TemplateArgumentLoc, refersToTypeLoc,
              clang::ast_matchers::internal::Matcher<clang::TypeLoc>,
              InnerMatcher) {
  return Node.getArgument().getKind() == clang::TemplateArgument::Type &&
         InnerMatcher.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder,
                              Builder);
}

```

 

These could be used in a matcher, for example, to identify a type which is a template instantiation with any argument that refers to some type of interest (here, identified by `inner_matcher`).

```

auto template_instantiation =
            templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
                templateArgumentLoc(refersToTypeLoc(inner_matcher))));

```

 

As for AST guides, I don't know of any good ones, unfortunately. My first place to look is clang-query (especially in godbolt.org) -- I enter a code snippet and see what the resulting AST looks like.  To see the AST for types, try using something like this in godbolt.orghttps://godbolt.org/z/bTaoTE. (Kudos to Richard Smith for this one...).

 

On Mon, Dec 21, 2020 at 9:04 AM Massa, Gert via cfe-dev <[hidden email]> wrote:

Hi All,

 

Can anyone tell me how to get the template arguments from a clang::Type object? For example, if I have clang::Type for “std::vector<int>”, how do I get to this “int” type?

 

When looking at the API reference I’m getting a bit lost with all the terminology I’m not yet familiar with, any good resources to that explains the terminology? Especially how templates are represented is still unclear to me.

 

Thanks in advanced for your help and a huge thanks to all the LLVM and clang contributes!

 

With Kind Regards,

Gert Massa

 

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


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

smime.p7s (16K) Download Attachment