Search code examples
c++classattributesc-preprocessorlinkage

Is it possible to use a macro defined value in C/C++?


In the LLVM codebase, I see this lines:

class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
                                          public ilist_node<Function> {

My LSP (clangd) tells me that LLVM_EXTERNAL_VISIBILITY refers to

/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
/// into a shared library, then the class should be private to the library and
/// not accessible from outside it.  Can also be used to mark variables and
/// functions, making them private to any shared library they are linked into.
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
///
/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
/// this attribute will be made public and visible outside of any shared library
/// they are linked in to.
#if __has_attribute(visibility) &&                                             \
    (!(defined(_WIN32) || defined(__CYGWIN__)) ||                              \
     (defined(__MINGW32__) && defined(__clang__)))
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
#else
#define LLVM_EXTERNAL_VISIBILITY     // <-------------- THIS
#endif
#else
#define LLVM_LIBRARY_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
#endif

I can't figure out the usefulness: why should I #define an identifier without a value, but using that as if it had one?

One idea is that it acts as a conditional: if something happens, then the preprocessor substitutes some text; if not, it simply doesn't substitute anything, but prevents the compiler from complaining about some undefined LLVM_LIBRARY_VISIBILITY token. Is this correct?

Moreover, what kind of attributes can be specified there? Something about the linkage of the class?

Thanks!


Solution

  • One idea is that it acts as a conditional: if something happens, then the preprocessor substitutes some text; if not, it simply doesn't substitute anything, but prevents the compiler from complaining about some undefined LLVM_LIBRARY_VISIBILITY token. Is this correct?

    Pretty much. Some build environments, it'll have a value. Others not. Seems mainly a matter of portability.

    __attribute__((visibility("default"))) refers to the visibility of the symbol it is attached to. The default visibility can be changed at compile time.