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