<div dir="ltr">Hi,<br><br>I'm trying to write a program which uses libclang to refacture some code. To do<br>this I need to inspect the AST of the template arguments, but I can not figure<br>out how I can build a tree from the vistor callbacks.<br>
<br>Here is what my test source code looks like:<br><br>Â Â Â 1: template<typename ...T><br>Â Â Â 2: struct Foo {};<br>Â Â Â 3:<br>Â Â Â 4: static Foo<int, int, Foo<short, long>> foo;<br><br>When running the clang_visitChildren on this code I receive the following<br>
callbacks:<br><br>Â Â Â (SYNTAX: <PARENT-CURSOR-HASH>/<CURSOR-HASH> <FILE>:<RANGE> <KIND> <DISPLAYNAME> <DISPLAYTYPE>)<br><br>Â Â Â 1/0 /tmp/test.cxx:1,1-2,14 31 Foo<T><br>Â Â Â 0/2 /tmp/test.cxx:1,10-23 27 T type-parameter-0-0<br>
   1/3 /tmp/test.cxx:4,1-43 9 foo Foo<int, int, Foo<short, long> ><br>   3/4 /tmp/test.cxx:4,8-11 45 Foo<br>   3/4 /tmp/test.cxx:4,22-25 45 Foo<br>   3/5 /tmp/test.cxx:4,40-43 103 Foo Foo<int, int, Foo<short, long> ><br>
<br>What confuses me is that all callbacks on line 4 has the same parent... So how<br>can I build a tree of the template arguments?<br><br>Should I be using the c++ API instead of the C-API for this?<br><br>Any hints or guidance is most appreciated.<br>
<br>/Allan<br><br>PS: Following are the code I wrote for this experiments:<br><br>#include <map><br>#include <stdio.h><br>#include <iostream><br>#include "clang-c/Index.h"<br><br>static std::map<unsigned, size_t> hashes;<br>
<br>size_t hash(const CXCursor &c) {<br>Â Â Â unsigned h = clang_hashCursor(c);<br>Â Â Â if (hashes.find(h) == hashes.end()) {<br>Â Â Â Â Â Â Â size_t s = hashes.size();<br>Â Â Â Â Â Â Â hashes[h] = s;<br>Â Â Â Â Â Â Â return s;<br>Â Â Â } else {<br>
       return hashes[h];<br>   }<br>}<br><br>struct WString {<br>   WString(CXString s) : str(s) {}<br>   ~WString() { clang_disposeString(str); }<br>   CXString str;<br>};<br><br>std::ostream &operator<<(std::ostream &o, const CXString &s) {<br>
   if (clang_getCString(s)) o << clang_getCString(s);<br>   return o;<br>}<br><br>std::ostream &operator<<(std::ostream &o, const CXSourceRange &range) {<br>   CXSourceLocation start = clang_getRangeStart(range);<br>
   CXSourceLocation end = clang_getRangeEnd(range);<br><br>   CXFile file;<br>   unsigned start_line = 0;<br>   unsigned start_col = 0;<br>   unsigned end_line = 0;<br>   unsigned end_col = 0;<br><br>   clang_getExpansionLocation(start, &file, &start_line, &start_col, 0);<br>
   clang_getExpansionLocation(end, 0, &end_line, &end_col, 0);<br><br>   o << clang_getFileName(file) << ":";<br>   if (start_line == end_line)<br>       o << start_line << "," << start_col << "-" << end_col;<br>
   else<br>       o << start_line << "," << start_col << "-" << end_line << ","<br>         << end_col;<br><br>   return o;<br>}<br><br>enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent,<br>
                             CXClientData client_data) {<br>   if (cursor.kind == CXCursor_MacroDefinition) return CXChildVisit_Recurse;<br><br>   CXSourceRange range = clang_getCursorExtent(cursor);<br>   CXType t = clang_getCursorType(cursor);<br>
   CXType tt = clang_getCanonicalType(t);<br><br>   std::cout << hash(parent) << "/" << hash(cursor) << " " << range << " "<br>             << cursor.kind << " " << clang_getCursorDisplayName(cursor) << " "<br>
             << clang_getTypeSpelling(tt) << std::endl;<br><br>   return CXChildVisit_Recurse;<br>}<br><br>int main(int argc, char *argv[]) {<br>   CXIndex idx = clang_createIndex(1, 1);<br>   CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile(<br>
       idx, 0, argc - 1, argv + 1, 0, 0);<br>   clang_visitChildren(clang_getTranslationUnitCursor(tu), visit, 0);<br>   clang_disposeTranslationUnit(tu);<br>   return 0;<br>}<br><br><br></div>