// RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,TYPE // RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,TYPE // RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,ZERO // RUN: %clang_cc1 %s -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,ZERO // RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -xc++ -o- | FileCheck %s --check-prefixes=CHECK,CHECKCXX,TYPE,TYPECXX // RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -disable-llvm-passes -emit-llvm -xc++ -o- | FileCheck %s --check-prefixes=CHECK,CHECKCXX,TYPE,TYPECXX #ifdef __cplusplus extern "C" { #endif void f(void); void f2(int); void (*fptr)(void); void *opaque; unsigned long uintptr; #ifdef __cplusplus struct ptr_member { void (*fptr_)(int) = 0; }; ptr_member pm; void (*test_member)() = (void (*)())pm.fptr_; // CHECKCXX-LABEL: define{{.*}} internal void @__cxx_global_var_init // TYPECXX: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 2712, i32 0, i64 18983) #endif // CHECK-LABEL: define{{.*}} void @test_cast_to_opaque void test_cast_to_opaque() { opaque = (void *)f; // TYPE: [[RESIGN_VAL:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 0) // TYPE: [[RESIGN_PTR:%.*]] = inttoptr i64 [[RESIGN_VAL]] to ptr // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define{{.*}} void @test_cast_from_opaque void test_cast_from_opaque() { fptr = (void (*)(void))opaque; // TYPE: [[LOAD:%.*]] = load ptr, ptr @opaque // TYPE: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null // TYPE: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label // TYPE: [[RESIGN_LAB]]: // TYPE: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 // TYPE: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 0, i32 0, i64 18983) // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define{{.*}} void @test_cast_to_intptr void test_cast_to_intptr() { uintptr = (unsigned long)fptr; // TYPE: [[ENTRY:.*]]: // TYPE: [[LOAD:%.*]] = load ptr, ptr @fptr // TYPE: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null // TYPE: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label %[[RESIGN_CONT:.*]] // TYPE: [[RESIGN_LAB]]: // TYPE: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 // TYPE: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 18983, i32 0, i64 0) // TYPE: [[RESIGN:%.*]] = inttoptr i64 [[RESIGN_INT]] to ptr // TYPE: br label %[[RESIGN_CONT]] // TYPE: [[RESIGN_CONT]]: // TYPE: phi ptr [ null, %[[ENTRY]] ], [ [[RESIGN]], %[[RESIGN_LAB]] ] // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define{{.*}} void @test_function_to_function_cast void test_function_to_function_cast() { void (*fptr2)(int) = (void (*)(int))fptr; // TYPE: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 2712) // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define{{.*}} void @test_call_lvalue_cast void test_call_lvalue_cast() { (*(void (*)(int))f)(42); // TYPE: entry: // TYPE-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 2712) // TYPE-NEXT: [[RESIGN_INT:%.*]] = inttoptr i64 [[RESIGN]] to ptr // TYPE-NEXT: call void [[RESIGN_INT]](i32 noundef 42) [ "ptrauth"(i32 0, i64 2712) ] // ZERO-NOT: @llvm.ptrauth.resign // ZERO: call void ptrauth (ptr @f, i32 0)(i32 noundef 42) [ "ptrauth"(i32 0, i64 0) ] } #ifdef __cplusplus } #endif