// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // RUN: %clang_cc1 -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=TRAP %s // RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ABORT %s // RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-recover=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=RECOVER %s // RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-minimal-runtime -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ABORT_MIN %s // RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-recover=cfi-vcall -fsanitize-minimal-runtime -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=RECOVER_MIN %s struct S1 { virtual void f(); }; // TRAP-LABEL: define hidden void @_Z3s1fP2S1( // TRAP-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] { // TRAP-NEXT: [[ENTRY:.*:]] // TRAP-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8 // TRAP-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8 // TRAP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8 // TRAP-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 // TRAP-NEXT: [[TMP1:%.*]] = call { ptr, i1 } @llvm.type.checked.load(ptr [[VTABLE]], i32 0, metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]] // TRAP-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i1 } [[TMP1]], 1, !nosanitize [[META5]] // TRAP-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]] // TRAP: [[TRAP]]: // TRAP-NEXT: call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !nosanitize [[META5]] // TRAP-NEXT: unreachable, !nosanitize [[META5]] // TRAP: [[CONT]]: // TRAP-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i1 } [[TMP1]], 0, !nosanitize [[META5]] // TRAP-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) // TRAP-NEXT: ret void // // ABORT-LABEL: define hidden void @_Z3s1fP2S1( // ABORT-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] { // ABORT-NEXT: [[ENTRY:.*:]] // ABORT-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8 // ABORT-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8 // ABORT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8 // ABORT-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 // ABORT-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]] // ABORT-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]] // ABORT-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]] // ABORT: [[HANDLER_CFI_CHECK_FAIL]]: // ABORT-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64, !nosanitize [[META5]] // ABORT-NEXT: [[TMP4:%.*]] = zext i1 [[TMP2]] to i64, !nosanitize [[META5]] // ABORT-NEXT: call void @__ubsan_handle_cfi_check_fail_abort(ptr @anon.00e38160576ab76122d2f8d139d2e390.1, i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR3:[0-9]+]], !nosanitize [[META5]] // ABORT-NEXT: unreachable, !nosanitize [[META5]] // ABORT: [[CONT]]: // ABORT-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 // ABORT-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VFN]], align 8 // ABORT-NEXT: call void [[TMP5]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) // ABORT-NEXT: ret void // // RECOVER-LABEL: define hidden void @_Z3s1fP2S1( // RECOVER-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] { // RECOVER-NEXT: [[ENTRY:.*:]] // RECOVER-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8 // RECOVER-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8 // RECOVER-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8 // RECOVER-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 // RECOVER-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]] // RECOVER-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]] // RECOVER-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]] // RECOVER: [[HANDLER_CFI_CHECK_FAIL]]: // RECOVER-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64, !nosanitize [[META5]] // RECOVER-NEXT: [[TMP4:%.*]] = zext i1 [[TMP2]] to i64, !nosanitize [[META5]] // RECOVER-NEXT: call void @__ubsan_handle_cfi_check_fail(ptr @anon.00e38160576ab76122d2f8d139d2e390.1, i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR3:[0-9]+]], !nosanitize [[META5]] // RECOVER-NEXT: br label %[[CONT]], !nosanitize [[META5]] // RECOVER: [[CONT]]: // RECOVER-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 // RECOVER-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VFN]], align 8 // RECOVER-NEXT: call void [[TMP5]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) // RECOVER-NEXT: ret void // // ABORT_MIN-LABEL: define hidden void @_Z3s1fP2S1( // ABORT_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] { // ABORT_MIN-NEXT: [[ENTRY:.*:]] // ABORT_MIN-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8 // ABORT_MIN-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8 // ABORT_MIN-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8 // ABORT_MIN-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 // ABORT_MIN-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]] // ABORT_MIN-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]] // ABORT_MIN-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]] // ABORT_MIN: [[HANDLER_CFI_CHECK_FAIL]]: // ABORT_MIN-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal_abort() #[[ATTR3:[0-9]+]], !nosanitize [[META5]] // ABORT_MIN-NEXT: unreachable, !nosanitize [[META5]] // ABORT_MIN: [[CONT]]: // ABORT_MIN-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 // ABORT_MIN-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VFN]], align 8 // ABORT_MIN-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) // ABORT_MIN-NEXT: ret void // // RECOVER_MIN-LABEL: define hidden void @_Z3s1fP2S1( // RECOVER_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] { // RECOVER_MIN-NEXT: [[ENTRY:.*:]] // RECOVER_MIN-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8 // RECOVER_MIN-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8 // RECOVER_MIN-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8 // RECOVER_MIN-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 // RECOVER_MIN-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]] // RECOVER_MIN-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]] // RECOVER_MIN-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]] // RECOVER_MIN: [[HANDLER_CFI_CHECK_FAIL]]: // RECOVER_MIN-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal() #[[ATTR3:[0-9]+]], !nosanitize [[META5]] // RECOVER_MIN-NEXT: br label %[[CONT]], !nosanitize [[META5]] // RECOVER_MIN: [[CONT]]: // RECOVER_MIN-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 // RECOVER_MIN-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VFN]], align 8 // RECOVER_MIN-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) // RECOVER_MIN-NEXT: ret void // void s1f(S1 *s1) { s1->f(); } //. // TRAP: [[META5]] = !{} // TRAP: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1} //. // ABORT: [[META5]] = !{} // ABORT: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1} //. // RECOVER: [[META5]] = !{} // RECOVER: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1} //. // ABORT_MIN: [[META5]] = !{} // ABORT_MIN: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1} //. // RECOVER_MIN: [[META5]] = !{} // RECOVER_MIN: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1} //.