blob: aee7fba1227b70492405232b7827f1ad853ad8ff [file] [log] [blame]
Ryan Flynn8f6e88f2009-08-03 23:16:15 +00001// RUN: clang-cc -emit-llvm -o %t %s &&
2
3#pragma weak weakvar
4int weakvar;
5// RUN: grep '@weakvar = weak global' %t | count 1 &&
6
7#pragma weak weakdef
8void weakdef(void) {}
Daniel Dunbar7cfd8912009-08-04 04:38:31 +00009// RUN: grep 'define weak void @weakdef()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000010
11#pragma weak param // expected-warning {{weak identifier 'param' never declared}}
12#pragma weak correct_linkage
13void f(int param) {
14 int correct_linkage;
15}
16int correct_linkage;
17// RUN: grep '@correct_linkage = weak global' %t | count 1 &&
18
19#pragma weak weakvar_alias = __weakvar_alias
20int __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
26void __foo(void) {}
27// RUN: grep '@foo = alias weak void ()\* @__foo\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000028// RUN: grep 'define void @__foo()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000029
30
31void __foo2(void) {}
32#pragma weak foo2 = __foo2
33// RUN: grep '@foo2 = alias weak void ()\* @__foo2\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000034// RUN: grep 'define void @__foo2()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000035
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}}
43typedef int td;
44
45#pragma weak td2 = __td2 // expected-warning {{weak identifier '__td2' never declared}}
46typedef int __td2;
47
48
49///// test weird cases
50
51// test repeats
52
53#pragma weak stutter = __stutter
54#pragma weak stutter = __stutter
55void __stutter(void) {}
56// RUN: grep '@stutter = alias weak void ()\* @__stutter\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000057// RUN: grep 'define void @__stutter()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000058
59void __stutter2(void) {}
60#pragma weak stutter2 = __stutter2
61#pragma weak stutter2 = __stutter2
62// RUN: grep '@stutter2 = alias weak void ()\* @__stutter2\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000063// RUN: grep 'define void @__stutter2()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000064
65
66// test decl/pragma weak order
67
68void __declfirst(void);
69#pragma weak declfirst = __declfirst
70void __declfirst(void) {}
71// RUN: grep '@declfirst = alias weak void ()\* @__declfirst\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000072// RUN: grep 'define void @__declfirst()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000073
74void __declfirstattr(void) __attribute((noinline));
75#pragma weak declfirstattr = __declfirstattr
76void __declfirstattr(void) {}
77// RUN: grep '@declfirstattr = alias weak void ()\* @__declfirstattr\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000078// RUN: grep 'define void @__declfirstattr()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000079
80//// test that other attributes are preserved
81
82//// ensure that pragma weak/__attribute((weak)) play nice
83
84void mix(void);
85#pragma weak mix
86__attribute((weak)) void mix(void) { }
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000087// RUN: grep 'define weak void @mix()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000088
89// ensure following __attributes are preserved and that only a single
90// alias is generated
91#pragma weak mix2 = __mix2
92void __mix2(void) __attribute((noinline));
93void __mix2(void) __attribute((noinline));
94void __mix2(void) {}
95// RUN: grep '@mix2 = alias weak void ()\* @__mix2\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +000096// RUN: grep 'define void @__mix2()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +000097
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
102void both(void) __attribute((alias("__both")));
103#pragma weak both = __both
104void __both(void) {}
105// RUN: grep '@both = alias void ()\* @__both\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000106// RUN: grep 'define void @__both()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000107
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
112void __both2(void);
113void both2(void) __attribute((alias("__both2"))); // first, wins
114#pragma weak both2 = __both2
115void __both2(void) {}
116// RUN: grep '@both2 = alias void ()\* @__both2\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000117// RUN: grep 'define void @__both2()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000118
119void __both3(void);
120#pragma weak both3 = __both3 // first, wins
121void both3(void) __attribute((alias("__both3")));
122void __both3(void) {}
123// RUN: grep '@both3 = alias weak void ()\* @__both3\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000124// RUN: grep 'define void @__both3()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000125
126///////////// ensure that #pragma weak does not alter existing __attributes()
127
128void __a1(void) __attribute((noinline));
129#pragma weak a1 = __a1
130void __a1(void) {}
131// RUN: grep '@a1 = alias weak void ()\* @__a1\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000132// RUN: grep 'define void @__a1()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000133
134// attributes introduced BEFORE a combination of #pragma weak and alias()
135// hold...
136void __a3(void) __attribute((noinline));
137#pragma weak a3 = __a3
138void a3(void) __attribute((alias("__a3")));
139void __a3(void) {}
140// RUN: grep '@a3 = alias weak void ()\* @__a3\>' %t | count 1 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000141// RUN: grep 'define void @__a3()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000142
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 &&
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000146// RUN: grep 'define .*fastcall.* void @__xxx()' %t | count 1 &&
Ryan Flynn8f6e88f2009-08-03 23:16:15 +0000147
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.
154void yyy(void){}
155void zzz(void){}
156#pragma weak yyy
157// NOTE: weak doesn't apply, not before or in same TopLevelDec(!)
Daniel Dunbar7cfd8912009-08-04 04:38:31 +0000158// RUN: grep 'define void @yyy()' %t | count 1