@@ -32,14 +32,7 @@ namespace lldb_dap {
3232DAP g_dap;
3333
3434DAP::DAP ()
35- : broadcaster(" lldb-dap" ),
36- exception_breakpoints (
37- {{" cpp_catch" , " C++ Catch" , lldb::eLanguageTypeC_plus_plus},
38- {" cpp_throw" , " C++ Throw" , lldb::eLanguageTypeC_plus_plus},
39- {" objc_catch" , " Objective-C Catch" , lldb::eLanguageTypeObjC},
40- {" objc_throw" , " Objective-C Throw" , lldb::eLanguageTypeObjC},
41- {" swift_catch" , " Swift Catch" , lldb::eLanguageTypeSwift},
42- {" swift_throw" , " Swift Throw" , lldb::eLanguageTypeSwift}}),
35+ : broadcaster(" lldb-dap" ), exception_breakpoints(),
4336 focus_tid (LLDB_INVALID_THREAD_ID), stop_at_entry(false ), is_attach(false ),
4437 enable_auto_variable_summaries(false ),
4538 enable_synthetic_child_debugging(false ),
@@ -65,16 +58,64 @@ DAP::DAP()
6558
6659DAP::~DAP () = default ;
6760
61+ void DAP::PopulateExceptionBreakpoints () {
62+ llvm::call_once (initExceptionBreakpoints, [this ]() {
63+ exception_breakpoints = {};
64+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeC_plus_plus)) {
65+ exception_breakpoints->emplace_back (" cpp_catch" , " C++ Catch" ,
66+ lldb::eLanguageTypeC_plus_plus);
67+ exception_breakpoints->emplace_back (" cpp_throw" , " C++ Throw" ,
68+ lldb::eLanguageTypeC_plus_plus);
69+ }
70+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeObjC)) {
71+ exception_breakpoints->emplace_back (" objc_catch" , " Objective-C Catch" ,
72+ lldb::eLanguageTypeObjC);
73+ exception_breakpoints->emplace_back (" objc_throw" , " Objective-C Throw" ,
74+ lldb::eLanguageTypeObjC);
75+ }
76+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeSwift)) {
77+ exception_breakpoints->emplace_back (" swift_catch" , " Swift Catch" ,
78+ lldb::eLanguageTypeSwift);
79+ exception_breakpoints->emplace_back (" swift_throw" , " Swift Throw" ,
80+ lldb::eLanguageTypeSwift);
81+ }
82+ });
83+ }
84+
6885ExceptionBreakpoint *DAP::GetExceptionBreakpoint (const std::string &filter) {
69- for (auto &bp : exception_breakpoints) {
86+ // PopulateExceptionBreakpoints() is called after g_dap.debugger is created
87+ // in a request-initialize.
88+ //
89+ // But this GetExceptionBreakpoint() method may be called before attaching, in
90+ // which case, we may not have populated the filter yet.
91+ //
92+ // We also cannot call PopulateExceptionBreakpoints() in DAP::DAP() because
93+ // we need SBDebugger::Initialize() to have been called before this.
94+ //
95+ // So just calling PopulateExceptionBreakoints(),which does lazy-populating
96+ // seems easiest. Two other options include:
97+ // + call g_dap.PopulateExceptionBreakpoints() in lldb-dap.cpp::main()
98+ // right after the call to SBDebugger::Initialize()
99+ // + Just call PopulateExceptionBreakpoints() to get a fresh list everytime
100+ // we query (a bit overkill since it's not likely to change?)
101+ PopulateExceptionBreakpoints ();
102+ assert (exception_breakpoints.has_value () &&
103+ " exception_breakpoints must have been populated" );
104+
105+ for (auto &bp : *exception_breakpoints) {
70106 if (bp.filter == filter)
71107 return &bp;
72108 }
73109 return nullptr ;
74110}
75111
76112ExceptionBreakpoint *DAP::GetExceptionBreakpoint (const lldb::break_id_t bp_id) {
77- for (auto &bp : exception_breakpoints) {
113+ // See comment in the other GetExceptionBreakpoint().
114+ PopulateExceptionBreakpoints ();
115+ assert (exception_breakpoints.has_value () &&
116+ " exception_breakpoints must have been populated" );
117+
118+ for (auto &bp : *exception_breakpoints) {
78119 if (bp.bp .GetID () == bp_id)
79120 return &bp;
80121 }
0 commit comments