Author: Dave Lee Date: 2024-03-15T16:09:24-07:00 New Revision: 4da2b542b142dac441722e044ee75da2475d9a20
URL: https://github.com/llvm/llvm-project/commit/4da2b542b142dac441722e044ee75da2475d9a20 DIFF: https://github.com/llvm/llvm-project/commit/4da2b542b142dac441722e044ee75da2475d9a20.diff LOG: [lldb] Fix dwim-print to not delete non-result persistent variables (#85152) `EvaluateExpression` does not always create a new persistent result. If the expression is a bare persistent variable, then a new persistent result is not created. This means the caller can't assume a new persistent result is created for each evaluation. However, `dwim-print` was doing exactly that: assuming a new persistent result for each evaluation. This resulted in a bug: ``` (lldb) p int $j = 23 (lldb) p $j (lldb) p $j ``` The first `p $j` would not create a persistent result, and so `dwim-print` would inadvertently delete `$j`. The second `p $j` would fail. The fix is to try `expr` as a persistent variable, after trying `expr` as a frame variable. For persistent variables, this avoids calling `EvaluateExpression`. Resolves https://github.com/llvm/llvm-project/issues/84806 rdar://124688427 Added: Modified: lldb/source/Commands/CommandObjectDWIMPrint.cpp lldb/test/API/commands/dwim-print/TestDWIMPrint.py Removed: ################################################################################ diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index b183cb423111fb..a88da986bb384f 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -23,7 +23,6 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/FormatVariadic.h" #include <regex> @@ -161,7 +160,17 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, } } - // Second, also lastly, try `expr` as a source expression to evaluate. + // Second, try `expr` as a persistent variable. + if (expr.starts_with("$")) + if (auto *state = target.GetPersistentExpressionStateForLanguage(language)) + if (auto var_sp = state->GetVariable(expr)) + if (auto valobj_sp = var_sp->GetValueObject()) { + valobj_sp->Dump(result.GetOutputStream(), dump_options); + result.SetStatus(eReturnStatusSuccessFinishResult); + return; + } + + // Third, and lastly, try `expr` as a source expression to evaluate. { auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; diff --git a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py index 040632096c70e7..c650b1e3533e08 100644 --- a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py +++ b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py @@ -146,3 +146,15 @@ def test_void_result(self): self, "// break here", lldb.SBFileSpec("main.c") ) self.expect("dwim-print (void)15", matching=False, patterns=["(?i)error"]) + + def test_preserves_persistent_variables(self): + """Test dwim-print does not delete persistent variables.""" + self.build() + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.c") + ) + self.expect("dwim-print int $i = 15") + # Run the same expression twice and verify success. This ensures the + # first command does not delete the persistent variable. + for _ in range(2): + self.expect("dwim-print $i", startstr="(int) 15") _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits