Now when looking up for the clang::FunctionDeclfunction, the first parameter’s canonical type is a clang::TagType which resolves to a clang::ClassTemplateSpecializationDecl implicitly instantiated.
Of course this is the expected behavior: the parser is even capable of resolving SFINAE with type traits.
The main challenge:
Now consider we want to instantiate StructTemplate<double>, how to go from here?
We assume of course that the example code is parsed without prior knowledge of class template specializations existence.
Using: clang::ClassTemplateDecl::findSpecialization(), clang::ClassTemplateSpecializationDecl::Create(), clang::ClassTemplateDecl::AddSpecialization()
work great when there are no partial specializations (in our case there is one explicitly defined).
Using: clang::TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization() needs a clang::ClassTemplatePartialSpecializationDecl which we need to find first, if it ever exists of course (clang::ClassTemplateDecl::findPartialSpecialization() isn’t working, or to be precise not sure what clang::TemplateParameterList should we provide).
Using: clang::ASTContext::getTemplateSpecializationType() has a canonical type clang::TemplateSpecializationType() which isn’t a clang::TagType (we can’t resolve to any concrete class template declaration).
What is the correct way to solve such problem, knowing that the parser itself is able to resolve its occurrence in code?
This subject is kind of obscure and doesn’t have much documentation.
Does anyone know what to do there, or at least where should I ask and get a solution?
Thanks for the reply, I really appreciate it, as I have been searching along for a month now.
Yes, what I am trying to do is instantiating a template programmatically(a class template for example).
Things work great when no partial specializations are available.
But when available, I am not able to obtain a correct instantiation. I tried various methods without any success. The main problem is lack of documentation on how things work on the parser side, because the parser is able to instantiate templates written in code.
I will checkout the link you provided and see what goes on.
Probably you mean the desired instantiation because I do not think it is the “correct” from language perspective.
I tried various methods without any success.
I suspect one of the places you could start is Sema::ActOnCallExpr. If you call it with the “right” arguments it will do almost everything you want. However, I am not sure if that covers your intent for the case with the partial template specializations…
What I meant is, using clang::ClassTemplateDecl::findSpecialization() isn’t useful when the arguments match a partial instantiation and visiting the class template with a clang::TemplateDeclInstantiator will return a dummy ClassTemplateDecl with no members. So the result in some cases is incorrect, semantically speaking: it is non existing in the AST (it is created and injected after the call).
I will try the snippet in the link you provided and see what happens.
I don’t know about Sema::ActOnCallExpr but will try searching in clang’s codebase for any hints.
@vvassilev Tried the snipped provided in the link, works like a charm. Instantiates a clang::ClassTemplateDecl while considering full and partial specializations.
Nice! Many thanks!
Just another question if you don’t mind (while I have actually many but will try to ask them later, because of their lower priority): how to parse additional code (from a string for instance) once the AST is formed?
By the way, I am writing a binding generator over clang which will act as modern boosted SWIG harnessing the power of llvm infrastructure.
So far everything is working like a charm, and way better than the handwritten bison parser of SWIG.
You should really look at what CppInterOp is designed for. It allows you to do incremental compilation.
Are you aware of the cppyy project, it probably does something quite similar to your needs. You can find me on discord and we can chat more if you need to…