Подтвердить что ты не робот

Получить исходный (нерасширенный) текст макроса с помощью libclang

Используя libclang, у меня есть курсор в AST, что соответствует выражению, вызванному расширением макроса. Я хочу получить исходный, нерасширенный текст макроса.

Я искал API libclang для этого и не могу найти его. Я что-то пропустил?

Предполагая, что такого API не существует, я вижу несколько способов сделать это, как на основе использования clang_getCursorExtent(), чтобы получить исходный диапазон курсора - который, предположительно, является диапазоном исходного текст.

Первой идеей является использование clang_getFileLocation() для получения имени файла и позиции od начала и конца диапазона и для чтения текста непосредственно из файла. Если я скомпилирован из несохраненных файлов, то мне нужно разобраться с этим, но моя основная забота об этом подходе заключается в том, что просто не кажется правильным выйти за пределы файловой системы, когда я уверен, что clang хранит всю эту информацию внутри, Также были бы последствия, если бы AST был загружен, а не сгенерирован, или если исходные файлы были изменены после их разбора.

Второй подход заключается в вызове clang_tokenize() на уровне курсора. Я попытался сделать это и обнаружил, что он не может создать список токенов для большинства курсоров в AST. Выяснив, что внутри clang_tokenize() внутренне манипулирует поставляемым диапазоном и заканчивается тем, что он охватывает несколько файлов (предположительно из-за некоторого эффекта расширения макроса) и прерывается. Это кажется мне неправильным, но я чувствую, что в любом случае я злоупотребляю clang_tokenize(), пытаясь это сделать.

Итак, какой лучший подход?

4b9b3361

Ответ 1

Это единственный способ, которым я нашел.

Итак, вы получаете курсор верхнего уровня с clang_getTranslationUnitCursor(). Затем вы выполняете clang_visitChildren(), когда функция посетителя передается в это возвращаемое значение CXChildVisit_Continue, так что возвращаются только ближайшие дети. Среди детей вы видите обычные типы курсоров для объявлений верхнего уровня (например, CXCursor_TypedefDecl, CXCursor_EnumDecl), но среди них также есть CXCursor_MacroExpansion. Кажется, что каждое отдельное макрообнаружение появляется в курсоре с этим типом. Затем вы можете вызвать clang_tokenize() на любом из этих курсоров и дать вам нерасширенный текст макроса.

Я понятия не имею, почему расширения макросов застряли в верхней части AST, а не внутри элементов, где они привыкают, что делает вещи довольно неудобными. Пример:

enum someEnum{
    one = SOMEMACRO,
    two,
    three
}

Было бы неплохо, если бы курсор макроса расширения для SOMEMACRO был в объявлении перечисления вместо того, чтобы быть его родным братом.

(Я понимаю, что это смехотворно поздно, но я надеюсь, что это приведет к большему риску заражения, возможно, кто-то более опытный с ним может дать больше понимания).