================ @@ -65,16 +58,60 @@ DAP::DAP() DAP::~DAP() = default; +void DAP::PopulateExceptionBreakpoints() { + exception_breakpoints = {}; + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeC_plus_plus)) { + exception_breakpoints->emplace_back("cpp_catch", "C++ Catch", + lldb::eLanguageTypeC_plus_plus); + exception_breakpoints->emplace_back("cpp_throw", "C++ Throw", + lldb::eLanguageTypeC_plus_plus); + } + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeObjC)) { + exception_breakpoints->emplace_back("objc_catch", "Objective-C Catch", + lldb::eLanguageTypeObjC); + exception_breakpoints->emplace_back("objc_throw", "Objective-C Throw", + lldb::eLanguageTypeObjC); + } + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeSwift)) { + exception_breakpoints->emplace_back("swift_catch", "Swift Catch", + lldb::eLanguageTypeSwift); + exception_breakpoints->emplace_back("swift_throw", "Swift Throw", + lldb::eLanguageTypeSwift); + } +} + ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const std::string &filter) { - for (auto &bp : exception_breakpoints) { + // PopulateExceptionBreakpoints() is called after g_dap.debugger is created + // in a request-initialize. + // + // But this GetExceptionBreakpoint() method may be called before attaching, in + // which case, we may not have populated the filter yet. + // + // We also cannot call PopulateExceptionBreakpoints() in DAP::DAP() because + // we need SBDebugger::Initialize() to have been called before this. + // + // So just checking the filter list and do lazy-populating seems easiest. + // Two other options include: + // + call g_dap.PopulateExceptionBreakpoints() in lldb-dap.cpp::main() + // right after the call to SBDebugger::Initialize() + // + Just call PopulateExceptionBreakpoints() to get a fresh list everytime + // we query (a bit overkill since it's not likely to change?) + if (!exception_breakpoints.has_value()) ---------------- JDevlieghere wrote:
You could avoid having to duplicate this check (and the comment) by hoisting it into `PopulateExceptionBreakpoints` and call it unconditionally here. You can keep an assert to convey the precondition is that `PopulateExceptionBreakpoints` must have been called: ``` assert(exception_breakpoints && "PopulateExceptionBreakpoints must be called") ``` I'm not familiar enough with the code to know if there's a risk of racing on that variable, but if I was implementing the lazy approach, I would wrap the thing into a `call_once`. If there's no risk of multiple threads calling `GetExceptionBreakpoint` then this might be overkill and checking the optional is sufficient and marginally more efficient. https://github.com/llvm/llvm-project/pull/94625 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits