Hello everybody, I am new to the list, so please excuse if this isn't the right place to ask and thanks for any pointer where to turn instead. I am trying to write a C program that analyzes certain parts of a .c file at token level, in this particular example I am interested in function bodies. I use a visitor to find cursors of interest, get their source code range (extent) and tokenize that range. The docs for clang_tokenize() explicitly state: "All of the tokens produced by tokenization will fall within this source range".
Unfortunately, in my case that is not working out. The last token is out of the range and seems to be the beginning of the next function definition. I am assuming this is my fault, yet I reduced the code to a minimal version which reliably produces this bahaviour and still cannot spot the mistake. Can anybody tell me what the problem is? I attached the minimal example, compile and run with e.g. $ gcc -o token -lclang -Wall token.c $ ./token It will analyze its own source code and point out the relevant tokens. In case this is a problem with my clang installation, for me the program output is: > range_values(CXSourceRange, uint32_t *, uint32_t *, uint32_t *) - 13 lines: 10-22 > - Token 95/95 ('static') (lines 24-24) not in range! > visitor_left_source_file(CXCursor, CXFile) - 7 lines: 24-30 > - Token 43/43 ('static') (lines 32-32) not in range! > visitor(CXCursor, CXCursor, CXClientData) - 43 lines: 32-74 > - Token 260/260 ('int') (lines 76-76) not in range! > main(int, char **) - 20 lines: 76-95 Output of 'clang -v': > clang version 3.4.1 (tags/RELEASE_34/dot1-final) > Target: x86_64-unknown-linux-gnu > Thread model: posix Any hints would be greatly appreciated! Thanks a bunch, Conrad
#include <errno.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <clang-c/Index.h> static void range_values(CXSourceRange r, uint32_t *from_line, uint32_t *to_line, uint32_t *lines) { uint32_t col, off; CXFile file; CXSourceLocation from = clang_getRangeStart(r); CXSourceLocation to = clang_getRangeEnd(r); clang_getExpansionLocation(from, &file, from_line, &col, &off); clang_getExpansionLocation(to, &file, to_line, &col, &off); if (lines) { *lines = *to_line - *from_line + 1; } } static int visitor_left_source_file(CXCursor cursor, CXFile orig_file) { CXFile file; CXSourceLocation loc = clang_getCursorLocation(cursor); clang_getExpansionLocation(loc, &file, NULL, NULL, NULL); return file != orig_file; } static enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) { CXFile orig_file = (CXFile)client_data; if (visitor_left_source_file(cursor, orig_file)) { return CXChildVisit_Continue; } if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt && clang_getCursorKind(parent) == CXCursor_FunctionDecl) { CXString name = clang_getCursorDisplayName(parent); CXTranslationUnit tu = clang_Cursor_getTranslationUnit(cursor); uint32_t from, to, lines; CXSourceRange range = clang_getCursorExtent(parent); range_values(range, &from, &to, &lines); printf("%s - %u lines: %u-%u\n", clang_getCString(name), lines, from, to); CXToken *tokens = NULL; unsigned num_tokens, i; clang_tokenize(tu, range, &tokens, &num_tokens); for (i = 0; i < num_tokens; ++i) { uint32_t token_from, token_to, token_lines; CXSourceRange r = clang_getTokenExtent(tu, tokens[i]); range_values(r, &token_from, &token_to, &token_lines); if (token_from > to) { // I have no idea why this happens... CXString tok = clang_getTokenSpelling(tu, tokens[i]); printf(" - Token %u/%u ('%s') (lines %u-%u) not in range!\n", i+1, num_tokens, clang_getCString(tok), token_from, token_to); clang_disposeString(tok); break; } } clang_disposeTokens(tu, tokens, num_tokens); clang_disposeString(name); return CXChildVisit_Continue; } return CXChildVisit_Recurse; } int main(int argc, char **argv) { CXIndex index = clang_createIndex(1, 0); CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile(index, "token.c", 0, NULL, 0, NULL); if (!tu) { fprintf(stderr, "Failed to create translation unit!\n"); return 1; } CXString fn = clang_getTranslationUnitSpelling(tu); CXFile orig_file = clang_getFile(tu, clang_getCString(fn)); clang_disposeString(fn); CXCursor tuc = clang_getTranslationUnitCursor(tu); clang_visitChildren(tuc, visitor, orig_file); clang_disposeTranslationUnit(tu); clang_disposeIndex(index); return 0; }
_______________________________________________ cfe-users mailing list cfe-users@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-users