2010-04-21 2 views
12

я знаю, как использовать атрибут устаревшее для принизить функции, как это:Как отказаться от макроса в GCC?

int old_fn() __attribute__ ((deprecated)); 

Но как принизить макрос так:

#define OLD_MACRO 1 

Спасибо заранее.

Эрик

ответ

1

Поскольку Макросы не являются частью компилятора (они являются функцией препроцессора), нет чистого способа сделать это. В лучшем случае разместите свои устаревшие макросы в новом заголовочном файле, заполненном #warnings. Разумеется, это приведет к нарушению существующего кода, но его единственный способ гарантировать привлечение внимания к устареванию.

8

Я думаю, что лучшее, что вы можете сделать что-то вроде этого:

#ifdef USE_DEPRECATED_MACROS 
#warning using deprecated macros 
#define OLD_MACRO 1 
... 
#endif 

Таким образом, вы вынуждаете пользователю, например, add -DUSE_DEPRECATED_MACROS к их параметрам компилятора, и они получают предупреждение.

+2

+1; отличный мини-хак – INS

+2

Как бы вкус, я бы предпочел, чтобы пользователь '#define USE_DEPRECATED_MACROS 1' в своем источнике до' # include' вместо того, чтобы помещать флаг через командную строку ... но действительно, тот же результат так или иначе; они должны знать, что они делают, и могут поддерживать это, когда это возможно (и терять предупреждение). Хороший звонок! –

+6

Я бы сделал это наоборот: '#ifndef NO_DEPRECATED_MACROS'. Таким образом, вы выдаете предупреждение при сохранении совместимости источников для клиентов вашего файла заголовка.Затем пользователь может добавить 'NO_DEPRECATED_MACROS', чтобы избавиться от предупреждения, а не разрушить его, когда он берет новый заголовочный файл, и ему нужно прочитать заметки о выпуске, чтобы узнать, почему OLD_MACRO ушел. Конечно, если пользователь использует '-Werror', то все это одно и то же, но если он этого не сделает, возможно, именно потому, что он не хочет, чтобы его сборка падала, потому что вы возились с предупреждениями ;-) –

5

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

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

#define DEPRECATE(name) static inline void __attribute__((deprecated)) deprecate_ ## name (void) { ; } 
... 
#define MAX(x, y) (DEPRECATE(MAX), x>y?x:y) 
// yeah, yeah, it repeats args in the body, but it's just an example 

Для постоянной определения вы, вероятно, хотите, чтобы предположить, что организм должен оценить, не имея для генерации кода, например, за пределами тела функции, в мишенях переключателя/case, или как начальное значение статической переменной внутри функции.

Это сложно, но вы можете сделать это для многих вещей.

Желаю, чтобы у C был __builtin_warn (const char *), который работал бы на уровне компилятора (не-препроцессор) и делал бы такие вещи проще.

редактировать

Для постоянной определения вы можете сделать:

#define THREE (DEPRICATED(THREE),3) 
+0

И действительно, если бы у вас был этот макрос, вам нужно было бы его осудить. – Joshua

+1

@ Joshua: В следующем выпуске программного обеспечения 'THREE' не будет определено, но в версии после этого' #define THREE (4) '. – nategoose

10

Nice, элегантное решение, однако в зависимости от C99 быть включен (работает с GCC 4.8.2 или более поздней версии, не тестируется на более ранних версиях) :

#define DEPRECATED_MACRO1 _Pragma ("GCC warning \"'DEPRECATED_MACRO1' macro is deprecated\"") 7 
#define DEPRECATED_MACRO2(...) _Pragma ("GCC warning \"'DEPRECATED_MACRO2' macro is deprecated\"") printf(__VA_ARGS__) 

int main(int argc, char*argv[]) 
{ 
    int n = DEPRECATED_MACRO1; 
    DEPRECATED_MACRO2("%d\n", n); 
    return 0; 
} 
+2

Это также работает с Clang/LLVM. – Isaac

+0

Это не работает wth gcc 4.3.3. Хороший вариант, хотя. – mjs

+0

@mjs Согласно [здесь] (https://www.gnu.org/software/gcc/c99status.html), '_Pragma' должен поддерживаться с gcc 3.0 (полная поддержка C99 с gcc 4.5). Возможно, вам придется включить C99 явно с '-std = c99' ранее до 4.5 (возможно, даже позже, не знаю, когда c99 получил стандарт для gcc ...), чтобы сделать эту работу. – Aconcagua

Смежные вопросы