5

With GCC & Clang you can deprecate struct members, (as shown below).

However I didn't see a way to do this for other compilers (MSVC for example).

While this isn't apart of the C spec and most likely relies on pragma's or custom extensions for each compiler, it would be useful to be able to support this across a wider range of compilers.

/* mytest.h */
#ifdef __GNUC__
#  define ATTR_DEPRECATED __attribute__((deprecated))
#else
#  define ATTR_DEPRECATED  /* unsupported compiler */
#endif

struct Test {
  int bar;
  int foo  ATTR_DEPRECATED;
};

Once a member is deprecated, the compiler should warn of its use if its accessed directly, eg:

#include "mytest.h"
static func(void)
{
    Test t;
    t.bar = 1;
    t.foo = 0;  /* <-- WARN ABOUT THIS AT COMPILE TIME */
}
ideasman42
  • 42,413
  • 44
  • 197
  • 320

4 Answers4

2

Besides compilers which support GCC's __attribute__((deprecated)) (Clang for example) there aren't conventions for MSVC to deprecate struct members (With MSVC you can deprecate the identifier but that applies globally, not just to that struct).

Also no other conventions for other C compilers have been posted. So it looks like this is GCC specific.

ideasman42
  • 42,413
  • 44
  • 197
  • 320
1

Put simply, there isn't a one-way fits all thing here. Some compilers simply don't support such ideas. I will suggest something along the lines of this however, duplicated here (with some modification):

#ifdef __GNUC__
   #define ATTR_DEPRECATED __attribute__((deprecated))
#elif defined _MSC_VER
   //List of deprecated values
   #pragma deprecated(values)
#endif

Unfortunately, this requires a #pragma line for every deprecated member but hey. Also, as ideasman points out in the comments, the deprecated pragma is global, so if you have an instance with the same name as your struct member anywhere, it will be marked.

Community
  • 1
  • 1
Sinkingpoint
  • 7,449
  • 2
  • 29
  • 45
  • @DAhrens Not according to [this](http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html) – Sinkingpoint Apr 02 '14 at 21:54
  • The problem with MSVC's `deprecated` pragma, is its global, it applies to any matching id, so you couldn't for example deprecate `x`, in a struct member, or it would complain of any instance of `x` used anywhere else (as a local variable for example). – ideasman42 Apr 02 '14 at 21:56
  • @ideasman42 Moved that into the answer with accreditation, hope you don't mind :) – Sinkingpoint Apr 02 '14 at 21:59
  • @Quirliom It was an incomplete comment. I decided to post it as an answer instead. – DAhrens Apr 02 '14 at 21:59
1

Perhaps something more along the lines of this:

#ifdef __GNUC__
    #define DEPRECATED(x) x __attribute__((deprecated))
#elif defined _MSC_VER
    #define DEPRECATED(x) __pragma deprecated(x)
#else
    #define DEPRECATED(x) x
#endif

edit: this is based on Quirliom's answer 2nd edit: fixed #pragma to be __pragma as suggested by ideasman42

DAhrens
  • 380
  • 1
  • 10
  • 3
    `#pragma` should be renamed to `__pragma` when used in a define. As stated already, this works on a global identifier level, so you can't reference a struct member directly this way. – ideasman42 Apr 02 '14 at 21:59
  • Thanks for the comment. Am I right to presume this would still work for a function definition? – DAhrens Apr 02 '14 at 22:05
  • 1
    yes, but for MSVC function definition there is already `__declspec(deprecated)` – ideasman42 Apr 02 '14 at 22:07
  • Alright. Not very familiar with MSVC myself. Spend all of my time on GCC. – DAhrens Apr 02 '14 at 22:09
  • same, just trying to make life easier for our windows devs, but seems not possible in this case. – ideasman42 Apr 02 '14 at 22:25
-1

If all of deprecated structure members have names which are unique to the structure, it may be possible to replace the structure with one that contains an array of a structure containing the real values but slightly different names, and then use #define to create macros that define all of the structure's elements.

For example, if the old structure was:

typedef struct {
  int FOO_first;
  int FOO_second;
  long FOO_third;
} FOO;

one could replace it with:

#define WARNING_ZERO (2u < -1) // An expression which will yield a constant zero but print a warning

#define FOO_second (FOOO_second[WARNING_ZERO])

typedef struct {
  int FOO_first;
  int FOOO_second[1];
  long FOO_third;
}

Unfortunately, I don't know any way to make that technique work in C if the names of any deprecated items are used as identifiers for any other purpose.

supercat
  • 77,689
  • 9
  • 166
  • 211