[DAG] Fix typo in VSELECT SimplifyDemandedVectorElts handling. NFC.
[llvm-project.git] / lldb / source / Commands / CommandObjectDWIMPrint.cpp
blob695f3d7931cd0a226539a77faf98029f03039601
1 //===-- CommandObjectDWIMPrint.cpp ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectDWIMPrint.h"
11 #include "lldb/Core/ValueObject.h"
12 #include "lldb/DataFormatters/DumpValueObjectOptions.h"
13 #include "lldb/Expression/ExpressionVariable.h"
14 #include "lldb/Expression/UserExpression.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandObject.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionGroupFormat.h"
19 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Utility/ConstString.h"
22 #include "lldb/lldb-defines.h"
23 #include "lldb/lldb-enumerations.h"
24 #include "lldb/lldb-forward.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/Support/FormatVariadic.h"
28 #include <regex>
30 using namespace llvm;
31 using namespace lldb;
32 using namespace lldb_private;
34 CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter)
35 : CommandObjectRaw(interpreter, "dwim-print",
36 "Print a variable or expression.",
37 "dwim-print [<variable-name> | <expression>]",
38 eCommandProcessMustBePaused | eCommandTryTargetAPILock) {
40 CommandArgumentData var_name_arg(eArgTypeVarName, eArgRepeatPlain);
41 m_arguments.push_back({var_name_arg});
43 m_option_group.Append(&m_format_options,
44 OptionGroupFormat::OPTION_GROUP_FORMAT |
45 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
46 LLDB_OPT_SET_1);
47 StringRef exclude_expr_options[] = {"debug", "top-level"};
48 m_option_group.Append(&m_expr_options, exclude_expr_options);
49 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
50 m_option_group.Finalize();
53 Options *CommandObjectDWIMPrint::GetOptions() { return &m_option_group; }
55 void CommandObjectDWIMPrint::HandleArgumentCompletion(
56 CompletionRequest &request, OptionElementVector &opt_element_vector) {
57 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
58 GetCommandInterpreter(), lldb::eVariablePathCompletion, request, nullptr);
61 void CommandObjectDWIMPrint::DoExecute(StringRef command,
62 CommandReturnObject &result) {
63 m_option_group.NotifyOptionParsingStarting(&m_exe_ctx);
64 OptionsWithRaw args{command};
65 StringRef expr = args.GetRawPart();
67 if (expr.empty()) {
68 result.AppendErrorWithFormatv("'{0}' takes a variable or expression",
69 m_cmd_name);
70 return;
73 if (args.HasArgs()) {
74 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
75 m_exe_ctx))
76 return;
79 // If the user has not specified, default to disabling persistent results.
80 if (m_expr_options.suppress_persistent_result == eLazyBoolCalculate)
81 m_expr_options.suppress_persistent_result = eLazyBoolYes;
82 bool suppress_result = m_expr_options.ShouldSuppressResult(m_varobj_options);
84 auto verbosity = GetDebugger().GetDWIMPrintVerbosity();
86 Target *target_ptr = m_exe_ctx.GetTargetPtr();
87 // Fallback to the dummy target, which can allow for expression evaluation.
88 Target &target = target_ptr ? *target_ptr : GetDummyTarget();
90 EvaluateExpressionOptions eval_options =
91 m_expr_options.GetEvaluateExpressionOptions(target, m_varobj_options);
92 // This command manually removes the result variable, make sure expression
93 // evaluation doesn't do it first.
94 eval_options.SetSuppressPersistentResult(false);
96 DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions(
97 m_expr_options.m_verbosity, m_format_options.GetFormat());
98 dump_options.SetHideRootName(suppress_result);
100 bool is_po = m_varobj_options.use_objc;
102 StackFrame *frame = m_exe_ctx.GetFramePtr();
104 // Either Swift was explicitly specified, or the frame is Swift.
105 lldb::LanguageType language = m_expr_options.language;
106 if (language == lldb::eLanguageTypeUnknown && frame)
107 language = frame->GuessLanguage();
109 // Add a hint if object description was requested, but no description
110 // function was implemented.
111 auto maybe_add_hint = [&](llvm::StringRef output) {
112 // Identify the default output of object description for Swift and
113 // Objective-C
114 // "<Name: 0x...>. The regex is:
115 // - Start with "<".
116 // - Followed by 1 or more non-whitespace characters.
117 // - Followed by ": 0x".
118 // - Followed by 5 or more hex digits.
119 // - Followed by ">".
120 // - End with zero or more whitespace characters.
121 const std::regex swift_class_regex("^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$");
123 if (GetDebugger().GetShowDontUsePoHint() && target_ptr &&
124 (language == lldb::eLanguageTypeSwift ||
125 language == lldb::eLanguageTypeObjC) &&
126 std::regex_match(output.data(), swift_class_regex)) {
128 static bool note_shown = false;
129 if (note_shown)
130 return;
132 result.GetOutputStream()
133 << "note: object description requested, but type doesn't implement "
134 "a custom object description. Consider using \"p\" instead of "
135 "\"po\" (this note will only be shown once per debug session).\n";
136 note_shown = true;
140 // First, try `expr` as the name of a frame variable.
141 if (frame) {
142 auto valobj_sp = frame->FindVariable(ConstString(expr));
143 if (valobj_sp && valobj_sp->GetError().Success()) {
144 if (!suppress_result) {
145 if (auto persisted_valobj = valobj_sp->Persist())
146 valobj_sp = persisted_valobj;
149 if (verbosity == eDWIMPrintVerbosityFull) {
150 StringRef flags;
151 if (args.HasArgs())
152 flags = args.GetArgString();
153 result.AppendMessageWithFormatv("note: ran `frame variable {0}{1}`",
154 flags, expr);
157 if (is_po) {
158 StreamString temp_result_stream;
159 valobj_sp->Dump(temp_result_stream, dump_options);
160 llvm::StringRef output = temp_result_stream.GetString();
161 maybe_add_hint(output);
162 result.GetOutputStream() << output;
163 } else {
164 valobj_sp->Dump(result.GetOutputStream(), dump_options);
166 result.SetStatus(eReturnStatusSuccessFinishResult);
167 return;
171 // Second, also lastly, try `expr` as a source expression to evaluate.
173 auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
174 ValueObjectSP valobj_sp;
175 std::string fixed_expression;
177 ExpressionResults expr_result = target.EvaluateExpression(
178 expr, exe_scope, valobj_sp, eval_options, &fixed_expression);
180 // Only mention Fix-Its if the expression evaluator applied them.
181 // Compiler errors refer to the final expression after applying Fix-It(s).
182 if (!fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
183 Stream &error_stream = result.GetErrorStream();
184 error_stream << " Evaluated this expression after applying Fix-It(s):\n";
185 error_stream << " " << fixed_expression << "\n";
188 if (expr_result == eExpressionCompleted) {
189 if (verbosity != eDWIMPrintVerbosityNone) {
190 StringRef flags;
191 if (args.HasArgs())
192 flags = args.GetArgStringWithDelimiter();
193 result.AppendMessageWithFormatv("note: ran `expression {0}{1}`", flags,
194 expr);
197 if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) {
198 if (is_po) {
199 StreamString temp_result_stream;
200 valobj_sp->Dump(temp_result_stream, dump_options);
201 llvm::StringRef output = temp_result_stream.GetString();
202 maybe_add_hint(output);
203 result.GetOutputStream() << output;
204 } else {
205 valobj_sp->Dump(result.GetOutputStream(), dump_options);
209 if (suppress_result)
210 if (auto result_var_sp =
211 target.GetPersistentVariable(valobj_sp->GetName())) {
212 auto language = valobj_sp->GetPreferredDisplayLanguage();
213 if (auto *persistent_state =
214 target.GetPersistentExpressionStateForLanguage(language))
215 persistent_state->RemovePersistentVariable(result_var_sp);
218 result.SetStatus(eReturnStatusSuccessFinishResult);
219 } else {
220 if (valobj_sp)
221 result.SetError(valobj_sp->GetError());
222 else
223 result.AppendErrorWithFormatv(
224 "unknown error evaluating expression `{0}`", expr);