Ryan Flynn | 8f6e88f | 2009-08-03 23:16:15 +0000 | [diff] [blame^] | 1 | // RUN: clang-cc -emit-llvm -o %t %s && |
| 2 | |
| 3 | #pragma weak weakvar |
| 4 | int weakvar; |
| 5 | // RUN: grep '@weakvar = weak global' %t | count 1 && |
| 6 | |
| 7 | #pragma weak weakdef |
| 8 | void weakdef(void) {} |
| 9 | // RUN: grep 'define weak void @weakdef() nounwind {' %t | count 1 && |
| 10 | |
| 11 | #pragma weak param // expected-warning {{weak identifier 'param' never declared}} |
| 12 | #pragma weak correct_linkage |
| 13 | void f(int param) { |
| 14 | int correct_linkage; |
| 15 | } |
| 16 | int correct_linkage; |
| 17 | // RUN: grep '@correct_linkage = weak global' %t | count 1 && |
| 18 | |
| 19 | #pragma weak weakvar_alias = __weakvar_alias |
| 20 | int __weakvar_alias; |
| 21 | // RUN: grep '@__weakvar_alias = common global' %t | count 1 && |
| 22 | // RUN: grep '@weakvar_alias = alias weak i32\* @__weakvar_alias' %t | count 1 && |
| 23 | //@weakvar_alias = alias weak i32* @__weakvar_alias |
| 24 | |
| 25 | #pragma weak foo = __foo |
| 26 | void __foo(void) {} |
| 27 | // RUN: grep '@foo = alias weak void ()\* @__foo\>' %t | count 1 && |
| 28 | // RUN: grep 'define void @__foo() nounwind {' %t | count 1 && |
| 29 | |
| 30 | |
| 31 | void __foo2(void) {} |
| 32 | #pragma weak foo2 = __foo2 |
| 33 | // RUN: grep '@foo2 = alias weak void ()\* @__foo2\>' %t | count 1 && |
| 34 | // RUN: grep 'define void @__foo2() nounwind {' %t | count 1 && |
| 35 | |
| 36 | |
| 37 | ///// test errors |
| 38 | |
| 39 | #pragma weak unused // expected-warning {{weak identifier 'unused' never declared}} |
| 40 | #pragma weak unused_alias = __unused_alias // expected-warning {{weak identifier '__unused_alias' never declared}} |
| 41 | |
| 42 | #pragma weak td // expected-warning {{weak identifier 'td' never declared}} |
| 43 | typedef int td; |
| 44 | |
| 45 | #pragma weak td2 = __td2 // expected-warning {{weak identifier '__td2' never declared}} |
| 46 | typedef int __td2; |
| 47 | |
| 48 | |
| 49 | ///// test weird cases |
| 50 | |
| 51 | // test repeats |
| 52 | |
| 53 | #pragma weak stutter = __stutter |
| 54 | #pragma weak stutter = __stutter |
| 55 | void __stutter(void) {} |
| 56 | // RUN: grep '@stutter = alias weak void ()\* @__stutter\>' %t | count 1 && |
| 57 | // RUN: grep 'define void @__stutter() nounwind {' %t | count 1 && |
| 58 | |
| 59 | void __stutter2(void) {} |
| 60 | #pragma weak stutter2 = __stutter2 |
| 61 | #pragma weak stutter2 = __stutter2 |
| 62 | // RUN: grep '@stutter2 = alias weak void ()\* @__stutter2\>' %t | count 1 && |
| 63 | // RUN: grep 'define void @__stutter2() nounwind {' %t | count 1 && |
| 64 | |
| 65 | |
| 66 | // test decl/pragma weak order |
| 67 | |
| 68 | void __declfirst(void); |
| 69 | #pragma weak declfirst = __declfirst |
| 70 | void __declfirst(void) {} |
| 71 | // RUN: grep '@declfirst = alias weak void ()\* @__declfirst\>' %t | count 1 && |
| 72 | // RUN: grep 'define void @__declfirst() nounwind {' %t | count 1 && |
| 73 | |
| 74 | void __declfirstattr(void) __attribute((noinline)); |
| 75 | #pragma weak declfirstattr = __declfirstattr |
| 76 | void __declfirstattr(void) {} |
| 77 | // RUN: grep '@declfirstattr = alias weak void ()\* @__declfirstattr\>' %t | count 1 && |
| 78 | // RUN: grep 'define void @__declfirstattr() nounwind noinline {' %t | count 1 && |
| 79 | |
| 80 | //// test that other attributes are preserved |
| 81 | |
| 82 | //// ensure that pragma weak/__attribute((weak)) play nice |
| 83 | |
| 84 | void mix(void); |
| 85 | #pragma weak mix |
| 86 | __attribute((weak)) void mix(void) { } |
| 87 | // RUN: grep 'define weak void @mix() nounwind {' %t | count 1 && |
| 88 | |
| 89 | // ensure following __attributes are preserved and that only a single |
| 90 | // alias is generated |
| 91 | #pragma weak mix2 = __mix2 |
| 92 | void __mix2(void) __attribute((noinline)); |
| 93 | void __mix2(void) __attribute((noinline)); |
| 94 | void __mix2(void) {} |
| 95 | // RUN: grep '@mix2 = alias weak void ()\* @__mix2\>' %t | count 1 && |
| 96 | // RUN: grep 'define void @__mix2() nounwind noinline {' %t | count 1 && |
| 97 | |
| 98 | ////////////// test #pragma weak/__attribute combinations |
| 99 | |
| 100 | // if the SAME ALIAS is already declared then it overrides #pragma weak |
| 101 | // resulting in a non-weak alias in this case |
| 102 | void both(void) __attribute((alias("__both"))); |
| 103 | #pragma weak both = __both |
| 104 | void __both(void) {} |
| 105 | // RUN: grep '@both = alias void ()\* @__both\>' %t | count 1 && |
| 106 | // RUN: grep 'define void @__both() nounwind {' %t | count 1 && |
| 107 | |
| 108 | // if the TARGET is previously declared then whichever aliasing method |
| 109 | // comes first applies and subsequent aliases are discarded. |
| 110 | // TODO: warn about this |
| 111 | |
| 112 | void __both2(void); |
| 113 | void both2(void) __attribute((alias("__both2"))); // first, wins |
| 114 | #pragma weak both2 = __both2 |
| 115 | void __both2(void) {} |
| 116 | // RUN: grep '@both2 = alias void ()\* @__both2\>' %t | count 1 && |
| 117 | // RUN: grep 'define void @__both2() nounwind {' %t | count 1 && |
| 118 | |
| 119 | void __both3(void); |
| 120 | #pragma weak both3 = __both3 // first, wins |
| 121 | void both3(void) __attribute((alias("__both3"))); |
| 122 | void __both3(void) {} |
| 123 | // RUN: grep '@both3 = alias weak void ()\* @__both3\>' %t | count 1 && |
| 124 | // RUN: grep 'define void @__both3() nounwind {' %t | count 1 && |
| 125 | |
| 126 | ///////////// ensure that #pragma weak does not alter existing __attributes() |
| 127 | |
| 128 | void __a1(void) __attribute((noinline)); |
| 129 | #pragma weak a1 = __a1 |
| 130 | void __a1(void) {} |
| 131 | // RUN: grep '@a1 = alias weak void ()\* @__a1\>' %t | count 1 && |
| 132 | // RUN: grep 'define void @__a1() nounwind noinline {' %t | count 1 && |
| 133 | |
| 134 | // attributes introduced BEFORE a combination of #pragma weak and alias() |
| 135 | // hold... |
| 136 | void __a3(void) __attribute((noinline)); |
| 137 | #pragma weak a3 = __a3 |
| 138 | void a3(void) __attribute((alias("__a3"))); |
| 139 | void __a3(void) {} |
| 140 | // RUN: grep '@a3 = alias weak void ()\* @__a3\>' %t | count 1 && |
| 141 | // RUN: grep 'define void @__a3() nounwind noinline {' %t | count 1 && |
| 142 | |
| 143 | #pragma weak xxx = __xxx |
| 144 | __attribute((pure,noinline,const,fastcall)) void __xxx(void) { } |
| 145 | // RUN: grep '@xxx = alias weak void ()\* @__xxx\>' %t | count 1 && |
| 146 | // RUN: grep 'define .*fastcall.* void @__xxx() nounwind readnone noinline {' %t | count 1 && |
| 147 | |
| 148 | /// TODO: stuff that still doesn't work |
| 149 | |
| 150 | // due to the fact that disparate TopLevelDecls cannot affect each other |
| 151 | // (due to clang's Parser and ASTConsumer behavior, and quite reasonable) |
| 152 | // #pragma weak must appear before or within the same TopLevelDecl as it |
| 153 | // references. |
| 154 | void yyy(void){} |
| 155 | void zzz(void){} |
| 156 | #pragma weak yyy |
| 157 | // NOTE: weak doesn't apply, not before or in same TopLevelDec(!) |
| 158 | // RUN: grep 'define void @yyy() nounwind {' %t | count 1 |