// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5 // // N.B. although the clang driver defaults to merge, clang_cc1 defaults to non-merge. // (This is similar to -fsanitize-recover, for which the default is also applied // at the driver level only.) // If optimization is disabled, merging is disabled (overrides -fsanitize-merge). // RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux -fsanitize-cfi-cross-dso \ // RUN: -fsanitize=cfi-icall,cfi-nvcall,cfi-vcall,cfi-unrelated-cast,cfi-derived-cast \ // RUN: -fsanitize-trap=cfi-icall,cfi-nvcall \ // RUN: -fsanitize-merge=cfi-icall,cfi-nvcall \ // RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=MERGE // RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux -fsanitize-cfi-cross-dso \ // RUN: -fsanitize=cfi-icall,cfi-nvcall,cfi-vcall,cfi-unrelated-cast,cfi-derived-cast \ // RUN: -fsanitize-trap=cfi-icall,cfi-nvcall \ // RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=NO-MERGE // NOMERGE-LABEL: define dso_local void @caller( // NOMERGE-SAME: ptr noundef [[F:%.*]]) #[[ATTR0:[0-9]+]] !type [[META4:![0-9]+]] !type [[META5:![0-9]+]] !type [[META6:![0-9]+]] { // NOMERGE-NEXT: [[ENTRY:.*:]] // NOMERGE-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 8 // NOMERGE-NEXT: store ptr [[F]], ptr [[F_ADDR]], align 8 // NOMERGE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 8 // NOMERGE-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[TMP0]], metadata !"_ZTSFvvE"), !nosanitize [[META7:![0-9]+]] // NOMERGE-NEXT: br i1 [[TMP1]], label %[[CFI_CONT:.*]], label %[[CFI_SLOWPATH:.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META7]] // NOMERGE: [[CFI_SLOWPATH]]: // NOMERGE-NEXT: call void @__cfi_slowpath(i64 9080559750644022485, ptr [[TMP0]]) #[[ATTR7:[0-9]+]], !nosanitize [[META7]] // NOMERGE-NEXT: br label %[[CFI_CONT]], !nosanitize [[META7]] // NOMERGE: [[CFI_CONT]]: // NOMERGE-NEXT: call void [[TMP0]]() // NOMERGE-NEXT: ret void void caller(void (*f)(void)) { f(); } // MERGE-LABEL: define dso_local void @caller( // MERGE-SAME: ptr noundef [[F:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !type [[META4:![0-9]+]] !type [[META5:![0-9]+]] !type [[META6:![0-9]+]] { // MERGE-NEXT: [[ENTRY:.*:]] // MERGE-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[F]], metadata !"_ZTSFvvE"), !nosanitize [[META7:![0-9]+]] // MERGE-NEXT: br i1 [[TMP0]], label %[[CFI_CONT:.*]], label %[[CFI_SLOWPATH:.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META7]] // MERGE: [[CFI_SLOWPATH]]: // MERGE-NEXT: tail call void @__cfi_slowpath(i64 9080559750644022485, ptr [[F]]) #[[ATTR5:[0-9]+]], !nosanitize [[META7]] // MERGE-NEXT: br label %[[CFI_CONT]], !nosanitize [[META7]] // MERGE: [[CFI_CONT]]: // MERGE-NEXT: tail call void [[F]]() #[[ATTR5]] // MERGE-NEXT: ret void // // // MERGE-LABEL: define weak_odr hidden void @__cfi_check_fail( // MERGE-SAME: ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR0]] { // MERGE-NEXT: [[ENTRY:.*:]] // MERGE-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[TMP0]], null, !nosanitize [[META7]] // MERGE-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF9:![0-9]+]], !nosanitize [[META7]] // MERGE: [[TRAP]]: // MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR6:[0-9]+]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[CONT]]: // MERGE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP0]], align 4, !nosanitize [[META7]] // MERGE-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.type.test(ptr [[TMP1]], metadata !"all-vtables"), !nosanitize [[META7]] // MERGE-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i64, !nosanitize [[META7]] // MERGE-NEXT: switch i8 [[TMP2]], label %[[CONT8:.*]] [ // MERGE-NEXT: i8 0, label %[[HANDLER_CFI_CHECK_FAIL:.*]] // MERGE-NEXT: i8 1, label %[[TRAP]] // MERGE-NEXT: i8 2, label %[[HANDLER_CFI_CHECK_FAIL4:.*]] // MERGE-NEXT: i8 3, label %[[HANDLER_CFI_CHECK_FAIL6:.*]] // MERGE-NEXT: i8 4, label %[[TRAP]] // MERGE-NEXT: ], !prof [[PROF10:![0-9]+]] // MERGE: [[HANDLER_CFI_CHECK_FAIL]]: // MERGE-NEXT: [[TMP5:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP5]], i64 [[TMP6]], i64 [[TMP4]]) #[[ATTR7:[0-9]+]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[HANDLER_CFI_CHECK_FAIL4]]: // MERGE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP7]], i64 [[TMP8]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[HANDLER_CFI_CHECK_FAIL6]]: // MERGE-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP9]], i64 [[TMP10]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[CONT8]]: // MERGE-NEXT: ret void, !nosanitize [[META7]] // // // MERGE-LABEL: define weak void @__cfi_check( // MERGE-SAME: i64 noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] align 4096 { // MERGE-NEXT: [[ENTRY:.*:]] // MERGE-NEXT: [[DOTNOT_I:%.*]] = icmp eq ptr [[TMP2]], null, !nosanitize [[META7]] // MERGE-NEXT: br i1 [[DOTNOT_I]], label %[[TRAP_I:.*]], label %[[CONT_I:.*]], !prof [[PROF9]], !nosanitize [[META7]] // MERGE: [[TRAP_I]]: // MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR6]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[CONT_I]]: // MERGE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 4, !nosanitize [[META7]] // MERGE-NEXT: [[TMP4:%.*]] = tail call i1 @llvm.type.test(ptr [[TMP1]], metadata !"all-vtables"), !nosanitize [[META7]] // MERGE-NEXT: [[TMP5:%.*]] = zext i1 [[TMP4]] to i64, !nosanitize [[META7]] // MERGE-NEXT: switch i8 [[TMP3]], label %[[__CFI_CHECK_FAIL_EXIT:.*]] [ // MERGE-NEXT: i8 0, label %[[HANDLER_CFI_CHECK_FAIL_I:.*]] // MERGE-NEXT: i8 1, label %[[TRAP_I]] // MERGE-NEXT: i8 2, label %[[HANDLER_CFI_CHECK_FAIL4_I:.*]] // MERGE-NEXT: i8 3, label %[[HANDLER_CFI_CHECK_FAIL6_I:.*]] // MERGE-NEXT: i8 4, label %[[TRAP_I]] // MERGE-NEXT: ], !prof [[PROF10]] // MERGE: [[HANDLER_CFI_CHECK_FAIL_I]]: // MERGE-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP6]], i64 [[TMP7]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[HANDLER_CFI_CHECK_FAIL4_I]]: // MERGE-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP8]], i64 [[TMP9]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[HANDLER_CFI_CHECK_FAIL6_I]]: // MERGE-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // MERGE-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP10]], i64 [[TMP11]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // MERGE-NEXT: unreachable, !nosanitize [[META7]] // MERGE: [[__CFI_CHECK_FAIL_EXIT]]: // MERGE-NEXT: ret void // // // NO-MERGE-LABEL: define dso_local void @caller( // NO-MERGE-SAME: ptr noundef [[F:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !type [[META4:![0-9]+]] !type [[META5:![0-9]+]] !type [[META6:![0-9]+]] { // NO-MERGE-NEXT: [[ENTRY:.*:]] // NO-MERGE-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[F]], metadata !"_ZTSFvvE"), !nosanitize [[META7:![0-9]+]] // NO-MERGE-NEXT: br i1 [[TMP0]], label %[[CFI_CONT:.*]], label %[[CFI_SLOWPATH:.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META7]] // NO-MERGE: [[CFI_SLOWPATH]]: // NO-MERGE-NEXT: tail call void @__cfi_slowpath(i64 9080559750644022485, ptr [[F]]) #[[ATTR5:[0-9]+]], !nosanitize [[META7]] // NO-MERGE-NEXT: br label %[[CFI_CONT]], !nosanitize [[META7]] // NO-MERGE: [[CFI_CONT]]: // NO-MERGE-NEXT: tail call void [[F]]() #[[ATTR5]] // NO-MERGE-NEXT: ret void // // // NO-MERGE-LABEL: define weak_odr hidden void @__cfi_check_fail( // NO-MERGE-SAME: ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR0]] { // NO-MERGE-NEXT: [[ENTRY:.*:]] // NO-MERGE-NEXT: [[DOTNOT:%.*]] = icmp eq ptr [[TMP0]], null, !nosanitize [[META7]] // NO-MERGE-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF9:![0-9]+]], !nosanitize [[META7]] // NO-MERGE: [[TRAP]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR6:[0-9]+]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[CONT]]: // NO-MERGE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP0]], align 4, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.type.test(ptr [[TMP1]], metadata !"all-vtables"), !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: switch i8 [[TMP2]], label %[[CONT10:.*]] [ // NO-MERGE-NEXT: i8 0, label %[[HANDLER_CFI_CHECK_FAIL:.*]] // NO-MERGE-NEXT: i8 1, label %[[TRAP3:.*]] // NO-MERGE-NEXT: i8 2, label %[[HANDLER_CFI_CHECK_FAIL5:.*]] // NO-MERGE-NEXT: i8 3, label %[[HANDLER_CFI_CHECK_FAIL7:.*]] // NO-MERGE-NEXT: i8 4, label %[[TRAP9:.*]] // NO-MERGE-NEXT: ], !prof [[PROF10:![0-9]+]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL]]: // NO-MERGE-NEXT: [[TMP5:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP5]], i64 [[TMP6]], i64 [[TMP4]]) #[[ATTR7:[0-9]+]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[TRAP3]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL5]]: // NO-MERGE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP7]], i64 [[TMP8]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL7]]: // NO-MERGE-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP9]], i64 [[TMP10]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[TRAP9]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[CONT10]]: // NO-MERGE-NEXT: ret void, !nosanitize [[META7]] // // // NO-MERGE-LABEL: define weak void @__cfi_check( // NO-MERGE-SAME: i64 noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] align 4096 { // NO-MERGE-NEXT: [[ENTRY:.*:]] // NO-MERGE-NEXT: [[DOTNOT_I:%.*]] = icmp eq ptr [[TMP2]], null, !nosanitize [[META7]] // NO-MERGE-NEXT: br i1 [[DOTNOT_I]], label %[[TRAP_I:.*]], label %[[CONT_I:.*]], !prof [[PROF9]], !nosanitize [[META7]] // NO-MERGE: [[TRAP_I]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR6]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[CONT_I]]: // NO-MERGE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 4, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP4:%.*]] = tail call i1 @llvm.type.test(ptr [[TMP1]], metadata !"all-vtables"), !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP5:%.*]] = zext i1 [[TMP4]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: switch i8 [[TMP3]], label %[[__CFI_CHECK_FAIL_EXIT:.*]] [ // NO-MERGE-NEXT: i8 0, label %[[HANDLER_CFI_CHECK_FAIL_I:.*]] // NO-MERGE-NEXT: i8 1, label %[[TRAP3_I:.*]] // NO-MERGE-NEXT: i8 2, label %[[HANDLER_CFI_CHECK_FAIL5_I:.*]] // NO-MERGE-NEXT: i8 3, label %[[HANDLER_CFI_CHECK_FAIL7_I:.*]] // NO-MERGE-NEXT: i8 4, label %[[TRAP9_I:.*]] // NO-MERGE-NEXT: ], !prof [[PROF10]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL_I]]: // NO-MERGE-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP6]], i64 [[TMP7]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[TRAP3_I]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL5_I]]: // NO-MERGE-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP8]], i64 [[TMP9]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[HANDLER_CFI_CHECK_FAIL7_I]]: // NO-MERGE-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP2]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP1]] to i64, !nosanitize [[META7]] // NO-MERGE-NEXT: tail call void @__ubsan_handle_cfi_check_fail_abort(i64 [[TMP10]], i64 [[TMP11]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[TRAP9_I]]: // NO-MERGE-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR7]], !nosanitize [[META7]] // NO-MERGE-NEXT: unreachable, !nosanitize [[META7]] // NO-MERGE: [[__CFI_CHECK_FAIL_EXIT]]: // NO-MERGE-NEXT: ret void // MERGE: [[ATTR5]] = { nounwind } // MERGE: [[ATTR6]] = { noreturn nounwind } // NO-MERGE: [[ATTR6]] = { noreturn nounwind } // NO-MERGE: [[ATTR7]] = { nomerge noreturn nounwind }