diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.h b/lldb/source/Commands/CommandObjectDWIMPrint.h --- a/lldb/source/Commands/CommandObjectDWIMPrint.h +++ b/lldb/source/Commands/CommandObjectDWIMPrint.h @@ -43,6 +43,13 @@ HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override; + /// Add a hint if object description was requested, but no description + /// function was implemented, and dump valobj to output_stream after. + static void MaybeAddPoHintAndDump(ValueObject &valobj, + const DumpValueObjectOptions &dump_options, + lldb::LanguageType language, bool is_po, + Stream &output_stream); + private: bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -25,6 +25,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" +#include + using namespace llvm; using namespace lldb; using namespace lldb_private; @@ -56,6 +58,33 @@ GetCommandInterpreter(), lldb::eVariablePathCompletion, request, nullptr); } +void CommandObjectDWIMPrint::MaybeAddPoHintAndDump( + ValueObject &valobj, const DumpValueObjectOptions &dump_options, + lldb::LanguageType language, bool is_po, Stream &output_stream) { + // Identify the default output of object description for Swift and Objective-C + // ". The regex is: + // - Start with "<". + // - Followed by 1 or more non-whitespace characters. + // - Followed by ": 0x". + // - Followed by 5 or more hex digits. + // - Followed by ">". + // - End with zero or more whitespace characters. + static const std::regex swift_class_regex("^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$"); + + StreamString temp_result_stream; + valobj.Dump(temp_result_stream, dump_options); + const char *temp_result = temp_result_stream.GetData(); + if ((language == lldb::eLanguageTypeSwift || + language == lldb::eLanguageTypeObjC) && + is_po && std::regex_match(temp_result, swift_class_regex)) + output_stream + << "note: object description requested, but type doesn't implement " + "a custom object description. Consider using \"p\" instead of " + "\"po\"\n"; + + output_stream << temp_result; +} + bool CommandObjectDWIMPrint::DoExecute(StringRef command, CommandReturnObject &result) { m_option_group.NotifyOptionParsingStarting(&m_exe_ctx); @@ -95,8 +124,15 @@ m_expr_options.m_verbosity, m_format_options.GetFormat()); dump_options.SetHideRootName(suppress_result); + bool is_po = m_varobj_options.use_objc; + StackFrame *frame = m_exe_ctx.GetFramePtr(); + // Either Swift was explicitly specified, or the frame is Swift. + lldb::LanguageType language = m_expr_options.language; + if (language == lldb::eLanguageTypeUnknown && frame) + language = frame->GuessLanguage(); + // First, try `expr` as the name of a frame variable. if (frame) { auto valobj_sp = frame->FindVariable(ConstString(expr)); @@ -114,7 +150,9 @@ flags, expr); } - valobj_sp->Dump(result.GetOutputStream(), dump_options); + MaybeAddPoHintAndDump(*valobj_sp.get(), dump_options, language, is_po, + result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -136,7 +174,8 @@ } if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) - valobj_sp->Dump(result.GetOutputStream(), dump_options); + MaybeAddPoHintAndDump(*valobj_sp.get(), dump_options, language, is_po, + result.GetOutputStream()); if (suppress_result) if (auto result_var_sp = diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -9,6 +9,8 @@ #include "llvm/ADT/StringRef.h" #include "CommandObjectExpression.h" + +#include "CommandObjectDWIMPrint.h" #include "lldb/Core/Debugger.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/REPL.h" @@ -473,7 +475,13 @@ options.SetVariableFormatDisplayLanguage( result_valobj_sp->GetPreferredDisplayLanguage()); - result_valobj_sp->Dump(output_stream, options); + bool is_po = m_varobj_options.use_objc; + lldb::LanguageType language = m_command_options.language; + if (language == lldb::eLanguageTypeUnknown && frame) + language = frame->GuessLanguage(); + CommandObjectDWIMPrint::MaybeAddPoHintAndDump(*result_valobj_sp.get(), + options, language, is_po, + result.GetOutputStream()); if (suppress_result) if (auto result_var_sp = diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// #include "CommandObjectFrame.h" + +#include "CommandObjectDWIMPrint.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/DataVisualization.h" @@ -513,6 +515,9 @@ if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) m_option_variable.show_globals = true; + bool is_po = m_varobj_options.use_objc; + auto language = frame->GuessLanguage(); + if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); @@ -556,7 +561,10 @@ show_module)) s.PutCString(": "); } - valobj_sp->Dump(result.GetOutputStream(), options); + + CommandObjectDWIMPrint::MaybeAddPoHintAndDump( + *valobj_sp.get(), options, language, is_po, + result.GetOutputStream()); } } } @@ -604,7 +612,8 @@ Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName( valobj_sp->GetParent() ? entry.c_str() : nullptr); - valobj_sp->Dump(output_stream, options); + CommandObjectDWIMPrint::MaybeAddPoHintAndDump( + *valobj_sp.get(), options, language, is_po, output_stream); } else { if (auto error_cstr = error.AsCString(nullptr)) result.AppendError(error_cstr); @@ -674,7 +683,9 @@ valobj_sp->GetPreferredDisplayLanguage()); options.SetRootValueObjectName( var_sp ? var_sp->GetName().AsCString() : nullptr); - valobj_sp->Dump(result.GetOutputStream(), options); + CommandObjectDWIMPrint::MaybeAddPoHintAndDump( + *valobj_sp.get(), options, language, is_po, + result.GetOutputStream()); } } } @@ -694,8 +705,11 @@ options.SetFormat(m_option_format.GetFormat()); options.SetVariableFormatDisplayLanguage( rec_value_sp->GetPreferredDisplayLanguage()); + rec_value_sp->GetPreferredDisplayLanguage(); options.SetRootValueObjectName(rec_value_sp->GetName().AsCString()); - rec_value_sp->Dump(result.GetOutputStream(), options); + CommandObjectDWIMPrint::MaybeAddPoHintAndDump( + *rec_value_sp.get(), options, language, is_po, + result.GetOutputStream()); } } }