-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#pragma weak doesn't work #4051
Comments
Wow... It seems like really ugly way to define symbol aliases... Pawel, could you please attach the .s file generated by gcc? |
Assembly from gcc |
|
This also affects FreeBSD's rtld-elf. clang output: gcc output: code: int x = 0; |
Seems to do exactly the same thing as attribute((weak)), as expected. |
It seems it's also allowed to just use #pragma weak. In that case it applies to the beforementioned symbol. |
Test case:// RUN: clang -verify -emit-llvm -o %t %s && /* expecting-warning {{malformed #pragma weak, ignored}} */ #pragma weak #pragma weak g1 int g4;
|
Doug and I discussed this a bit today. Our overwhelming opinion is that all but the first usage (from #7) are really gross and we would lean towards not supporting them if at all possible. How much work would fixing this in the original source be? This seems like a pretty esoteric feature and using attributes for this task is a much nicer solution, so NTBF doesn't seem out of the question. However, a little googling does turn up some other references to it, for example it looks like IBM implements it, so it may be more widespread than I think. |
It isn't hard for us to change the code, but the problem we're having, is that we also have a lot of contributed vendor code in our source tree. I think I saw the first usage being used a Sun ZFS library, for example. The problem is that it's hard convince the maintainers to just edit their vendor code. But still, supporting at least a subset of possible notations would be an improvement. As long as Clang throws errors when using unsupported constructs, it's fine by me. The problem is that they go by unnoticed right now, which leads to all sorts of miscompilations. |
That makes sense (vendor contributed issues). We will certainly at least error on the construct if we are going to try to not support it. I'll discuss this some more tomorrow with interested parties and try to get a consensus. |
Just wondering if there's any progress on this bug, either as a patch or WONTFIX . It's preventing LLVM from compiling rtld-elf, csu, libc, libutil, librt and libzpool on FreeBSD. I've compiled a list of the documented behaviour of this directive in other compilers: http://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html Thanks! |
This is the only form that really bothers me. The others are relatively easy to track. |
There are around 50 occurrences of #pragma weak in the FreeBSD source tree. They are all either of the form #pragma weak a or #pragma weak a = b |
I've just committed r72907 and r72912, which are the start of an implementation; it's sufficient for writing code using #pragma weak that works with both clang and other compilers, but it's probably not enough to be compatible with a lot of already-written code. |
Thanks for working on this! As far as I can see from your patches, the following are now supported: int g0; int g1 = 0; It seems a lot of code uses the form: #pragma weak g2 = long_function but at least it can be rearranged so it compiles. |
Right.
Wrong; the supported form is the following: extern void g2; Basically, the #pragma weak can't introduce a new name, but it can alias an existing name to a name that isn't defined yet. |
These are just preliminary results, but it seems this is sufficient for Solaris's libzpool, but not libzfs and libc. I'll take a closer look at this after I've finished my builds. Stay tuned. |
Unfortunately in case of libc, where we mark functions as weak like this void it doesn't seem to have any effect. This is the diff between nm output on libc built with gcc and clang: --- libc.gcc 2009-06-06 18:57:53.000000000 +0200 |
Errr... #pragma weak func that's what we use. |
Ah, yes. It turns out the issue is a little more complex than I thought. This works: void #pragma weak func1 void #pragma weak func2 while this does not: void void #pragma weak func1 |
Ah, right... the current approach for Sema isn't really correct. I'm still not quite sure about the best way to write it. |
r77660 handles the original test case and should cover the subsequent issues brought up by the FreeBSD libraries (though I have not tested them directly). the case mentioned in comment #20 is not covered due to the way clang's Parser and ASTConsumer currently work. clang/test/Sema/pragma-weak.c cover all the cases I could think of, including combinations of #pragma weak and other attributes, including alias(...). if i've forgotten anything please let me know. #pragma weak ok int ok2; #pragma weak alias_ok = __alias_ok; int broken; |
Is this done enough for FreeBSD, or are important cases still missing? |
I think comment 20 is an important case (according to comment 18, it shows up in FreeBSD libc). It's kind of nasty, though, because it's essentially applying an attribute after the definition, which we don't generally support. |
i'm sorry i wasn't more specific; my patch addresses everything except this case from comment 20: void void #pragma weak func1 that is, it won't work if the #pragma weak does not appear before or in the same "TopLevelDecl" as the identifier it references, due to the way Parser and ASTConsumer currently work. i couldn't find this particular case in FreeBSD's libc at http://fxr.watson.org/fxr/search?v=FREEBSD-LIBC&string=%23pragma+weak |
I checked the uses of pragma weak in FreeBSD sources. Of the 50 occurrencies, 5 are still not covered by the latest patches: http://svn.freebsd.org/viewvc/base/head/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c?view=markup line 50 I'm really no C expert, but I expect that we can rewrite 2 and 3 to something parseable by LLVM. 5 is less important for obvious reasons. This leaves 1 and 4 which are Solaris code. I'll leave it to others to recommend an upstream patch, a local patchset or simply gcc-compile this specific code for the time being. |
Just a side note, We, AuroraUX are running into some of the very same issues as the FreeBSD guys as: As of (B.) the affects on us are current more severe just due to the number of occurrences of this sort of thing. Although our porting effort is not as far along as the Clang-FreeBSD lads; I say this as it may affect the out come of if this bug gets 'fully' fixed or code twisted to suit clang better. As both GCC and Sun Studio handle this code, (libzfs), I vote clang should to. Just my 2 pennies :) |
Thanks for the feedback guys, I'm on it. |
Erik, As far as I can tell the first case should work, i.e. pizza@pie: Could you provide a testcase? |
I should have added that my review was only by grep'ing, not actual compile failures. I thought the pragma weak needed to be adjacent to the statement, but apparently this also works: #pragma weak foo = bar In that case I agree that 1 and probably 3 in comment #26 are OK. |
r78016 adds the test file clang/test/Sema/pragma-weak.c which outlines exactly what is and is not supported. |
Daniel and I figured out why the code in comment #20 does what it does, and it's rather funny. The basic problem is that we cannot handle a #pragma weak foo that occurs after the function foo() was defined, because CodeGen has already seen the definition and does not know to change the definition to have weak linkage. We'll need to add another ASTConsumer hook---say, AttributeAddedToDecl(Attr*, Decl*)---that CodeGen can use to change the linkage and/or add an alias. Why does the code at the beginning of comment #20 work, then? Well, it's very funny: when the lexer tries to consume the '}' token to finish the function definition, it goes ahead and finds the next token. In doing so, the #pragma weak handler fires... and the function that is being defined gets marked as weak before CodeGen gets the definition. It's almost like we'd written void func1(void) { |
Doug, what is the status of this? I recall we had a nice discussion about it, but I forget what we concluded... :) |
AFAIK, nothing has changed since comment 32. |
We concluded that we need to add ASTConsumer::AttributeAddedToDecl, to cope with cases where we see #pragma weak after we see the definition of the entity. There hasn't been any implementation progress, though. |
I would like to add that the code of several packages in Fedora (10, 11 and 12) cannot be successfully parsed because of this problem. |
Another case of weakref. This time with attibute
|
That isn't really the same issue; could you file a separate bug? |
Sure, filed comment #37 as bug 5621. |
There is a bug in #pragma weak, relating to the use of static keyword along with a variable whose alias we create through the use of #pragma weak. I have attached the file weak-14.c, here Av1a is created as an alias to lv1. lv1 is static here and there is a declaration of Av1a (extern unsigned long Av1a) just after Av1a has been declared as the alias to lv1(using #pragma weak). The problem being faced is that Av1a should have its value as the value of lv1, which is not the case and hence the if condition is failing and the test case is aborting(which is not the correct behaviour). For the case of function Af1a everything works fine. When we check for the value of Av1a using a printf statement, we see that it is 0. The test case passes when we comment out the check in the if condition, || Av1a != 0xdeadbeefUL. What is interesting is that, when we remove static keyword from lv1, this case passes and Av1a is assigned the correct value. Also when we comment extern unsigned long Av1a(the declaration of Av1a) and dont remove the static keyword from lv1, the case works fine, with correct value getting assigned to Av1a. Compilation command to create executable: |
test file for the failure of pragma weak with use of static keyword for a variable. |
It was just brought to my attention that this may be causing problems with MPICH as well: https://trac.mpich.org/projects/mpich/ticket/1815 |
In the file SemaDeclAttr.cpp replace VD->getStorageClass()and VD->getStorageClassAsWritten() with SC_None. This solves the problem related to pragma weak. It might be applicable for your problem as well. |
mentioned in issue llvm/llvm-bugzilla-archive#4696 |
Cherry pick two swift changes from next branch
This seem to be fixed. Clang emits a error for the testcase now:
Removing |
Extended Description
0>root@one /tmp# gcc -o t t.c
0>root@one /tmp# ./t
spasiba
0>root@one /tmp# ccc -o t t.c
/tmp/tmpTGEXC1.o(.text+0x2b): In function
main': : undefined reference to
t'The text was updated successfully, but these errors were encountered: