Поддерживает ли ctags исправленную функцию прототипа GCC?

Я обнаружил, что gcc поддерживает странное определение функции, например:

static void add_define P3(char *, name, int, nargs, char *, exps)

Который компилируется с -D__USE_FIXED_PROTOTYPES__. И мои плагины тегов vim не могли дать правильный результат. Я попытался выяснить в справочной странице ctags, но не смог найти ее.

РЕДАКТИРОВАТЬ Да, это странно. Макрос есть

#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)

и комментарий говорит, что это

Совместимость с ANSI/K&R.

Он предназначен для сборки xlc, c-компилятора AIX.

1 ответ

Решение

С определением макроса, как показано:

#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)

эта декларация:

static void add_define P3(char *, name, int, nargs, char *, exps);

(Я добавил конечную точку с запятой) расширяется до этого:

static void add_define(char *name, int nargs, char *exps);

который является совершенно обычным прототипом функции (при условии конечной точки с запятой).

Вероятно, есть альтернативная версия этого макроса, что-то вроде этого:

#define P3(t1, v1, t2, v2, t3, v3) \
    (v1, v2, v3) \
    t1 v1; \
    t2 v2; \
    t3 v3;

это расширилось бы до:

static void add_define(name, nargs, exps)
char *name;
int nargs;
char *exps

который является объявлением функции не-прототипа в стиле K&R.

Вероятно, есть что-то вроде:

#ifdef __STDC__
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
#else
#define P3(t1, v1, t2, v2, t3, v3) \
    (v1, v2, v3) \
    t1 v1; \
    t2 v2; \
    t3 v3;
#endif

наряду с аналогичными макросами P0, P1, P2 и т. д. для различного числа параметров. Или, как вы подразумеваете в своем вопросе, он использует определяемый пользователем макрос __USE_FIXED_PROTOTYPES__ скорее, чем __STDC__,

Это позволит одному объявлению автоматически расширяться либо до современного прототипа, либо до объявления в стиле K&R; последнее будет необходимо только с очень старыми пре-ANSI компиляторами.

Чтобы ответить на вопрос в заголовке (наконец-то!), ctags работает на необработанном C-источнике. Быстрый эксперимент с GNU ctags показывает, что не очень умно интерпретировать макросы, которые скрывают основной синтаксис. Он сгенерирует записи тегов для самих определений макросов, но не распознает

static void add_define P3(char *, name, int, nargs, char *, exps) {
    /* ... */
}

как определение функции. (Вы можете запустить исходный файл через препроцессор, но тогда теги будут ссылаться на предварительно обработанный файл, что не особенно полезно.) В принципе, ctags должен понимать полный синтаксис C, включая препроцессор; на практике это не так.

Если вы хотите иметь ctags генерировать теги для вашего исходного файла, вам нужно избавиться от макросов и написать узнаваемые прототипы. Вы не сможете скомпилировать модифицированный исходный код с помощью пре-ANSI-компилятора, но в наши дни это вряд ли станет проблемой. Если вы в состоянии сделать это, полученный код будет легче поддерживать.

Или, так как вывод генерируется ctags достаточно просто, не должно быть слишком сложно вручную добавить соответствующие теги в tags файл (хотя поддерживать его автоматически может быть сложно).

Другие вопросы по тегам