<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, May 25, 2014 at 5:53 PM, Allan Nielsen <span dir="ltr"><<a href="mailto:a@awn.dk" target="_blank">a@awn.dk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<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></div></blockquote>
<div><br></div><div>Front-loading by saying that I'm not an expert on the C-API:</div><div>1. You want to use the C-API if you need a library that is stable, and provides for backwards compatibility going forward. That is, if you want to write this tool once, and than use it for years without ever having to touch it, the C API is your only hope.</div>
<div>2. As you discovered, the C API makes some power uses harder; I don't know whether what you want to do is possible with the C API, but I'd say that it's quite a bit easier with the C++ API; that said, if you use the C++ API, you'll have to recompile your tool when you want to use a newer clang, and there are sometimes breaking interface changes, for which you'll have to adapt your code (that said, those interface changes are not a big issue - we have many tools against the C++ API we maintain, and have not found that to be an issue - the "being willing to recompile" is the much larger barrier-to-entry, I think).</div>
<div><br></div><div>So, I'd cautiously advice you to use the C++ API if you're coding in C++ anyway, and you don't want to ship a tool that can auto-link against different versions of clang to customers.</div>
<div><br></div><div>Others might jump in with different opinions :)</div><div><br></div><div>Cheers,</div><div>/Manuel</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><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>
<br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div>