Index: docs/UndefinedBehaviorSanitizer.rst =================================================================== --- docs/UndefinedBehaviorSanitizer.rst +++ docs/UndefinedBehaviorSanitizer.rst @@ -124,8 +124,8 @@ - ``-fsanitize=signed-integer-overflow``: Signed integer overflow, including all the checks added by ``-ftrapv``, and checking for overflow in signed division (``INT_MIN / -1``). - - ``-fsanitize=unreachable``: If control flow reaches - ``__builtin_unreachable``. + - ``-fsanitize=unreachable``: If control flow reaches an unreachable + program point. - ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflows. Note that unlike signed integer overflow, unsigned integer is not undefined behavior. However, while it has well-defined semantics, Index: lib/CodeGen/CGAtomic.cpp =================================================================== --- lib/CodeGen/CGAtomic.cpp +++ lib/CodeGen/CGAtomic.cpp @@ -300,16 +300,15 @@ return TempAlloca; } -static RValue emitAtomicLibcall(CodeGenFunction &CGF, - StringRef fnName, - QualType resultType, - CallArgList &args) { +static RValue emitAtomicLibcall(CodeGenFunction &CGF, StringRef fnName, + QualType resultType, CallArgList &args) { const CGFunctionInfo &fnInfo = CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args); llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo); llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName); auto callee = CGCallee::forDirect(fn); - return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args); + return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args, + SourceLocation()); } /// Does a store of the given IR type modify the full expected width? Index: lib/CodeGen/CGBlocks.cpp =================================================================== --- lib/CodeGen/CGBlocks.cpp +++ lib/CodeGen/CGBlocks.cpp @@ -1162,7 +1162,7 @@ CGCallee Callee(CGCalleeInfo(), Func); // And call the block. - return EmitCall(FnInfo, Callee, ReturnValue, Args); + return EmitCall(FnInfo, Callee, ReturnValue, Args, E->getExprLoc()); } Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -823,7 +823,7 @@ CGM.getTypes().arrangeBuiltinFunctionCall(Ctx.VoidTy, Args); llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); - EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); + EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args, E.getExprLoc()); // Push a clang.arc.use cleanup for each object in RetainableOperands. The // cleanup will cause the use to appear after the final log call, keeping @@ -1218,14 +1218,7 @@ case Builtin::BI__debugbreak: return RValue::get(EmitTrapCall(Intrinsic::debugtrap)); case Builtin::BI__builtin_unreachable: { - if (SanOpts.has(SanitizerKind::Unreachable)) { - SanitizerScope SanScope(this); - EmitCheck(std::make_pair(static_cast(Builder.getFalse()), - SanitizerKind::Unreachable), - SanitizerHandler::BuiltinUnreachable, - EmitCheckSourceLocation(E->getExprLoc()), None); - } else - Builder.CreateUnreachable(); + EmitUnreachable(E->getExprLoc()); // We do need to preserve an insertion point. EmitBlock(createBasicBlock("unreachable.cont")); @@ -1858,8 +1851,8 @@ CGM.getTypes().arrangeBuiltinFunctionCall(E->getType(), Args); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo); llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName); - return EmitCall(FuncInfo, CGCallee::forDirect(Func), - ReturnValueSlot(), Args); + return EmitCall(FuncInfo, CGCallee::forDirect(Func), ReturnValueSlot(), + Args, SourceLocation()); } case Builtin::BI__atomic_test_and_set: { Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -2753,6 +2753,12 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc) { + if (FI.isNoReturn()) { + // Noreturn functions don't return. + EmitUnreachable(EndLoc); + return; + } + if (CurCodeDecl && CurCodeDecl->hasAttr()) { // Naked functions don't have epilogues. Builder.CreateUnreachable(); @@ -3713,6 +3719,7 @@ const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &CallArgs, + SourceLocation Loc, llvm::Instruction **callOrInvoke) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. @@ -4236,7 +4243,15 @@ EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize), SRetPtr.getPointer()); - Builder.CreateUnreachable(); + // Strip away the noreturn attribute to better diagnose unreachable UB. + if (SanOpts.has(SanitizerKind::Unreachable)) { + if (auto *F = CS.getCalledFunction()) + F->removeFnAttr(llvm::Attribute::NoReturn); + CS.removeAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoReturn); + } + + EmitUnreachable(Loc); Builder.ClearInsertionPoint(); // FIXME: For now, emit a dummy basic block because expr emitters in Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -2099,7 +2099,7 @@ const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall( Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs); CGCallee Callee = CGCallee::forDirect(CalleePtr, D); - EmitCall(Info, Callee, ReturnValueSlot(), Args); + EmitCall(Info, Callee, ReturnValueSlot(), Args, SourceLocation()); // Generate vtable assumptions if we're constructing a complete object // with a vtable. We don't do this for base subobjects for two reasons: @@ -2773,7 +2773,8 @@ // Now emit our call. auto callee = CGCallee::forDirect(calleePtr, callOperator); - RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); + RValue RV = + EmitCall(calleeFnInfo, callee, returnSlot, callArgs, SourceLocation()); // If necessary, copy the returned value into the slot. if (!resultType->isVoidType() && returnSlot.isNull()) Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -558,7 +558,7 @@ Args.add(RValue::get(Arg), CGF.getContext().getPointerType(Var.getType())); auto Callee = CGCallee::forDirect(CleanupFn); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); + CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args, SourceLocation()); } }; } // end anonymous namespace Index: lib/CodeGen/CGException.cpp =================================================================== --- lib/CodeGen/CGException.cpp +++ lib/CodeGen/CGException.cpp @@ -1442,7 +1442,7 @@ CGM.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, Args); auto Callee = CGCallee::forDirect(OutlinedFinally); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); + CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args, SourceLocation()); } }; } // end anonymous namespace Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -3030,6 +3030,17 @@ CGM.addUsedGlobal(F); } +void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { + if (SanOpts.has(SanitizerKind::Unreachable)) { + SanitizerScope SanScope(this); + EmitCheck(std::make_pair(static_cast(Builder.getFalse()), + SanitizerKind::Unreachable), + SanitizerHandler::BuiltinUnreachable, + EmitCheckSourceLocation(Loc), None); + } + Builder.CreateUnreachable(); +} + void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { llvm::BasicBlock *Cont = createBasicBlock("cont"); @@ -4577,7 +4588,7 @@ Callee.setFunctionPointer(CalleePtr); } - return EmitCall(FnInfo, Callee, ReturnValue, Args); + return EmitCall(FnInfo, Callee, ReturnValue, Args, E->getExprLoc()); } LValue CodeGenFunction:: Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -89,7 +89,8 @@ *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs); auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall( Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize); - return EmitCall(FnInfo, Callee, ReturnValue, Args); + return EmitCall(FnInfo, Callee, ReturnValue, Args, + CE ? CE->getExprLoc() : SourceLocation()); } RValue CodeGenFunction::EmitCXXDestructorCall( @@ -100,7 +101,7 @@ commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type), - Callee, ReturnValueSlot(), Args); + Callee, ReturnValueSlot(), Args, SourceLocation()); } RValue CodeGenFunction::EmitCXXPseudoDestructorExpr( @@ -444,7 +445,7 @@ EmitCallArgs(Args, FPT, E->arguments()); return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required, /*PrefixSize=*/0), - Callee, ReturnValue, Args); + Callee, ReturnValue, Args, E->getExprLoc()); } RValue @@ -1267,10 +1268,10 @@ llvm::Instruction *CallOrInvoke; llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl); CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl); - RValue RV = - CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( - Args, CalleeType, /*chainCall=*/false), - Callee, ReturnValueSlot(), Args, &CallOrInvoke); + RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( + Args, CalleeType, /*chainCall=*/false), + Callee, ReturnValueSlot(), Args, SourceLocation(), + &CallOrInvoke); /// C++1y [expr.new]p10: /// [In a new-expression,] an implementation is allowed to omit a call Index: lib/CodeGen/CGExprComplex.cpp =================================================================== --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -627,7 +627,8 @@ CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs()); llvm::Instruction *Call; - RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call); + RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, + SourceLocation(), &Call); cast(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); return Res.getComplexVal(); } Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -606,7 +606,7 @@ llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction(); CGCallee callee = CGCallee::forDirect(fn); CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } /// Determine whether the given architecture supports unaligned atomic @@ -872,7 +872,7 @@ CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn); CGF.EmitCall( CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } void @@ -970,9 +970,9 @@ // FIXME: We shouldn't need to get the function info here, the // runtime already should have computed it to build the function. llvm::Instruction *CallInstruction; - RValue RV = EmitCall( - getTypes().arrangeBuiltinFunctionCall(propType, args), - callee, ReturnValueSlot(), args, &CallInstruction); + RValue RV = + EmitCall(getTypes().arrangeBuiltinFunctionCall(propType, args), callee, + ReturnValueSlot(), args, SourceLocation(), &CallInstruction); if (llvm::CallInst *call = dyn_cast(CallInstruction)) call->setTailCall(); @@ -1088,7 +1088,7 @@ CGCallee callee = CGCallee::forDirect(fn); CGF.EmitCall( CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } /// emitCPPObjectAtomicSetterCall - Call the runtime function to store @@ -1125,7 +1125,7 @@ CGCallee callee = CGCallee::forDirect(fn); CGF.EmitCall( CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } @@ -1256,7 +1256,7 @@ args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); CGCallee callee = CGCallee::forDirect(setOptimizedPropertyFn); EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } else { args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); args.add(RValue::get(arg), getContext().getObjCIdType()); @@ -1268,7 +1268,7 @@ // already should have computed it to build the function. CGCallee callee = CGCallee::forDirect(setPropertyFn); EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), - callee, ReturnValueSlot(), args); + callee, ReturnValueSlot(), args, SourceLocation()); } return; @@ -1627,8 +1627,8 @@ // FIXME: We shouldn't need to get the function info here, the runtime already // should have computed it to build the function. EmitCall( - CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, Args2), - EnumerationMutationFn, ReturnValueSlot(), Args2); + CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, Args2), + EnumerationMutationFn, ReturnValueSlot(), Args2, SourceLocation()); // Otherwise, or if the mutation function returns, just continue. EmitBlock(WasNotMutatedBB); Index: lib/CodeGen/CGObjCGNU.cpp =================================================================== --- lib/CodeGen/CGObjCGNU.cpp +++ lib/CodeGen/CGObjCGNU.cpp @@ -1349,7 +1349,8 @@ CGCallee callee(CGCalleeInfo(), imp); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call); + RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, + SourceLocation(), &call); call->setMetadata(msgSendMDKind, node); return msgRet; } @@ -1462,10 +1463,10 @@ llvm::Instruction *call; CGCallee callee(CGCalleeInfo(), imp); - RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call); + RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, + SourceLocation(), &call); call->setMetadata(msgSendMDKind, node); - if (!isPointerSizedReturn) { messageBB = CGF.Builder.GetInsertBlock(); CGF.Builder.CreateBr(continueBB); Index: lib/CodeGen/CGObjCMac.cpp =================================================================== --- lib/CodeGen/CGObjCMac.cpp +++ lib/CodeGen/CGObjCMac.cpp @@ -2167,7 +2167,7 @@ Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); CGCallee Callee = CGCallee::forDirect(Fn); RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, - &CallSite); + SourceLocation(), &CallSite); // Mark the call as noreturn if the method is marked noreturn and the // receiver cannot be null. @@ -7092,7 +7092,8 @@ calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType); CGCallee callee(CGCalleeInfo(), calleePtr); - RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); + RValue result = + CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args, SourceLocation()); return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs, requiresnullCheck ? method : nullptr); } Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -357,7 +357,8 @@ // Now emit our call. llvm::Instruction *CallOrInvoke; CGCallee Callee = CGCallee::forDirect(CalleePtr, MD); - RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke); + RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, SourceLocation(), + &CallOrInvoke); // Consider return adjustment if we have ThunkInfo. if (Thunk && !Thunk->Return.isEmpty()) Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -3278,6 +3278,7 @@ /// LLVM arguments and the types they were derived from. RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, + SourceLocation Loc, llvm::Instruction **callOrInvoke = nullptr); RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E, @@ -3736,6 +3737,10 @@ llvm::ConstantInt *TypeId, llvm::Value *Ptr, ArrayRef StaticArgs); + /// Emit a reached-unreachable diagnostic if \p Loc is valid and runtime + /// checking is enabled. Otherwise, just emit an unreachable instruction. + void EmitUnreachable(SourceLocation Loc); + /// \brief Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. void EmitTrapCheck(llvm::Value *Checked); Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -3941,7 +3941,7 @@ CGCallee Callee = CGCallee::forDirect(CalleePtr, CD); const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix); - CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args); + CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args, SourceLocation()); Cleanups.ForceCleanup(); Index: test/CodeGen/ubsan-noreturn.c =================================================================== --- /dev/null +++ test/CodeGen/ubsan-noreturn.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - | FileCheck %s + +// CHECK-LABEL: @f( +void __attribute__((noreturn)) f() { + // CHECK: __ubsan_handle_builtin_unreachable + // CHECK: unreachable +} Index: test/CodeGenCXX/ubsan-unreachable.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/ubsan-unreachable.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=unreachable | FileCheck %s + +extern void __attribute__((noreturn)) abort(); + +// CHECK-LABEL: define void @_Z14calls_noreturnv +void calls_noreturn() { + abort(); + + // Check that there are no attributes on the call site. + // CHECK-NOT: call void @_Z5abortv{{.*}}# + + // CHECK: __ubsan_handle_builtin_unreachable + // CHECK: unreachable +} + +struct A { + // Test regular members. + void __attribute__((noreturn)) does_not_return1() { + // CHECK-NOT: call void @_Z5abortv(){{.*}}# + abort(); + } + + // CHECK: declare void @_Z5abortv{{.*}} [[ABORT_ATTR:#[0-9]+]] + + // CHECK-LABEL: define linkonce_odr void @_ZN1A5call1Ev + void call1() { + // CHECK-NOT: call void @_ZN1A16does_not_return1Ev{{.*}}# + does_not_return1(); + + // CHECK: __ubsan_handle_builtin_unreachable + // CHECK: unreachable + } + + // Test static members. + static void __attribute__((noreturn)) does_not_return2() { + // CHECK-NOT: call void @_Z5abortv{{.*}}# + abort(); + } + + // CHECK-LABEL: define linkonce_odr void @_ZN1A5call2Ev + void call2() { + // CHECK-NOT: call void @_ZN1A16does_not_return2Ev{{.*}}# + does_not_return2(); + + // CHECK: __ubsan_handle_builtin_unreachable + // CHECK: unreachable + } + + // Test calls through pointers to non-static member functions. + typedef void __attribute__((noreturn)) (A::*MemFn)(); + + // CHECK-LABEL: define linkonce_odr void @_ZN1A5call3Ev + void call3() { + MemFn MF = &A::does_not_return1; + (this->*MF)(); + + // CHECK-NOT: call void %{{.*}}# + // CHECK: __ubsan_handle_builtin_unreachable + // CHECK: unreachable + } +}; + +// CHECK: define linkonce_odr void @_ZN1A16does_not_return1Ev{{.*}} [[DOES_NOT_RETURN_ATTR:#[0-9]+]] +// CHECK: define linkonce_odr void @_ZN1A16does_not_return2Ev{{.*}} [[DOES_NOT_RETURN_ATTR]] + +void force_irgen() { + A a; + a.call1(); + a.call2(); + a.call3(); +} + +// CHECK-NOT: [[ABORT_ATTR]] = {{[^}]+}}noreturn +// CHECK-NOT: [[DOES_NOT_RETURN_ATTR]] = {{[^}]+}}noreturn