forked from OSchip/llvm-project
206 lines
6.5 KiB
C
206 lines
6.5 KiB
C
// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-pc-linux-gnu -emit-llvm %s -o - -verify | FileCheck %s
|
|
|
|
// CHECK: @weakvar = weak{{.*}} global
|
|
// CHECK: @__weakvar_alias ={{.*}} global
|
|
// CHECK: @correct_linkage = weak{{.*}} global
|
|
|
|
|
|
// CHECK-DAG: @both ={{.*}} alias void (), void ()* @__both
|
|
// CHECK-DAG: @both2 ={{.*}} alias void (), void ()* @__both2
|
|
// CHECK-DAG: @weakvar_alias = weak{{.*}} alias i32, i32* @__weakvar_alias
|
|
// CHECK-DAG: @foo = weak{{.*}} alias void (), void ()* @__foo
|
|
// CHECK-DAG: @foo2 = weak{{.*}} alias void (), void ()* @__foo2
|
|
// CHECK-DAG: @stutter = weak{{.*}} alias void (), void ()* @__stutter
|
|
// CHECK-DAG: @stutter2 = weak{{.*}} alias void (), void ()* @__stutter2
|
|
// CHECK-DAG: @declfirst = weak{{.*}} alias void (), void ()* @__declfirst
|
|
// CHECK-DAG: @declfirstattr = weak{{.*}} alias void (), void ()* @__declfirstattr
|
|
// CHECK-DAG: @mix2 = weak{{.*}} alias void (), void ()* @__mix2
|
|
// CHECK-DAG: @a1 = weak{{.*}} alias void (), void ()* @__a1
|
|
// CHECK-DAG: @xxx = weak{{.*}} alias void (), void ()* @__xxx
|
|
// CHECK-DAG: @undecfunc_alias1 = weak{{.*}} alias void (), void ()* @undecfunc
|
|
// CHECK-DAG: @undecfunc_alias2 = weak{{.*}} alias void (), void ()* @undecfunc
|
|
// CHECK-DAG: @undecfunc_alias3 = weak{{.*}} alias void (), void ()* @undecfunc
|
|
// CHECK-DAG: @undecfunc_alias4 = weak{{.*}} alias void (), void ()* @undecfunc
|
|
|
|
|
|
|
|
// CHECK-LABEL: 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-LABEL: define{{.*}} void @__foo()
|
|
|
|
|
|
void __foo2(void) {}
|
|
#pragma weak foo2 = __foo2
|
|
// CHECK-LABEL: 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' attribute only applies to variables and functions}}
|
|
typedef int td;
|
|
|
|
#pragma weak td2 = __td2 // expected-warning {{'weak' attribute only applies to variables and functions}}
|
|
typedef int __td2;
|
|
|
|
typedef int __td3;
|
|
#pragma weak td3 = __td3 // expected-warning {{'weak' attribute only applies to variables and functions}}
|
|
|
|
///// test weird cases
|
|
|
|
// test repeats
|
|
|
|
#pragma weak stutter = __stutter
|
|
#pragma weak stutter = __stutter
|
|
void __stutter(void) {}
|
|
// CHECK-LABEL: define{{.*}} void @__stutter()
|
|
|
|
void __stutter2(void) {}
|
|
#pragma weak stutter2 = __stutter2
|
|
#pragma weak stutter2 = __stutter2
|
|
// CHECK-LABEL: define{{.*}} void @__stutter2()
|
|
|
|
|
|
// test decl/pragma weak order
|
|
|
|
void __declfirst(void);
|
|
#pragma weak declfirst = __declfirst
|
|
void __declfirst(void) {}
|
|
// CHECK-LABEL: define{{.*}} void @__declfirst()
|
|
|
|
void __declfirstattr(void) __attribute((noinline));
|
|
#pragma weak declfirstattr = __declfirstattr
|
|
void __declfirstattr(void) {}
|
|
// CHECK-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: define{{.*}} void @__both2()
|
|
|
|
///////////// 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() [[NI:#[0-9]+]]
|
|
|
|
#pragma weak xxx = __xxx
|
|
__attribute((pure,noinline,const)) void __xxx(void) { }
|
|
// CHECK: void @__xxx() [[RN:#[0-9]+]]
|
|
|
|
///////////// PR28611: Try multiple aliases of same undeclared symbol or alias
|
|
#pragma weak undecfunc_alias1 = undecfunc
|
|
#pragma weak undecfunc_alias1 = undecfunc // Try specifying same alias/target pair a second time.
|
|
#pragma weak undecfunc_alias3 = undecfunc_alias2 // expected-warning {{alias will always resolve to undecfunc}}
|
|
#pragma weak undecfunc_alias4 = undecfunc_alias2 // expected-warning {{alias will always resolve to undecfunc}}
|
|
#pragma weak undecfunc_alias2 = undecfunc
|
|
void undecfunc_alias2(void);
|
|
void undecfunc(void) { }
|
|
|
|
///////////// PR10878: Make sure we can call a weak alias
|
|
void SHA512Pad(void *context) {}
|
|
#pragma weak SHA384Pad = SHA512Pad
|
|
void PR10878(void) { SHA384Pad(0); }
|
|
// CHECK: call void @SHA384Pad(i8* noundef null)
|
|
|
|
|
|
// PR14046: Parse #pragma weak in function-local context
|
|
extern int PR14046e(void);
|
|
void PR14046f(void) {
|
|
#pragma weak PR14046e
|
|
PR14046e();
|
|
}
|
|
// CHECK: declare extern_weak i32 @PR14046e()
|
|
|
|
// Parse #pragma weak after a label or case statement
|
|
extern int PR16705a(void);
|
|
extern int PR16705b(void);
|
|
extern int PR16705c(void);
|
|
void PR16705f(int a) {
|
|
switch(a) {
|
|
case 1:
|
|
#pragma weak PR16705a
|
|
PR16705a();
|
|
default:
|
|
#pragma weak PR16705b
|
|
PR16705b();
|
|
}
|
|
label:
|
|
#pragma weak PR16705c
|
|
PR16705c();
|
|
}
|
|
|
|
// CHECK: declare extern_weak i32 @PR16705a()
|
|
// CHECK: declare extern_weak i32 @PR16705b()
|
|
// CHECK: declare extern_weak i32 @PR16705c()
|
|
|
|
|
|
///////////// 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-LABEL: define{{.*}} void @yyy()
|
|
|
|
int correct_linkage;
|
|
|
|
// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} }
|
|
// CHECK: attributes [[RN]] = { noinline nounwind optnone readnone{{.*}} }
|