@@ -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,62 @@ DAP::DAP()
6558
6659DAP::~DAP () = default ;
6760
61+ void DAP::PopulateExceptionBreakpoints () {
62+ llvm::call_once (init_exception_breakpoints_flag, [this ]() {
63+ exception_breakpoints = std::vector<ExceptionBreakpoint> {};
64+
65+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeC_plus_plus)) {
66+ exception_breakpoints->emplace_back (" cpp_catch" , " C++ Catch" ,
67+ lldb::eLanguageTypeC_plus_plus);
68+ exception_breakpoints->emplace_back (" cpp_throw" , " C++ Throw" ,
69+ lldb::eLanguageTypeC_plus_plus);
70+ }
71+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeObjC)) {
72+ exception_breakpoints->emplace_back (" objc_catch" , " Objective-C Catch" ,
73+ lldb::eLanguageTypeObjC);
74+ exception_breakpoints->emplace_back (" objc_throw" , " Objective-C Throw" ,
75+ lldb::eLanguageTypeObjC);
76+ }
77+ if (lldb::SBDebugger::SupportsLanguage (lldb::eLanguageTypeSwift)) {
78+ exception_breakpoints->emplace_back (" swift_catch" , " Swift Catch" ,
79+ lldb::eLanguageTypeSwift);
80+ exception_breakpoints->emplace_back (" swift_throw" , " Swift Throw" ,
81+ lldb::eLanguageTypeSwift);
82+ }
83+ assert (!exception_breakpoints->empty () && " should not be empty" );
84+ });
85+ }
86+
6887ExceptionBreakpoint *DAP::GetExceptionBreakpoint (const std::string &filter) {
69- for (auto &bp : exception_breakpoints) {
88+ // PopulateExceptionBreakpoints() is called after g_dap.debugger is created
89+ // in a request-initialize.
90+ //
91+ // But this GetExceptionBreakpoint() method may be called before attaching, in
92+ // which case, we may not have populated the filter yet.
93+ //
94+ // We also cannot call PopulateExceptionBreakpoints() in DAP::DAP() because
95+ // we need SBDebugger::Initialize() to have been called before this.
96+ //
97+ // So just calling PopulateExceptionBreakoints(),which does lazy-populating
98+ // seems easiest. Two other options include:
99+ // + call g_dap.PopulateExceptionBreakpoints() in lldb-dap.cpp::main()
100+ // right after the call to SBDebugger::Initialize()
101+ // + Just call PopulateExceptionBreakpoints() to get a fresh list everytime
102+ // we query (a bit overkill since it's not likely to change?)
103+ PopulateExceptionBreakpoints ();
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+
116+ for (auto &bp : *exception_breakpoints) {
78117 if (bp.bp .GetID () == bp_id)
79118 return &bp;
80119 }
0 commit comments