diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 9501a9e5dc395..f9d72c6711fba 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -533,6 +533,17 @@ class StackFrame : public ExecutionContextScope, lldb::RecognizedStackFrameSP GetRecognizedFrame(); + // BEGIN SWIFT + // Implement LanguageCPlusPlus::GetParentNameIfClosure and upstream this. + // rdar://152321823 + /// If `sc` represents a "closure-like" function according to `lang`, and + /// `missing_var_name` can be found in a parent context, create a diagnostic + /// explaining that this variable is available but not captured by the + /// closure. + std::string + GetVariableNotCapturedDiagnostic(llvm::StringRef missing_var_name); + // END SWIFT + protected: friend class StackFrameList; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index a8b4ae5944f0a..da24f24df7cff 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -479,20 +479,13 @@ VariableList *StackFrame::GetVariableList(bool get_file_globals, } // BEGIN SWIFT -// Implement LanguageCPlusPlus::GetParentNameIfClosure and upstream this. -// rdar://152321823 - -/// If `sc` represents a "closure-like" function according to `lang`, and -/// `missing_var_name` can be found in a parent context, create a diagnostic -/// explaining that this variable is available but not captured by the closure. -static std::string -GetVariableNotCapturedDiagnostic(SymbolContext &sc, SourceLanguage lang, - ConstString missing_var_name) { - Language *lang_plugin = Language::FindPlugin(lang.AsLanguageType()); +std::string +StackFrame::GetVariableNotCapturedDiagnostic(llvm::StringRef missing_var_name) { + Language *lang_plugin = Language::FindPlugin(GetLanguage().AsLanguageType()); if (lang_plugin == nullptr) return ""; Function *parent_func = - lang_plugin->FindParentOfClosureWithVariable(missing_var_name, sc); + lang_plugin->FindParentOfClosureWithVariable(missing_var_name, m_sc); if (!parent_func) return ""; return llvm::formatv("A variable named '{0}' existed in function '{1}', but " @@ -708,8 +701,8 @@ ValueObjectSP StackFrame::LegacyGetValueForVariableExpressionPath( // BEGIN SWIFT // Implement LanguageCPlusPlus::GetParentNameIfClosure and upstream this. // rdar://152321823 - if (std::string message = GetVariableNotCapturedDiagnostic( - m_sc, GetLanguage(), name_const_string); + if (std::string message = + GetVariableNotCapturedDiagnostic(name_const_string); !message.empty()) error = Status::FromErrorString(message.c_str()); else diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index 6f28434c646cd..7fd17b6a42dc8 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -161,6 +161,15 @@ Interpreter::Visit(const IdentifierNode *node) { identifier = LookupGlobalIdentifier(node->GetName(), m_exe_ctx_scope, m_target, use_dynamic); if (!identifier) { + // BEGIN SWIFT + // Implement LanguageCPlusPlus::GetParentNameIfClosure and upstream this. + // rdar://152321823 + if (std::string message = + m_exe_ctx_scope->GetVariableNotCapturedDiagnostic(node->GetName()); + !message.empty()) + return llvm::make_error( + m_expr, message, node->GetLocation(), node->GetName().size()); + // END SWIFT std::string errMsg = llvm::formatv("use of undeclared identifier '{0}'", node->GetName()); return llvm::make_error( diff --git a/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py b/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py index b483abf5b9b04..a18495b6b6516 100644 --- a/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py +++ b/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py @@ -54,8 +54,6 @@ def get_to_bkpt(self, bkpt_name): @swiftTest def test_simple_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_simple_closure") check_not_captured_error(self, thread.frames[0], "var_in_foo", "func_1(arg:)") check_not_captured_error(self, thread.frames[0], "arg", "func_1(arg:)") @@ -64,8 +62,6 @@ def test_simple_closure(self): @swiftTest def test_nested_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_double_closure_1") check_not_captured_error(self, thread.frames[0], "var_in_foo", "func_2(arg:)") check_not_captured_error(self, thread.frames[0], "arg", "func_2(arg:)") @@ -92,8 +88,6 @@ def test_nested_closure(self): @skipIf(oslist=["windows", "linux"]) def test_async_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_async_closure_1") check_not_captured_error(self, thread.frames[0], "var_in_foo", "func_3(arg:)") check_not_captured_error(self, thread.frames[0], "arg", "func_3(arg:)") @@ -115,8 +109,6 @@ def test_async_closure(self): @swiftTest def test_ctor_class_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_ctor_class") check_not_captured_error( self, thread.frames[0], "input", "MY_CLASS.init(input:)" @@ -174,8 +166,6 @@ def test_ctor_class_closure(self): @swiftTest def test_ctor_struct_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_ctor_struct") check_not_captured_error( self, thread.frames[0], "input", "MY_STRUCT.init(input:)" @@ -233,8 +223,6 @@ def test_ctor_struct_closure(self): @swiftTest def test_ctor_enum_closure(self): self.build() - # rdar://158447239 - self.runCmd('settings set target.experimental.use-DIL false') (target, process, thread) = self.get_to_bkpt("break_ctor_enum") check_not_captured_error( self, thread.frames[0], "input", "MY_ENUM.init(input:)"