Самоанализ C++: перечисление доступных классов и методов в кодовой базе C++
Я работаю над некоторым нестандартным статическим анализом кода C++ для моей диссертации. Как часть расширения системы типов C++, я хочу взять базу кода C++ и перечислить доступные функции, методы и классы вместе с их сигнатурами типов с минимальными усилиями (это всего лишь прототип). Какой лучший способ сделать что-то подобное быстро и легко? Должен ли я взломать Clang, чтобы выкладывать нужную мне информацию? Стоит ли смотреть на синтаксический анализ заголовочных файлов чем-то вроде SWIG? Или есть еще более легкая вещь, которую я мог бы сделать?
5 ответов
GCCXML, основанный на GCC, может быть билетом. Насколько я понимаю, он собирает и сбрасывает все определения, но не содержимое функций / методов.
Другие, вероятно, упомянут CLANG, который, конечно, анализирует код и должен иметь доступ к определениям символов в модуле компиляции. (У меня нет опыта здесь).
Для полноты вы должны знать о нашем DMS Software Reengineering Toolkit с его C++ Front End. (Ответы CLANG, похоже, гласят: "Пройдите AST"). Решение DMS предоставляет перечислимую таблицу символов, содержащую всю информацию о типе. Вы также можете пройти AST, если хотите.
Часто статический анализ приводит к диагностике и желанию изменить исходный код. DMS может применять преобразования программы источник-источник для выполнения таких изменений, обусловленных анализом.
Я искренне рекомендую LLVM для статического анализа (см. Также Clang Static Analyzer)
Я думаю, что ваш лучший выбор - взломать Clang и получить AST. Для этого есть хороший урок. Его очень легко изменить его синтаксис, и он также имеет статический анализатор.
В своей работе я использую API из пакета программ под названием "Understand 4 C++" от scitools. Я использую это, чтобы написать все мои инструменты статического анализа. Я даже написал.NET API, чтобы обернуть их C API. Который я ставлю на codeplex.
Как только вы это сделаете, сбросить все типы классов легко:
ClassType[] allclasses = Database.GetAllClassTypes()
foreach (ClassType c in allclasses)
{
Console.WriteLine("Class Name: {0}", c.NameLong);
}
Теперь для небольшой предыстории о моей задаче, которая похожа на вашу. В некоторые годы мы должны поддерживать наш двоичный SDK обратно совместимым с SDK предыдущих лет. В этом случае полезно сравнивать код SDK между выпусками, чтобы проверить возможные критические изменения. Однако с парой сотен файлов и десятками тысяч строк комментариев это может быть большой головной болью, если использовать инструмент различий текста, такой как Beyond Compare или Araxis. Так что мне действительно нужно обратить внимание на фактические изменения кода, а не переупорядочение, не перемещение кода вверх и вниз по файлу, не добавление комментариев и т. Д.
Итак, инструмент, который я написал для выгрузки всего кода.
В одном текстовом файле я сбрасываю все все классы. Для каждого класса я печатаю свое дерево наследования, его функции-члены как виртуальные, так и не виртуальные. Для каждой виртуальной функции я печатаю, какие виртуальные методы родительского класса она переопределяет (если есть). Я также распечатываю его переменные-члены. То же самое относится и к структурам. В другом файле я печатаю все макросы. В другом файле я печатаю все typedefs.
Затем с помощью этого я могу различать эти файлы с файлами из предыдущего выпуска. Затем сразу становится ясно, что изменилось от релиза к релизу. Например, легко увидеть, где параметр функции был изменен с TCHAR* на const TCHAR*, например.
Вы можете рассмотреть возможность разработки плагина GCC для ваших целей.
А GCC MELT - это высокоуровневый предметно-ориентированный язык (который я разработал и реализовал) для простого расширения GCC.
Статья Питера Коллингборна и Пола Келли на семинаре GROW09, посвященная инфраструктуре времени компиляции для GCC Использование Haskell, может иметь отношение к вашей работе.