Получить информацию о директивах препроцессора

Я недавно начал использовать libclang для разбора C-файлов. Проблема у меня заключается в том, что, очевидно, libclang запускает препроцессор перед генерацией AST. Я хотел бы запретить запуск препроцессора и вместо этого получить информацию о том, что директивы препроцессора находятся в файле …

Я использую следующий скрипт Python (cindex.py и libclang)

import codecs
from clang.cindex import *

class SourceFile(object):
def __init__(self, path):
with codecs.open(path, 'r', 'utf-8') as file:
self.file_content = file.read()

index = Index.create()
root_node = index.parse(path)

for included in root_node.get_includes():
print included.include

self.print_declerations(root_node.cursor)

def print_declerations(self, root, recurse=True):
print root.kind.name, root.spelling
if root.kind.is_declaration():
node_def = root.get_definition()
if node_def is not None:
start_offset = node_def.extent.start.offset
end_offset = node_def.extent.end.offset + 1
print self.file_content[start_offset:end_offset], '\n'

if recurse:
for child in root.get_children():
self.print_declerations(child, False)

if __name__ == '__main__':
path = 'Sample.cpp'
print 'Translation unit:', path
source = SourceFile(path)

Какие выводы

Translation unit: Sample.cpp
/mingw/include\stdio.h
/mingw/include\_mingw.h
/mingw/include\sys/types.h
TRANSLATION_UNIT None
TYPEDEF_DECL __builtin_va_list

STRUCT_DECL _iobuf

TYPEDEF_DECL FILE

VAR_DECL _iob
UNEXPOSED_DECL

FUNCTION_DECL main
int main()
{
printf(HELLO_WORLD);
return 0;
}

Для следующего C-кода:

#include <stdio.h>
#define HELLO_WORLD "HELLO!"
int main()
{
printf(HELLO_WORLD);
return 0;
}

Я хотел бы получить DEFINE_DECL HELLO_WORLD для моего #define в коде (в настоящее время я ничего не получаю). И, конечно, также получить аналогичные утверждения для моего # include. Это возможно?

РЕДАКТИРОВАТЬ: В основном, я хочу проанализировать файл без расширенных директив препроцессора.

10

Решение

Несколько дней назад я задавал тот же вопрос на канале #llvm freenode irc. Ответ был таков: «macroses не является частью AST, поэтому вы не можете», но, скорее всего, вам может помочь опция «-fsyntax-only» и плагин clang вместо libclang.

Отредактировано: похоже, что теперь это действительно возможно, см. Ответ по bradtgmurray

4

Другие решения

Если вы добавите PARSE_DETAILED_PROCESSING_RECORD в качестве опции для вашего вызова index.parse (), вы получите доступ к узлам препроцессора.

index = clang.cindex.Index.create()
tu = index.parse(filename, options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)

Этот параметр соответствует следующему значению параметра libclang C API. Там есть комментарий, который включает в себя еще немного контекста.

/**
* \brief Used to indicate that the parser should construct a "detailed"* preprocessing record, including all macro definitions and instantiations.
*
* Constructing a detailed preprocessing record requires more memory
* and time to parse, since the information contained in the record
* is usually not retained. However, it can be useful for
* applications that require more detailed information about the
* behavior of the preprocessor.
*/
CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
23

Если вы используете аргументы командной строки как способ вызова libclang, вот соответствующий код из реализации libclang C API:

// Do we need the detailed preprocessing record?
if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
Args->push_back("-Xclang");
Args->push_back("-detailed-preprocessing-record");
}
1
По вопросам рекламы [email protected]