Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -536,7 +536,6 @@ Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; - Options.TrapFuncName = CodeGenOpts.TrapFuncName; Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -543,14 +543,10 @@ Value *F = CGM.getIntrinsic(Intrinsic::clear_cache); return RValue::get(Builder.CreateCall(F, {Begin, End})); } - case Builtin::BI__builtin_trap: { - Value *F = CGM.getIntrinsic(Intrinsic::trap); - return RValue::get(Builder.CreateCall(F, {})); - } - case Builtin::BI__debugbreak: { - Value *F = CGM.getIntrinsic(Intrinsic::debugtrap); - return RValue::get(Builder.CreateCall(F, {})); - } + case Builtin::BI__builtin_trap: + return RValue::get(EmitTrapCall(Intrinsic::trap)); + case Builtin::BI__debugbreak: + return RValue::get(EmitTrapCall(Intrinsic::debugtrap)); case Builtin::BI__builtin_unreachable: { if (SanOpts.has(SanitizerKind::Unreachable)) { SanitizerScope SanScope(this); Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1453,6 +1453,8 @@ // Attributes that should go on the call site only. if (!CodeGenOpts.SimplifyLibCalls) FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); + if (!CodeGenOpts.TrapFuncName.empty()) + FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); } else { // Attributes that should go on the function, but not the call site. if (!CodeGenOpts.DisableFPElim) { Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -2403,8 +2403,7 @@ TrapBB = createBasicBlock("trap"); Builder.CreateCondBr(Checked, Cont, TrapBB); EmitBlock(TrapBB); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap); - llvm::CallInst *TrapCall = Builder.CreateCall(F, {}); + llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); TrapCall->setDoesNotReturn(); TrapCall->setDoesNotThrow(); Builder.CreateUnreachable(); @@ -2415,6 +2414,18 @@ EmitBlock(Cont); } +llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { + llvm::CallInst *TrapCall = + Builder.CreateCall(CGM.getIntrinsic(IntrID), {}); + + if (!CGM.getCodeGenOpts().TrapFuncName.empty()) + TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, + "trap-func-name", + CGM.getCodeGenOpts().TrapFuncName); + + return TrapCall; +} + /// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an /// array to pointer, return the array subexpression. static const Expr *isSimpleArrayDecayOperand(const Expr *E) { Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2867,6 +2867,10 @@ /// conditional branch to it, for the -ftrapv checks. void EmitTrapCheck(llvm::Value *Checked); + /// \brief Emit a call to trap or debugtrap and attach function attribute + /// "trap-func-name" if specified. + llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID); + /// \brief Create a check for a function parameter that may potentially be /// declared as non-null. void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -930,8 +930,9 @@ EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return), "missing_return", EmitCheckSourceLocation(FD->getLocation()), None); - } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap), {}); + } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) { + EmitTrapCall(llvm::Intrinsic::trap); + } Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); } Index: test/CodeGenCXX/trap-fnattr.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/trap-fnattr.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv -ftrap-function=mytrap %s -o - | FileCheck %s -check-prefix=TRAPFUNC +// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv %s -o - | FileCheck %s -check-prefix=NOOPTION + +// TRAPFUNC-LABEL: define void @_Z12test_builtinv +// TRAPFUNC: call void @llvm.trap() [[ATTR0:#[0-9]+]] + +// NOOPTION-LABEL: define void @_Z12test_builtinv +// NOOPTION: call void @llvm.trap(){{$}} + +void test_builtin(void) { + __builtin_trap(); +} + +// TRAPFUNC-LABEL: define i32 @_Z13test_noreturnv +// TRAPFUNC: call void @llvm.trap() [[ATTR0]] + +// NOOPTION-LABEL: define i32 @_Z13test_noreturnv +// NOOPTION: call void @llvm.trap(){{$}} + +int test_noreturn(void) { +} + +// TRAPFUNC-LABEL: define i32 @_Z17test_add_overflowii +// TRAPFUNC: call void @llvm.trap() [[ATTR1:#[0-9]+]] + +// NOOPTION-LABEL: define i32 @_Z17test_add_overflowii +// NOOPTION: call void @llvm.trap() [[ATTR2:#[0-9]+]] + +int test_add_overflow(int a, int b) { + return a + b; +} + +// TRAPFUNC: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="mytrap" } +// TRAPFUNC: attributes [[ATTR1]] = { {{.*}}"trap-func-name"="mytrap" } + +// NOOPTION-NOT: attributes [[ATTR2]] = { {{.*}}"trap-func-name"="mytrap" }