views:

218

answers:

3

Hi,

i Know how to use attribute deprecated to deprcate a function like this:

int old_fn () __attribute__ ((deprecated));

But how to deprecate a Macro like this:

#define OLD_MACRO 1

Thank you in advance.

Eric

A: 

Since Macros are not part of the compiler (they are a pre-processor function), there is no clean way of doing this. At best, place your deprecated macros in a new header file filled with #warnings. This will of course break existing code, but its one way to guarantee drawing attention to the deprecation.

Yann Ramin
+6  A: 

I think the best you can do is something like this:

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

This way you force the user to e.g. add -DUSE_DEPRECATED_MACROS to their compiler options and they get a warning.

Paul R
+1; great mini hack
Iulian Şerbănoiu
As a matter of taste, I would prefer to have the user `#define USE_DEPRECATED_MACROS 1` in their source before the `#include` rather than putting the flag in through the command line... but really, same result either way; they have to know what they're doing, and can back it out when possible (and lose the warning thereby). Good call!
Charles Duffy
I'd do it the other way around: `#ifndef NO_DEPRECATED_MACROS`. That way, you issue the warning while maintaining source-compatibility for clients of your header file. The user can then add `NO_DEPRECATED_MACROS` to get rid of the warning, rather than his build breaking when he takes the new header file, and him having to read the release notes to find out why OLD_MACRO is gone. Of course if the user uses `-Werror` it all amounts to the same thing, but if he doesn't then maybe that's precisely because he doesn't want his build falling over because you're tinkering with warnings ;-)
Steve Jessop
+1  A: 

You could make sure that these macros would expand to something that would include a expression that would trigger the attribut((deprecated)) warning.

For function-like macros this is pretty easy (especially with the comma operator), but for constant defines or nonstandard macros this may be more complicated, since the context in which these expand is different. I think you could do:

#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

For a constant define you probably want to assume that the body has to evaluate without having to generate code, such as outside of a function body, in the targets of a switch/case, or as the initial value of a static variable within a function.

This is tricky, but you may be able to do it for many things.

I wish that C had a __builtin_warn(const char *) that would work at the compiler level (not-preprocessor) and make things like this easier.

nategoose