summaryrefslogtreecommitdiff
path: root/clang/test/CodeGen/pragma-weak.c
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CodeGen/pragma-weak.c')
-rw-r--r--clang/test/CodeGen/pragma-weak.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/clang/test/CodeGen/pragma-weak.c b/clang/test/CodeGen/pragma-weak.c
new file mode 100644
index 0000000..7ad2b77
--- /dev/null
+++ b/clang/test/CodeGen/pragma-weak.c
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - -verify | FileCheck %s
+
+// CHECK: @weakvar = weak global
+// CHECK: @__weakvar_alias = common global
+// CHECK: @correct_linkage = weak global
+
+
+// CHECK: @both = alias void ()* @__both
+// CHECK: @both2 = alias void ()* @__both2
+// CHECK: @both3 = alias weak void ()* @__both3
+// CHECK: @a3 = alias weak void ()* @__a3
+// CHECK: @weakvar_alias = alias weak i32* @__weakvar_alias
+// CHECK: @foo = alias weak void ()* @__foo
+// CHECK: @foo2 = alias weak void ()* @__foo2
+// CHECK: @stutter = alias weak void ()* @__stutter
+// CHECK: @stutter2 = alias weak void ()* @__stutter2
+// CHECK: @declfirst = alias weak void ()* @__declfirst
+// CHECK: @declfirstattr = alias weak void ()* @__declfirstattr
+// CHECK: @mix2 = alias weak void ()* @__mix2
+// CHECK: @a1 = alias weak void ()* @__a1
+// CHECK: @xxx = alias weak void ()* @__xxx
+
+
+
+// CHECK: define weak void @weakdef()
+
+
+#pragma weak weakvar
+int weakvar;
+
+#pragma weak weakdef
+void weakdef(void) {}
+
+#pragma weak param // expected-warning {{weak identifier 'param' never declared}}
+#pragma weak correct_linkage
+void f(int param) {
+ int correct_linkage;
+}
+
+#pragma weak weakvar_alias = __weakvar_alias
+int __weakvar_alias;
+
+#pragma weak foo = __foo
+void __foo(void) {}
+// CHECK: define void @__foo()
+
+
+void __foo2(void) {}
+#pragma weak foo2 = __foo2
+// CHECK: define void @__foo2()
+
+
+///// test errors
+
+#pragma weak unused // expected-warning {{weak identifier 'unused' never declared}}
+#pragma weak unused_alias = __unused_alias // expected-warning {{weak identifier '__unused_alias' never declared}}
+
+#pragma weak td // expected-warning {{weak identifier 'td' never declared}}
+typedef int td;
+
+#pragma weak td2 = __td2 // expected-warning {{weak identifier '__td2' never declared}}
+typedef int __td2;
+
+
+///// test weird cases
+
+// test repeats
+
+#pragma weak stutter = __stutter
+#pragma weak stutter = __stutter
+void __stutter(void) {}
+// CHECK: define void @__stutter()
+
+void __stutter2(void) {}
+#pragma weak stutter2 = __stutter2
+#pragma weak stutter2 = __stutter2
+// CHECK: define void @__stutter2()
+
+
+// test decl/pragma weak order
+
+void __declfirst(void);
+#pragma weak declfirst = __declfirst
+void __declfirst(void) {}
+// CHECK: define void @__declfirst()
+
+void __declfirstattr(void) __attribute((noinline));
+#pragma weak declfirstattr = __declfirstattr
+void __declfirstattr(void) {}
+// CHECK: define void @__declfirstattr()
+
+//// test that other attributes are preserved
+
+//// ensure that pragma weak/__attribute((weak)) play nice
+
+void mix(void);
+#pragma weak mix
+__attribute((weak)) void mix(void) { }
+// CHECK: define weak void @mix()
+
+// ensure following __attributes are preserved and that only a single
+// alias is generated
+#pragma weak mix2 = __mix2
+void __mix2(void) __attribute((noinline));
+void __mix2(void) __attribute((noinline));
+void __mix2(void) {}
+// CHECK: define void @__mix2()
+
+////////////// test #pragma weak/__attribute combinations
+
+// if the SAME ALIAS is already declared then it overrides #pragma weak
+// resulting in a non-weak alias in this case
+void both(void) __attribute((alias("__both")));
+#pragma weak both = __both
+void __both(void) {}
+// CHECK: define void @__both()
+
+// if the TARGET is previously declared then whichever aliasing method
+// comes first applies and subsequent aliases are discarded.
+// TODO: warn about this
+
+void __both2(void);
+void both2(void) __attribute((alias("__both2"))); // first, wins
+#pragma weak both2 = __both2
+void __both2(void) {}
+// CHECK: define void @__both2()
+
+void __both3(void);
+#pragma weak both3 = __both3 // first, wins
+void both3(void) __attribute((alias("__both3")));
+void __both3(void) {}
+// CHECK: define void @__both3()
+
+///////////// ensure that #pragma weak does not alter existing __attributes()
+
+void __a1(void) __attribute((noinline));
+#pragma weak a1 = __a1
+void __a1(void) {}
+// CHECK: define void @__a1() {{.*}} noinline
+
+// attributes introduced BEFORE a combination of #pragma weak and alias()
+// hold...
+void __a3(void) __attribute((noinline));
+#pragma weak a3 = __a3
+void a3(void) __attribute((alias("__a3")));
+void __a3(void) {}
+// CHECK: define void @__a3() {{.*}} noinline
+
+#pragma weak xxx = __xxx
+__attribute((pure,noinline,const,fastcall)) void __xxx(void) { }
+// CHECK: void @__xxx() {{.*}} noinline
+
+///////////// PR10878: Make sure we can call a weak alias
+void SHA512Pad(void *context) {}
+#pragma weak SHA384Pad = SHA512Pad
+void PR10878() { SHA384Pad(0); }
+// CHECK: call void @SHA384Pad(i8* null)
+
+
+///////////// TODO: stuff that still doesn't work
+
+// due to the fact that disparate TopLevelDecls cannot affect each other
+// (due to clang's Parser and ASTConsumer behavior, and quite reasonable)
+// #pragma weak must appear before or within the same TopLevelDecl as it
+// references.
+void yyy(void){}
+void zzz(void){}
+#pragma weak yyy
+// NOTE: weak doesn't apply, not before or in same TopLevelDec(!)
+// CHECK: define void @yyy()
+
+int correct_linkage;