Index: include/clang/Basic/LangOptions.h =================================================================== --- include/clang/Basic/LangOptions.h +++ include/clang/Basic/LangOptions.h @@ -92,6 +92,10 @@ /// If none is specified, abort (GCC-compatible behaviour). std::string OverflowHandler; + /// \brief Flag controlling whether or not trap calls are merged + /// at the end of each function. + bool mergeTraps; + /// \brief The name of the current module. std::string CurrentModule; Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -607,6 +607,12 @@ : CommaJoined<["-"], "fno-sanitize-recover=">, Group, Flags<[CoreOption]>, HelpText<"Disable recovery for specified sanitizers">; +def fsanitize_merge_traps : Flag<["-"], "fsanitize-merge-traps">, + Group, + HelpText<"Merge all traps for sanitizers to one per function.">; +def fno_sanitize_merge_traps : Flag<["-"], "fno-sanitize-merge-traps">, + Group, + HelpText<"Generate traps for sanitizers inline to aid in debugging.">; def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Enable trapping for specified sanitizers">; Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" @@ -2535,9 +2536,25 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { llvm::BasicBlock *Cont = createBasicBlock("cont"); - // If we're optimizing, collapse all calls to trap down to just one per - // function to save on code size. - if (!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB) { + // Collapsing all calls to trap down to one per function makes debugging + // these issues much more difficult. Eliminating this optimization + // for debugging purposes. + // RE: Bug: 25682 + if(!getLangOpts().mergeTraps) { + llvm::InlineAsm *EmptyAsm = llvm::InlineAsm::get(llvm::FunctionType::get(CGM.VoidTy, false), + StringRef(""), StringRef(""), true); + TrapBB = createBasicBlock("trap"); + Builder.CreateCondBr(Checked, Cont, TrapBB); + EmitBlock(TrapBB); + llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); + TrapCall->setDoesNotReturn(); + TrapCall->setDoesNotThrow(); + Builder.CreateUnreachable(); + //this stops the trap calls from being merged at the end of the function + Builder.CreateCall(EmptyAsm, {}); + } else if(!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB) { + // If we're optimizing, collapse all calls to trap down to just one per + // function to save on code size. TrapBB = createBasicBlock("trap"); Builder.CreateCondBr(Checked, Cont, TrapBB); EmitBlock(TrapBB); @@ -2548,7 +2565,7 @@ } else { Builder.CreateCondBr(Checked, Cont, TrapBB); } - + EmitBlock(Cont); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1569,6 +1569,12 @@ if (Args.hasArg(OPT_fvisibility_inlines_hidden)) Opts.InlineVisibilityHidden = 1; + if (Args.hasArg(OPT_fno_sanitize_merge_traps)) { + Opts.mergeTraps = false; + } else { + Opts.mergeTraps = true; + } + if (Args.hasArg(OPT_ftrapv)) { Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); // Set the handler, if one is specified.