Now I'm facing a second problem. I am able to generate the template function bodies using print, but I can't seem to be able to locate the CallExpr inside the printed bodies (the spelling locations point to the non specialized template). I need this because I might have a template function calling another function, and I need to write both of them (and replace their calling names).
Example: template < typename T > T add(T x, T y) { return x + y; } template < typename T > T mul(T x, T y) { return x * y; } template < typename T > T test(T a, T x, T b) { return add(mul(a,x), b); } int main() { std::cout << test(2, 3, 4) << std::endl; } ---------------------------------- What I wanted to print: ---------------------------------- int add_int(int x, int y) { return x + y; } int mul_int(int x, int y) { return x * y; } int test_int(int a, int x, int b) { return add_int(mul_int(a,x), b); } int main() { std::cout << test_int(2, 3, 4) << std::endl; } When generating the source for test, I can call clang again and recursively expand each function but that's undesirable and probably slow. I could also parse generated expressions, but that could lead to errors. And finally I though about getting in the way of printing (and printing my own names on CallExpr) or to modify the AST itself but I have no idea how to do that. Thanks once again. On Wed, Aug 7, 2019 at 5:58 PM Romulo <abra...@gmail.com> wrote: > Thanks, this solved my problem! > > On Sun, Aug 4, 2019 at 11:07 PM Richard Smith <rich...@metafoo.co.uk> > wrote: > >> On Fri, 2 Aug 2019 at 15:05, Romulo via cfe-users < >> cfe-users@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); >> } >> >
_______________________________________________ cfe-users mailing list cfe-users@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users