Getting template arguments from a clang::Type object

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”, 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

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.org: https://godbolt.org/z/bTaoTE. (Kudos to Richard Smith for this one…).

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(record))

{

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

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

{

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

}

}