Reputation: 43
I am trying to make sense of the libspatialindex source code. Being new to c++, I have difficulty wrapping my head around the concept of macros. The library’s API wrapper for C, sidx_api.cc, directly and indirectly includes numerous headers two of which seemingly define the same macro, concerned with interfacing a dynamic library, without ‘undef’:
45 #if (defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64) && !defined __GNUC__
46 #ifdef SIDX_DLL_EXPORT
47 #define SIDX_DLL __declspec(dllexport)
48 #else
49 #define SIDX_DLL __declspec(dllimport)
50 #endif
51
52 // Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
53 #pragma warning( disable: 4251 )
54
55 #else
56 #define SIDX_DLL
57 #endif
29 #pragma once
30
31 #ifndef SIDX_C_DLL
32 #if defined(_MSC_VER)
33 # define SIDX_C_DLL __declspec(dllexport)
34 # define SIDX_DLL __declspec(dllexport)
35 #else
36 # if defined(USE_GCC_VISIBILITY_FLAG)
37 # define SIDX_C_DLL __attribute__ ((visibility("default")))
38 # define SIDX_DLL __attribute__ ((visibility("default")))
39 # else
40 # define SIDX_C_DLL
41 # define SIDX_DLL
42 # endif
43 #endif
44 #endif
I believe that redefining a macro without ‘undef’ is problematic, e.g., as discussed here and here. Am I missing something here? Thanks.
Upvotes: 3
Views: 1438
Reputation: 120079
No macro is illegally redefined here. Some may be defined more than once with identical definitions, which is OK. It's non-identical definitions that constitute a problem.
The DLL itself is always built with SIDX_DLL_EXPORT
defined by the project settings. Code that uses the DLL is built without this macro being defined.
The second header is a part of the DLL. It is always compiled with SIDX_DLL_EXPORT
being defined. Thus the macros defined by it, if any, are always identical to those defined in the first header. Such identical redefinition does not constitute a problem.
Upvotes: 4
Reputation: 15803
If you redefine it you need to redefine it using exactly the same list of preprocessing tokens. This is true for function-macros and for object-macros.
From 6.10.3 Macroreplacement p2
:
An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical.
Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.
So this definitions use shall
.
Now, from 4.Conformance p2
:
If a ‘‘shall’’or‘‘shall not’’requirement that appears outside of a constraint is violated, the behavior is undefined.
This is the official definition. So, without dropping the macro symbol out from the environment of the preprocessor (using #undef) before you redefine it you get undefined behavior.
In case you find other situation in some implementations of C, this is not standardized.
Correctly it would be to insert different definitions in function of some condition that you set outside:
#if COND
#define M M1
#else
#define M M2
#endif
If you use some library that redefines it, for sure there are some macros that set the COND
and make the things well defined. You need to learn how to use the library. Redefining it with different list of pp tokens is not valid.
Upvotes: 2