1 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \
2 // RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC %s
3 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \
4 // RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefix=CHECK %s
5 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast
6 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \
7 // RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC %s
9 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
10 // RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC %s
11 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
12 // RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefix=CHECK %s
13 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast
14 // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
15 // RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC %s
25 unsigned long uintptr
;
27 // CHECK: @test_constant_null = global ptr null
28 void (*test_constant_null
)(int) = 0;
30 // CHECK: @test_constant_cast = global ptr ptrauth (ptr @f, i32 0, i64 2712)
31 void (*test_constant_cast
)(int) = (void (*)(int))f
;
34 // CHECKC: @enum_func_ptr = global ptr ptrauth (ptr @enum_func, i32 0, i64 2712)
36 void enum_func(enum Enum0
);
37 void (*enum_func_ptr
)(enum Enum0
) = enum_func
;
40 // CHECK: @test_opaque = global ptr ptrauth (ptr @f, i32 0)
45 (void (*)(int))(double (*)(double))f
;
47 // CHECK: @test_intptr_t = global i64 ptrtoint (ptr ptrauth (ptr @f, i32 0) to i64)
48 unsigned long test_intptr_t
= (unsigned long)f
;
50 // CHECK: @test_through_long = global ptr ptrauth (ptr @f, i32 0, i64 2712)
51 void (*test_through_long
)(int) = (void (*)(int))(long)f
;
53 // CHECK: @test_to_long = global i64 ptrtoint (ptr ptrauth (ptr @f, i32 0) to i64)
54 long test_to_long
= (long)(double (*)())f
;
56 extern void external_function(void);
57 // CHECK: @fptr1 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983)
58 void (*fptr1
)(void) = external_function
;
59 // CHECK: @fptr2 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983)
60 void (*fptr2
)(void) = &external_function
;
62 // CHECK: @fptr3 = global ptr ptrauth (ptr @external_function, i32 2, i64 26)
63 void (*fptr3
)(void) = __builtin_ptrauth_sign_constant(&external_function
, 2, 26);
65 // CHECK: @fptr4 = global ptr ptrauth (ptr @external_function, i32 2, i64 26, ptr @fptr4)
66 void (*fptr4
)(void) = __builtin_ptrauth_sign_constant(&external_function
, 2, __builtin_ptrauth_blend_discriminator(&fptr4
, 26));
68 // CHECK-LABEL: define{{.*}} void @test_call()
70 // CHECK: [[T0:%.*]] = load ptr, ptr @fnptr,
71 // CHECK-NEXT: call void [[T0]]() [ "ptrauth"(i32 0, i64 18983) ]
75 // CHECK-LABEL: define{{.*}} ptr @test_function_pointer()
76 // CHECK: ret ptr ptrauth (ptr @external_function, i32 0, i64 18983)
77 void (*test_function_pointer())(void) {
78 return external_function
;
81 struct InitiallyIncomplete
;
82 extern struct InitiallyIncomplete
returns_initially_incomplete(void);
83 // CHECK-LABEL: define{{.*}} void @use_while_incomplete()
84 void use_while_incomplete() {
85 // CHECK: [[VAR:%.*]] = alloca ptr,
86 // CHECK-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]]
87 struct InitiallyIncomplete (*fnptr
)(void) = &returns_initially_incomplete
;
89 struct InitiallyIncomplete
{ int x
; };
90 // CHECK-LABEL: define{{.*}} void @use_while_complete()
91 void use_while_complete() {
92 // CHECK: [[VAR:%.*]] = alloca ptr,
93 // CHECK-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]]
94 // CHECK-NEXT: ret void
95 struct InitiallyIncomplete (*fnptr
)(void) = &returns_initially_incomplete
;
104 // CHECKC-LABEL: define{{.*}} void @test_knr
109 // CHECKC: [[P:%.*]] = alloca ptr
110 // CHECKC: store ptr ptrauth (ptr @knr, i32 0, i64 18983), ptr [[P]]
111 // CHECKC: [[LOAD:%.*]] = load ptr, ptr [[P]]
112 // CHECKC: call void [[LOAD]](i32 noundef 0) [ "ptrauth"(i32 0, i64 18983) ]
115 // CHECKC-LABEL: define{{.*}} void @test_redeclaration
116 void test_redeclaration() {
118 void (*ptr
)() = redecl
;
120 void (*ptr2
)(int) = redecl
;
124 // CHECKC: store ptr ptrauth (ptr @redecl, i32 0, i64 18983), ptr %ptr
125 // CHECKC: store ptr ptrauth (ptr @redecl, i32 0, i64 2712), ptr %ptr2
126 // CHECKC: call void {{.*}}() [ "ptrauth"(i32 0, i64 18983) ]
127 // CHECKC: call void {{.*}}(i32 noundef 0) [ "ptrauth"(i32 0, i64 2712) ]
134 // CHECKC-LABEL: define{{.*}} void @test_redecl_knr
135 void test_redecl_knr() {
139 // CHECKC: store ptr ptrauth (ptr @knr2, i32 0, i64 18983)
140 // CHECKC: call void {{.*}}() [ "ptrauth"(i32 0, i64 18983) ]
144 void (*p2
)(int) = knr2
;
147 // CHECKC: store ptr ptrauth (ptr @knr2, i32 0, i64 2712)
148 // CHECKC: call void {{.*}}(i32 noundef 0) [ "ptrauth"(i32 0, i64 2712) ]