diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp index 9cc9af88c5e4..b79911bcf3c4 100644 --- a/llvm/lib/CodeGen/StackProtector.cpp +++ b/llvm/lib/CodeGen/StackProtector.cpp @@ -731,8 +731,8 @@ BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) { } if (StackChkFail) { - cast(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn); - B.CreateCall(StackChkFail, Args); + CallInst *Call = B.CreateCall(StackChkFail, Args); + Call->addFnAttr(Attribute::NoReturn); } B.CreateUnreachable(); diff --git a/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll b/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll new file mode 100644 index 000000000000..9a102768b127 --- /dev/null +++ b/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll @@ -0,0 +1,34 @@ +;; This is a minimal reproducer that caused StackProtector to crash with a bad cast when +;; CrossDSOCFI is used. This test just needs to not crash. +; REQUIRES: x86-registered-target +; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes=lowertypetests,cross-dso-cfi,stack-protector + +define hidden void @__stack_chk_fail() !type !1{ + unreachable +} + +define void @store_captures() sspstrong { +entry: + %a = alloca i32, align 4 + %j = alloca ptr, align 8 + store ptr %a, ptr %j, align 8 + ret void +} + +define void @func(ptr %0) { +entry: + %1 = call i1 @llvm.type.test(ptr %0, metadata !"typeid") + br i1 %1, label %cont, label %trap + +trap: ; preds = %entry + call void @llvm.trap() + unreachable + +cont: ; preds = %entry + call void %0() + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 4, !"Cross-DSO CFI", i32 1} +!1 = !{i64 0, !"typeid"} diff --git a/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll b/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll new file mode 100644 index 000000000000..def3e014797d --- /dev/null +++ b/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll @@ -0,0 +1,22 @@ +;; __stack_chk_fail should have the noreturn attr even if it is an alias +; REQUIRES: x86-registered-target +; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes=stack-protector -S | FileCheck %s + +define hidden void @__stack_chk_fail_impl() { + unreachable +} + +@__stack_chk_fail = hidden alias void (), ptr @__stack_chk_fail_impl + +; CHECK-LABEL: @store_captures( +; CHECK: CallStackCheckFailBlk: +; CHECK-NEXT: call void @__stack_chk_fail() [[ATTRS:#.*]] +define void @store_captures() sspstrong { +entry: + %a = alloca i32, align 4 + %j = alloca ptr, align 8 + store ptr %a, ptr %j, align 8 + ret void +} + +; CHECK: attributes [[ATTRS]] = { noreturn }