[cfe-dev] How to perform template substitution in the clang library
stewart mackenzie
setori88 at gmail.com
Sun Dec 2 05:40:05 PST 2012
Hi John,
Further to the question:
Kenny said:
I've got a partial solution, the only caveat is that, I can't get
std::is_same<N<4>, N<4>>::value to return true. Well I can live with
that, as I could just define a constexpr method which operates on the
values directly. But I hope someone could provide a correct answer for
this.
I have put the complete solution and the modified input to
https://gist.github.com/4178490.
I've found that to substitute arguments into a class template and
instantiate it, one would:
Use the arguments to turn the ClassTemplateDecl into
ClassTemplateSpecializationDecl, and
Instantiate the specialization using Sema::InstantiateClass method.
The method Sema::RequireCompleteType does indirectly call
InstantiateClass, and requires less input, so I call this method
instead. Therefore, we would write:
/**
* Instantiate a class template.
*/
ClassTemplateSpecializationDecl* instantiate(ASTContext& ast, Sema& sema,
DeclContext* parent,
ClassTemplateDecl* decl,
ArrayRef<TemplateArgument> args) {
void* ins_point;
auto retval = decl->findSpecialization(args.data(), args.size(), ins_point);
if (retval == nullptr) {
retval = ClassTemplateSpecializationDecl::Create(ast, TTK_Class, parent,
{}, {}, decl,
args.data(),
args.size(),
nullptr);
decl->AddSpecialization(retval, ins_point);
}
bool is_incomplete = sema.RequireCompleteType({},
ast.getTypeDeclType(retval),
diag::err_incomplete_type);
return is_incomplete ? nullptr : retval;
}
This method only works for ClassTemplateDecl. In the question we also
have a TypeAliasTemplateDecl. For this, I am going to invoke the
TemplateDeclInstantiator directly, since this is the only object which
knows a TypeAliasTemplateDecl. Perhaps this method also works with
ClassTemplateDecl, but I can't be sure as it seems not enough work is
done using TemplateDeclInstantiator alone.
/**
* Instantiate a template alias (`template <...> using Foo = ...`).
*/
TypeAliasDecl* instantiate(ASTContext& ast, Sema& sema, DeclContext* parent,
TypeAliasTemplateDecl* decl,
ArrayRef<TemplateArgument> args) {
auto args_count = static_cast<unsigned>(args.size());
TemplateArgumentList arg_list {TemplateArgumentList::OnStack,
args.data(), args_count};
MultiLevelTemplateArgumentList multi_arg_list {arg_list};
TemplateDeclInstantiator instantiator {sema, parent, multi_arg_list};
auto instantiated = instantiator.Visit(decl);
if (auto inst_decl = dyn_cast<TypeAliasTemplateDecl>(instantiated)) {
return inst_decl->getTemplatedDecl();
}
return nullptr;
}
(I skipped FunctionTemplateDecl, it is out of the scope of my question.)
Kind regards
Stewart
More information about the cfe-dev
mailing list