Разрешение typedefs в C и C ++ - PullRequest
8 голосов
/ 30 января 2010

Я пытаюсь автоматически разрешить typedef в произвольных проектах C ++ или C .

Поскольку некоторые из typedef определены в системных заголовочных файлах (например, uint32), яВ настоящее время я пытаюсь добиться этого, запустив препроцессор gcc для моих файлов кода, а затем сканируя предварительно обработанные файлы на наличие typedefs.Затем я смогу заменить typedef в файлах кода проекта.

Мне интересно, есть ли другой, возможно, более простой способ, который я пропускаю.Вы можете вспомнить один из них?

Причина, по которой я хочу сделать это: я извлекаю метрики кода из проектов C / C ++ с помощью различных инструментов.Метрики основаны на методе.После извлечения метрик мне нужно объединить данные, которые создаются различными инструментами.Проблема в том, что один из инструментов разрешает typedefs, а другие нет.Если для типов параметров методов используются определения типов, у меня есть метрики, сопоставленные с разными именами методов, которые фактически ссылаются на один и тот же метод в исходном коде.

Подумайте об этом методе в исходном коде:int test(uint32 par1, int par2)
После запуска моих инструментов у меня есть метрики, сопоставленные с методом с именем int test(uint32 par1, int par2), а некоторые мои метрики сопоставлены с int test(unsigned int par1, int par2).

Ответы [ 3 ]

5 голосов
/ 30 января 2010

Если вам не важно выяснить, где они определены, вы можете использовать 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 . Когда вы освоитесь с тем, как это работает, стол для календарей , включенный в 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), чтобы убедиться, что команды генерации файла карты -mapfilename в вашей версии. В последних версиях использует -Wl,-M и перенаправляет стандартный вывод в файл .

3 голосов
/ 30 января 2010

Вы можете использовать Clang (интерфейс компилятора LLVM C / C ++) для анализа кода таким образом, чтобы сохранить информацию о typedefs и даже макросах. Он имеет очень хороший C ++ API для чтения данных после считывания исходного кода в AST (абстрактное синтаксическое дерево). http://clang.llvm.org/

Если вы вместо этого ищете простую программу, которая уже решает за вас (вместо API программирования Clang), я думаю, вам не повезло, поскольку я никогда не видел такой вещи.

2 голосов
/ 30 января 2010

GCC-XML может помочь с разрешением typedef, вам придется следовать идентификаторам типов элементов <Typedef> до тех пор, пока вы не разрешите их в <FundamentalType>, <Struct> или * 1006. * element.

Для замены typedefs в вашем проекте у вас есть более фундаментальная проблема: вы не можете просто искать и заменять, поскольку вам необходимо соблюдать область имен - подумайте, например, о. функционально-локальные определения типов, псевдонимы пространства имен или директивы using.

В зависимости от того, чего вы на самом деле пытаетесь достичь, должен быть лучший способ.

Обновление: На самом деле, в данном контексте исправления данных метрик замена типов названий с использованием gcc-xml должна работать нормально, если она поддерживает вашу кодовую базу.

...