8

I just discovered the #pragma weak directive in GCC:

6.57.9 Weak Pragmas

For compatibility with SVR4, GCC supports a set of #pragma directives for declaring symbols to be weak, and defining weak aliases.

#pragma weak symbol

This pragma declares symbol to be weak, as if the declaration had the attribute of the same name. The pragma may appear before or after the declaration of symbol. It is not an error for symbol to never be defined at all.

#pragma weak symbol1 = symbol2

This pragma declares symbol1 to be a weak alias of symbol2. It is an error if symbol2 is not defined in the current translation unit.

http://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html

Despite the fact that the GCC developers generally don't like #pragma and encourage you to use __attribute__ instead for all sorts of things that could be pragmas, I'm inclined to believe #pragma weak may actually be superior to the attribute-based approach, which looks like:

extern __typeof(old_name) new_name __attribute__(weak, alias("old_name"))

Aside from the ugliness of requiring __typeof (or requiring you to know the type and spell it out explicitly, even if it's a really complex function type), the biggest issue of the attribute based approach is that "old_name" must be passed to gcc as a string to be pasted literally into the generated assembly. This is problematic because different systems have different name-mangling characteristics (most popular is prefixing an underscore on all C symbol names, or doing nothing at all), and to pass the correct string to the alias attribute, you need to know the name mangling convention of the system you're building for, which is really not knowledge that belongs in an application-level library where weak aliases might be useful.

The syntax #pragma weak new_name = old_name seems to avoid this issue by handling both names at the compiler level, where t can mangle them both appropriately, unless I'm mistaken.

So with all the preliminaries finished, my actual questions are: Am I mistaken about #pragma weak having this "portability" advantage? and Do all modern compilers on unix-like systems (gcc, pcc, tinycc, icc, llvm/clang, etc.) still support the traditional SVR4 #pragma weak?

I'm aware of the following similar question, but it does not seem quite the same and the answers to not satisfactorily address my question:

How portable is weak linking? #pragma weak my_symbol

Community
  • 1
  • 1
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • I've looked at the internals of `#pragma weak` and it is very flimsy. The `__attribute__` version uses much more reliable compiler code. And personally, I've never used `typeof`, just repeated the declaration. – o11c Jul 08 '18 at 21:31

1 Answers1

5

Neither "#pragma weak" nor __attribute__ is part of the C standard, so neither is, strictly speaking, portable. Some C compilers strive to be compatible with most of GCC's extensions to the C standard, others do not.

Generally speaking, if you're already at the level of talking about weak symbols and weak aliases, you probably are past the point where you can write code that is reliably portable across compilers. Even your toolchain will become an issue here (including especially the linker) -- I don't think you can rely on anything without carefully testing.

Edited to add: The original poster commented below asking whether, pragmatically, #pragma is no less portable than __attribute__.

My own experience has been this: it is nice to be able to hide all such things inside of macros or other generated code in order to make portability easier. __attribute__ is easier to conceal inside a portability header file. For example, at least one of the BSD kernels has a cdefs.h that uses __attribute__ inside a macro to centralize the way that weak definitions are done throughout the code base to allow easier changes to new compilers. #pragma is harder to use in that manner. Such a macro can also conceal the difference between various name manglings by using the CPP pasting operator ("##" etc.)

For an example of such usage, see: http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/cdefs.h?rev=1.89.6.1&content-type=text/x-cvsweb-markup

Perry
  • 4,363
  • 1
  • 17
  • 20
  • I suppose this answer may be useful to some readers, but it doesn't provide any information I didn't already have. My question is basically whether `#pragma weak` is *more portable than* `__attribute__((weak, alias))` or at least *no less portable*, including the matter of whether I'm correct about it avoiding the name mangling issue. – R.. GitHub STOP HELPING ICE Feb 27 '12 at 21:56
  • 1
    Neither is portable by any reasonable measure. As for whether #pragma is "no less portable", I'd suggest that it probably isn't as good a choice, and I'll explain why in an edit above. – Perry Feb 27 '12 at 21:59
  • 1
    Once you have it wrapped in a macro, it makes no strong difference which one you use, because at that point you can simply pick whatever is supported by the local compiler, placing appropriate #ifdefs into your portability include file conditioned by a predef that selects the compiler. However, yes, \_Pragma at that point could would work just as well in the macro. Again, though, at this point you're no longer asking "what is portable" but "how do I pragmatically achieve this in multiple compilers", and the answer is usually a conditionally defined macro. – Perry Feb 27 '12 at 22:36
  • OK, your answer is at least somewhat more useful now, but it still doesn't address the core factual part of the question (whether one particular set of compilers is a subset of another). – R.. GitHub STOP HELPING ICE Feb 28 '12 at 14:47
  • Please notice that `#pragma weak` is not a gcc extension (as your answer hints), it's much older. – fuz Jan 06 '16 at 12:41