[cfe-users] How to get code for a function template specialization

Richard Smith via cfe-users cfe-users at lists.llvm.org
Sun Aug 4 19:07:29 PDT 2019


On Fri, 2 Aug 2019 at 15:05, Romulo via cfe-users <cfe-users at lists.llvm.org>
wrote:

> Hello there, thanks for your time reading this :)
>
> I am trying to extract the code for a specialized template function, but I
> have no idea on how to proceed. I know I can use SourceManager to get the
> original 'pure template' code but I don't know how to access the
> specialized functions (the SourceLocation for them points to the original
> function in the AST). My idea is to allow users to write some sugar code
> like:
>
> template <typename T>
> T myAdd(T x, T y) {
>   return x + y;
> }
>
> myAdd< double >(5.5, 3.3);
> or
> myAdd(1, 2);
>
> and after parsing their source files, generate the specialized functions
> with a different name in a separated utility file, replacing the
> occurrences of of use (that's the easy part).
> The utility file would look like:
>
> double _impl_double_myAdd(double x, double y) {
>   return x + y;
> }
>
> int _impl_int_myAdd(int x, int y) {
>   return x + y;
> }
>
> and the calls:
>
> _impl_double_myAdd(5.5, 3.3);
> and
> _impl_int_myAdd(1, 2);
>
> Can anyone point me in the right direction? I though about just replacing
> the usage cases of 'T' but that seems really manual and error prone.
>

You can call clang::Decl::print
<https://clang.llvm.org/doxygen/classclang_1_1Decl.html#a5bac5131c3f19c2f460c1437eedb051c>
on the template specialization declaration to see what it looks like after
substitution. We don't guarantee that the output will be valid C++ code in
all cases (and in fact, there are some constructs that can be produced by
template instantiation and cannot be written directly in C++, but they're
generally very rare), but it usually will be.

If you want a sample of what that looks like, try compiling your code with
"-Xclang -ast-print -S -o -"

For your original example (with the calls to myAdd moved to a function
f()), I get this with clang trunk:

template <typename T> T myAdd(T x, T y) {
    return x + y;
}
template<> double myAdd<double>(double x, double y) {
    return x + y;
}
template<> int myAdd<int>(int x, int y) {
    return x + y;
}
void f() {
    myAdd<double>(5.5, 3.2999999999999998);
    myAdd(1, 2);
}

Example case where the output is not valid C++:

template <typename T>
void destroy(T &t) { t.~T(); }
void f(int n) { destroy(n); }

... produces ...

template <typename T> void destroy(T &t) {
    t.~T();
}
template<> void destroy<int>(int &t) {
    t.~int(); // this won't parse
}
void f(int n) {
    destroy(n);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20190804/8789b869/attachment.html>


More information about the cfe-users mailing list