[SelectionDAG] Virtualize isTargetStrictFPOpcode / isTargetMemoryOpcode (#119969)
[llvm-project.git] / clang / test / CodeGen / kcfi.c
blob622843cedba50fe7d7c18d16e13cf1818bc1b26e
1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -o - %s | FileCheck %s --check-prefixes=CHECK,C
2 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -x c++ -o - %s | FileCheck %s --check-prefixes=CHECK,MEMBER
3 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fpatchable-function-entry-offset=3 -o - %s | FileCheck %s --check-prefixes=CHECK,OFFSET
4 #if !__has_feature(kcfi)
5 #error Missing kcfi?
6 #endif
8 /// Must emit __kcfi_typeid symbols for address-taken function declarations
9 // CHECK: module asm ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
10 // CHECK: module asm ".set __kcfi_typeid_[[F4]], [[#%d,HASH:]]"
11 /// Must not __kcfi_typeid symbols for non-address-taken declarations
12 // CHECK-NOT: module asm ".weak __kcfi_typeid_{{f6|_Z2f6v}}"
14 // C: @ifunc1 = ifunc i32 (i32), ptr @resolver1
15 // C: @ifunc2 = ifunc i64 (i64), ptr @resolver2
16 typedef int (*fn_t)(void);
18 // CHECK: define dso_local{{.*}} i32 @{{f1|_Z2f1v}}(){{.*}} !kcfi_type ![[#TYPE:]]
19 int f1(void) { return 0; }
21 // CHECK: define dso_local{{.*}} i32 @{{f2|_Z2f2v}}(){{.*}} !kcfi_type ![[#TYPE2:]]
22 unsigned int f2(void) { return 2; }
24 // CHECK-LABEL: define dso_local{{.*}} i32 @{{__call|_Z6__callPFivE}}(ptr{{.*}} %f)
25 int __call(fn_t f) __attribute__((__no_sanitize__("kcfi"))) {
26 // CHECK-NOT: call{{.*}} i32 %{{.}}(){{.*}} [ "kcfi"
27 return f();
30 // CHECK: define dso_local{{.*}} i32 @{{call|_Z4callPFivE}}(ptr{{.*}} %f){{.*}}
31 int call(fn_t f) {
32 // CHECK: call{{.*}} i32 %{{.}}(){{.*}} [ "kcfi"(i32 [[#HASH]]) ]
33 return f();
36 // CHECK-DAG: define internal{{.*}} i32 @{{f3|_ZL2f3v}}(){{.*}} !kcfi_type ![[#TYPE]]
37 static int f3(void) { return 1; }
39 // CHECK-DAG: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @[[F4]]()
40 extern int f4(void);
42 /// Must not emit !kcfi_type for non-address-taken local functions
43 // CHECK: define internal{{.*}} i32 @{{f5|_ZL2f5v}}()
44 // CHECK-NOT: !kcfi_type
45 // CHECK-SAME: {
46 static int f5(void) { return 2; }
48 // CHECK-DAG: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @{{f6|_Z2f6v}}()
49 extern int f6(void);
51 #ifndef __cplusplus
52 // C: define internal ptr @resolver1() #[[#]] !kcfi_type ![[#]] {
53 int ifunc1(int) __attribute__((ifunc("resolver1")));
54 static void *resolver1(void) { return 0; }
56 // C: define internal ptr @resolver2() #[[#]] !kcfi_type ![[#]] {
57 static void *resolver2(void) { return 0; }
58 long ifunc2(long) __attribute__((ifunc("resolver2")));
59 #endif
61 int test(void) {
62 return call(f1) +
63 __call((fn_t)f2) +
64 call(f3) +
65 call(f4) +
66 f5() +
67 f6();
70 #ifdef __cplusplus
71 struct A {
72 // MEMBER-DAG: define{{.*}} void @_ZN1A1fEv(ptr{{.*}} %this){{.*}} !kcfi_type ![[#TYPE3:]]
73 void f() {}
76 void test_member_call(void) {
77 void (A::* p)() = &A::f;
78 // MEMBER-DAG: call void %[[#]](ptr{{.*}} [ "kcfi"(i32 [[#%d,HASH3:]]) ]
79 (A().*p)();
81 #endif
83 // CHECK-DAG: ![[#]] = !{i32 4, !"kcfi", i32 1}
84 // OFFSET-DAG: ![[#]] = !{i32 4, !"kcfi-offset", i32 3}
85 // CHECK-DAG: ![[#TYPE]] = !{i32 [[#HASH]]}
86 // CHECK-DAG: ![[#TYPE2]] = !{i32 [[#%d,HASH2:]]}
87 // MEMBER-DAG: ![[#TYPE3]] = !{i32 [[#HASH3]]}