Hi,
with a variable declared (in C) as follows
const char x[] __attribute__ ((weak)) = "X";
clang/llvm will use initializer value for optimizations.
gcc does not.
In clang variables with weak attribute gets “weak” linkage, unless they are const then they get “weak_odr” linkage. (CodeGenModule::getLLVMLinkageForDeclarator)
And “weak” linkage is “interposable” while “weak_odr” isn’t. (GlobalValue::isInterposableLinkage). Allowing optimizations to use the value of the initializer in the “weak_odr” case.
Is this expected/correct behavior?
Is there some specification describing this behavior?
Unfortunately the “weak” attribute isn’t documented in AttrDocs.td. And gcc’s documentation doesn’t help much, but does use the wording “overriding symbol” which definitely alludes to interposition being allowed.
The closest thing to documentation in clang I can find is this comment in the testcase:
https://github.com/llvm/llvm-project/blob/main/clang/test/CodeGen/global-init.c#L15
// Since this is marked const, it should get weak_odr linkage, since all
// definitions have to be the same.
// CHECK: @d = weak_odr constant i32 0
const int d __attribute__((weak))= 0;
I can easily accept that in case of multiple weak definitions of weak symbol all must have same value (odr).
However my intuition (which may be based on misunderstanding) is that a non-weak (strong) definition of that same symbol does not have to have the same value even if it is const. I would like to believe that the point of having weak symbols is that they provide a sort of default which can be overridden by a different value during linking (and that is how it works for non-const variables (and functions)).
Oh btw, the LangRef says
weak linkage has the same merging semantics as
linkonce
linkage, except that unreferenced globals withweak
linkage may not be discarded. This is used for globals that are declared “weak” in C source code.
Which leaves out the part about it not being used it is a const variable.
The reward for reading this far is an example showing the behavior in compiler explorer: Compiler Explorer