While trying to use the C libclang bindings to parse some sources, I have found that preprocessor directives do not show up in the AST.
Following recommendations from this previous question, and calling clang_parseTranslationUnit
with the CXTranslationUnit_DetailedPreprocessingRecord
flag does not resolve the issue.
I have been able to reproduce the issue with the following demo code (not cleaning up objects is intentional), which is a simple driver that sources its compile arguments from a compile_commands.json
database located in the same directory as the tool for the file passed in as argv[1]
.
#include <clang-c/Index.h>
#include <iostream>
#include <vector>
int main(int argc, char **argv) {
CXIndex index = clang_createIndex(0, 0);
CXCompilationDatabase db = clang_CompilationDatabase_fromDirectory(".", nullptr);
CXCompileCommands cmds = clang_CompilationDatabase_getCompileCommands(db, argv[1]);
CXCompileCommand cmd = clang_CompileCommands_getCommand(cmds, 0);
std::vector<const char *> args;
for (int i = 0; i < clang_CompileCommand_getNumArgs(cmd); ++i) {
args.push_back(clang_CompileCommand_getArg(cmd, i));
}
CXTranslationUnit tu;
clang_parseTranslationUnit2FullArgv(index, nullptr, args.data(), args.size(),
nullptr, 0, CXTranslationUnit_DetailedPreprocessingRecord, &tu);
clang_visitChildren(clang_getTranslationUnitCursor(tu), visitor, nullptr);
}
The visitor
function is a function that prints out some basic information about any preprocessor directives it encounters.
CXChildVisitResult visitor(CXCursor cursor, CXCursor parent,
CXClientData client_data) {
if (clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0)
return CXChildVisit_Continue;
CXCursorKind kind = clang_getCursorKind(cursor);
if (kind >= CXCursor_FirstPreprocessing &&
kind <= CXCursor_LastPreprocessing) {
CXTranslationUnit tu = clang_Cursor_getTranslationUnit(cursor);
CXFile file = clang_getFile(tu, nullptr);
unsigned line, column;
clang_getExpansionLocation(
clang_getRangeStart(clang_getCursorExtent(cursor)), &file, &line,
&column, nullptr);
std::cout << clang_getCString(clang_getFileName(file)) << ":" << line << ":"
<< column << " ["
<< clang_getCString(clang_getCursorKindSpelling(kind)) << "]n";
}
return CXChildVisit_Recurse;
}
The issue is that the preprocessor directives do not show up in the AST, despite there not being other errors.
I have tried appending -Xclang -detailed-preprocessing-record
to the compile arguments, as suggested in the linked question, which does not resolve the issue.
Any help would be appreciated.