<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>