Я пытаюсь автоматически разрешить определения типов в произвольном C++ или проектах C.
Поскольку некоторые определения типов определяются в системных заголовочных файлах (например, uint32
), я в настоящее время пытаюсь достигнуть этого путем выполнения gcc препроцессора на моих файлах кода и затем сканирования предварительно обработанных файлов для определений типов. Я должен затем смочь заменить определения типов в файлах кода проекта.
Я задаюсь вопросом, если существует другой, возможно, более простой путь, я отсутствую. Можно ли думать о том?
Причина, почему я хочу сделать это: я извлекаю метрики кода из проектов C/C++ с различными инструментами. Метрики основаны на методе. После извлечения метрик я должен объединить данные, которые производятся различными инструментами. Проблема, что один из инструментов разрешает определения типов, и другие не делают. Если существуют определения типов, используемые для типов параметра методов, мне отобразили метрики на различные имена методов, которые на самом деле обращаются к тому же методу в исходном коде.
Думайте об этом методе в исходном коде: int test(uint32 par1, int par2)
После выполнения моих инструментов у меня есть метрики, отображенные на названном методе int test(uint32 par1, int par2)
и некоторые мои метрики отображаются на int test(unsigned int par1, int par2)
.
Если вас не волнует, где они определены, вы можете использовать objdump
для сброса таблицы символов C++, которая разрешает typedefs.
lorien$ objdump --demangle --syms foo
foo: file format mach-o-i386
SYMBOL TABLE:
00001a24 g 1e SECT 01 0000 .text dyld_stub_binding_helper
00001a38 g 1e SECT 01 0000 .text _dyld_func_lookup
...
00001c7c g 0f SECT 01 0080 .text foo::foo(char const*)
...
Этот фрагмент из следующего определения структуры:
typedef char const* c_string;
struct foo {
typedef c_string ntcstring;
foo(ntcstring s): buf(s) {}
std::string buf;
};
Это действительно требует, чтобы вы скомпилировали все и он будет показывать только символы в результирующем исполняемом файле, так что есть несколько ограничений. Другой вариант - дать компоновщику дамп карты символов. Для инструментов GNU добавьте -Wl,-map
и -Wl,name
, где name
- это имя генерируемого файла (см. примечание). Такой подход не распутывает имена, но с небольшой работой вы можете переинжиниринговать конвенции компилятора. Вывод из предыдущего фрагмента будет включать что-то вроде:
0x00001CBE 0x0000005E [ 2] __ZN3fooC2EPKc
0x00001D1C 0x0000001A [ 2] __ZN3fooC1EPKc
Вы можете расшифровать их, используя C++ ABI спецификацию. Как только вы освоитесь с тем, как это работает, таблица mangling table, включенная в ABI, становится бесценной. Вывод в данном случае:
<mangled-name> ::= '_Z' <encoding>
<encoding> ::= <name> <bare-function-type>
<name> ::= <nested-name>
<nested-name> ::= 'N' <source-name> <ctor-dtor-name> 'E'
<source-name> ::= <number> <identifier>
<ctor-dtor-name> ::= 'C2' # base object constructor
<bare-function-type> ::= <type>+
<type> ::= 'P' <type> # pointer to
<type> ::= <cv-qualifier> <type>
<cv-qualifier> ::= 'K' # constant
<type> ::= 'c' # character
Примечание: выглядит так, как будто GNU изменяет аргументы на ld
, так что вы можете захотеть проверить ваше локальное руководство (man ld
), чтобы убедиться, что команды генерации файла карты в вашей версии являются -map
-именем файла
. В последних версиях используйте -Wl,-M
и перенаправьте stdout в файл.
GCC-XML может помочь с разрешением Typedefs, вам нужно следовать идентификаторам типа
элементов, пока не решите их на
, ,
или
элемент.
Для замены Typedefs в ваш проект у вас есть более фундаментальные проблемы, хотя: вы не можете просто поискать и заменить, как вам придется уважать объем имен - подумайте об е. Функциональные функции Typedefs, псевдоним пространства имен или с использованием директив
.
В зависимости от того, что вы на самом деле пытаетесь достичь, там должен быть лучший способ.
Обновление: На самом деле, в данном контексте фиксации данных метрик, замена тепэнисов, использующих GCC-XML, должна работать нормально, если он поддерживает вашу кодовую базу.
Clang (внешний интерфейс компилятора LLVM C/C + +) можно использовать для анализа кода путь, чтобы сохранить информацию о типах и даже макросах. Имеет очень хороший C++ API для чтения данных после считывания исходного кода в AST (абстрактное синтаксическое дерево). http://clang.llvm.org/
Если вместо этого вы ищете простую программу, которая уже делает для вас разрешение (вместо Clang программирования API), я думаю, что вам не повезло, так как я никогда не видел такого.