Bug Summary

File:lldb/source/Commands/CommandObjectType.cpp
Warning:line 2265, column 7
Potential leak of memory pointed to by 'options'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CommandObjectType.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Commands -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source/Commands -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-19-134126-35450-1 -x c++ /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source/Commands/CommandObjectType.cpp
1//===-- CommandObjectType.cpp ---------------------------------------------===//
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//===----------------------------------------------------------------------===//
8
9#include "CommandObjectType.h"
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/IOHandler.h"
13#include "lldb/DataFormatters/DataVisualization.h"
14#include "lldb/Host/Config.h"
15#include "lldb/Host/OptionParser.h"
16#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Interpreter/CommandObject.h"
18#include "lldb/Interpreter/CommandReturnObject.h"
19#include "lldb/Interpreter/OptionArgParser.h"
20#include "lldb/Interpreter/OptionGroupFormat.h"
21#include "lldb/Interpreter/OptionValueBoolean.h"
22#include "lldb/Interpreter/OptionValueLanguage.h"
23#include "lldb/Interpreter/OptionValueString.h"
24#include "lldb/Interpreter/Options.h"
25#include "lldb/Symbol/Symbol.h"
26#include "lldb/Target/Language.h"
27#include "lldb/Target/StackFrame.h"
28#include "lldb/Target/Target.h"
29#include "lldb/Target/Thread.h"
30#include "lldb/Utility/ConstString.h"
31#include "lldb/Utility/RegularExpression.h"
32#include "lldb/Utility/StringList.h"
33
34#include "llvm/ADT/STLExtras.h"
35
36#include <algorithm>
37#include <functional>
38#include <memory>
39
40#define CHECK_FORMATTER_KIND_MASK(VAL)((m_formatter_kind_mask & (VAL)) == (VAL)) \
41 ((m_formatter_kind_mask & (VAL)) == (VAL))
42
43using namespace lldb;
44using namespace lldb_private;
45
46class ScriptAddOptions {
47public:
48 TypeSummaryImpl::Flags m_flags;
49 StringList m_target_types;
50 bool m_regex;
51 ConstString m_name;
52 std::string m_category;
53
54 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
55 ConstString name, std::string catg)
56 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
57
58 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
59};
60
61class SynthAddOptions {
62public:
63 bool m_skip_pointers;
64 bool m_skip_references;
65 bool m_cascade;
66 bool m_regex;
67 StringList m_target_types;
68 std::string m_category;
69
70 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
71 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
72 m_regex(regx), m_target_types(), m_category(catg) {}
73
74 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
75};
76
77static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
78 CommandReturnObject &result) {
79 if (command.empty())
80 return false;
81
82 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
83 if (entry.value().ref() != "unsigned")
84 continue;
85 auto next = command.entries()[entry.index() + 1].ref();
86 if (next == "int" || next == "short" || next == "char" || next == "long") {
87 result.AppendWarningWithFormat(
88 "unsigned %s being treated as two types. if you meant the combined "
89 "type "
90 "name use quotes, as in \"unsigned %s\"\n",
91 next.str().c_str(), next.str().c_str());
92 return true;
93 }
94 }
95 return false;
96}
97
98#define LLDB_OPTIONS_type_summary_add
99#include "CommandOptions.inc"
100
101class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
102 public IOHandlerDelegateMultiline {
103private:
104 class CommandOptions : public Options {
105 public:
106 CommandOptions(CommandInterpreter &interpreter) : Options() {}
107
108 ~CommandOptions() override = default;
109
110 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
111 ExecutionContext *execution_context) override;
112
113 void OptionParsingStarting(ExecutionContext *execution_context) override;
114
115 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116 return llvm::makeArrayRef(g_type_summary_add_options);
117 }
118
119 // Instance variables to hold the values for command options.
120
121 TypeSummaryImpl::Flags m_flags;
122 bool m_regex;
123 std::string m_format_string;
124 ConstString m_name;
125 std::string m_python_script;
126 std::string m_python_function;
127 bool m_is_add_script;
128 std::string m_category;
129 };
130
131 CommandOptions m_options;
132
133 Options *GetOptions() override { return &m_options; }
134
135 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
136
137 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
138
139public:
140 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
141
142 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
143
144 ~CommandObjectTypeSummaryAdd() override = default;
145
146 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
147 static const char *g_summary_addreader_instructions =
148 "Enter your Python command(s). Type 'DONE' to end.\n"
149 "def function (valobj,internal_dict):\n"
150 " \"\"\"valobj: an SBValue which you want to provide a summary "
151 "for\n"
152 " internal_dict: an LLDB support object not to be used\"\"\"\n";
153
154 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
155 if (output_sp && interactive) {
156 output_sp->PutCString(g_summary_addreader_instructions);
157 output_sp->Flush();
158 }
159 }
160
161 void IOHandlerInputComplete(IOHandler &io_handler,
162 std::string &data) override {
163 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
164
165#if LLDB_ENABLE_PYTHON1
166 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
167 if (interpreter) {
168 StringList lines;
169 lines.SplitIntoLines(data);
170 if (lines.GetSize() > 0) {
171 ScriptAddOptions *options_ptr =
172 ((ScriptAddOptions *)io_handler.GetUserData());
173 if (options_ptr) {
174 ScriptAddOptions::SharedPointer options(
175 options_ptr); // this will ensure that we get rid of the pointer
176 // when going out of scope
177
178 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
179 if (interpreter) {
180 std::string funct_name_str;
181 if (interpreter->GenerateTypeScriptFunction(lines,
182 funct_name_str)) {
183 if (funct_name_str.empty()) {
184 error_sp->Printf("unable to obtain a valid function name from "
185 "the script interpreter.\n");
186 error_sp->Flush();
187 } else {
188 // now I have a valid function name, let's add this as script
189 // for every type in the list
190
191 TypeSummaryImplSP script_format;
192 script_format = std::make_shared<ScriptSummaryFormat>(
193 options->m_flags, funct_name_str.c_str(),
194 lines.CopyList(" ").c_str());
195
196 Status error;
197
198 for (const std::string &type_name : options->m_target_types) {
199 CommandObjectTypeSummaryAdd::AddSummary(
200 ConstString(type_name), script_format,
201 (options->m_regex
202 ? CommandObjectTypeSummaryAdd::eRegexSummary
203 : CommandObjectTypeSummaryAdd::eRegularSummary),
204 options->m_category, &error);
205 if (error.Fail()) {
206 error_sp->Printf("error: %s", error.AsCString());
207 error_sp->Flush();
208 }
209 }
210
211 if (options->m_name) {
212 CommandObjectTypeSummaryAdd::AddSummary(
213 options->m_name, script_format,
214 CommandObjectTypeSummaryAdd::eNamedSummary,
215 options->m_category, &error);
216 if (error.Fail()) {
217 CommandObjectTypeSummaryAdd::AddSummary(
218 options->m_name, script_format,
219 CommandObjectTypeSummaryAdd::eNamedSummary,
220 options->m_category, &error);
221 if (error.Fail()) {
222 error_sp->Printf("error: %s", error.AsCString());
223 error_sp->Flush();
224 }
225 } else {
226 error_sp->Printf("error: %s", error.AsCString());
227 error_sp->Flush();
228 }
229 } else {
230 if (error.AsCString()) {
231 error_sp->Printf("error: %s", error.AsCString());
232 error_sp->Flush();
233 }
234 }
235 }
236 } else {
237 error_sp->Printf("error: unable to generate a function.\n");
238 error_sp->Flush();
239 }
240 } else {
241 error_sp->Printf("error: no script interpreter.\n");
242 error_sp->Flush();
243 }
244 } else {
245 error_sp->Printf("error: internal synchronization information "
246 "missing or invalid.\n");
247 error_sp->Flush();
248 }
249 } else {
250 error_sp->Printf("error: empty function, didn't add python command.\n");
251 error_sp->Flush();
252 }
253 } else {
254 error_sp->Printf(
255 "error: script interpreter missing, didn't add python command.\n");
256 error_sp->Flush();
257 }
258#endif
259 io_handler.SetIsDone(true);
260 }
261
262 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
263 SummaryFormatType type, std::string category,
264 Status *error = nullptr);
265
266protected:
267 bool DoExecute(Args &command, CommandReturnObject &result) override;
268};
269
270static const char *g_synth_addreader_instructions =
271 "Enter your Python command(s). Type 'DONE' to end.\n"
272 "You must define a Python class with these methods:\n"
273 " def __init__(self, valobj, internal_dict):\n"
274 " def num_children(self):\n"
275 " def get_child_at_index(self, index):\n"
276 " def get_child_index(self, name):\n"
277 " def update(self):\n"
278 " '''Optional'''\n"
279 "class synthProvider:\n";
280
281#define LLDB_OPTIONS_type_synth_add
282#include "CommandOptions.inc"
283
284class CommandObjectTypeSynthAdd : public CommandObjectParsed,
285 public IOHandlerDelegateMultiline {
286private:
287 class CommandOptions : public Options {
288 public:
289 CommandOptions() : Options() {}
290
291 ~CommandOptions() override = default;
292
293 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
294 ExecutionContext *execution_context) override {
295 Status error;
296 const int short_option = m_getopt_table[option_idx].val;
297 bool success;
298
299 switch (short_option) {
300 case 'C':
301 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
302 if (!success)
303 error.SetErrorStringWithFormat("invalid value for cascade: %s",
304 option_arg.str().c_str());
305 break;
306 case 'P':
307 handwrite_python = true;
308 break;
309 case 'l':
310 m_class_name = std::string(option_arg);
311 is_class_based = true;
312 break;
313 case 'p':
314 m_skip_pointers = true;
315 break;
316 case 'r':
317 m_skip_references = true;
318 break;
319 case 'w':
320 m_category = std::string(option_arg);
321 break;
322 case 'x':
323 m_regex = true;
324 break;
325 default:
326 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 326)
;
327 }
328
329 return error;
330 }
331
332 void OptionParsingStarting(ExecutionContext *execution_context) override {
333 m_cascade = true;
334 m_class_name = "";
335 m_skip_pointers = false;
336 m_skip_references = false;
337 m_category = "default";
338 is_class_based = false;
339 handwrite_python = false;
340 m_regex = false;
341 }
342
343 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
344 return llvm::makeArrayRef(g_type_synth_add_options);
345 }
346
347 // Instance variables to hold the values for command options.
348
349 bool m_cascade;
350 bool m_skip_references;
351 bool m_skip_pointers;
352 std::string m_class_name;
353 bool m_input_python;
354 std::string m_category;
355 bool is_class_based;
356 bool handwrite_python;
357 bool m_regex;
358 };
359
360 CommandOptions m_options;
361
362 Options *GetOptions() override { return &m_options; }
363
364 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
365
366 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
367
368protected:
369 bool DoExecute(Args &command, CommandReturnObject &result) override {
370 WarnOnPotentialUnquotedUnsignedType(command, result);
371
372 if (m_options.handwrite_python)
1
Assuming field 'handwrite_python' is true
2
Taking true branch
373 return Execute_HandwritePython(command, result);
3
Calling 'CommandObjectTypeSynthAdd::Execute_HandwritePython'
374 else if (m_options.is_class_based)
375 return Execute_PythonClass(command, result);
376 else {
377 result.AppendError("must either provide a children list, a Python class "
378 "name, or use -P and type a Python class "
379 "line-by-line");
380 return false;
381 }
382 }
383
384 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
385 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
386 if (output_sp && interactive) {
387 output_sp->PutCString(g_synth_addreader_instructions);
388 output_sp->Flush();
389 }
390 }
391
392 void IOHandlerInputComplete(IOHandler &io_handler,
393 std::string &data) override {
394 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
395
396#if LLDB_ENABLE_PYTHON1
397 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
398 if (interpreter) {
399 StringList lines;
400 lines.SplitIntoLines(data);
401 if (lines.GetSize() > 0) {
402 SynthAddOptions *options_ptr =
403 ((SynthAddOptions *)io_handler.GetUserData());
404 if (options_ptr) {
405 SynthAddOptions::SharedPointer options(
406 options_ptr); // this will ensure that we get rid of the pointer
407 // when going out of scope
408
409 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
410 if (interpreter) {
411 std::string class_name_str;
412 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
413 if (class_name_str.empty()) {
414 error_sp->Printf(
415 "error: unable to obtain a proper name for the class.\n");
416 error_sp->Flush();
417 } else {
418 // everything should be fine now, let's add the synth provider
419 // class
420
421 SyntheticChildrenSP synth_provider;
422 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
423 SyntheticChildren::Flags()
424 .SetCascades(options->m_cascade)
425 .SetSkipPointers(options->m_skip_pointers)
426 .SetSkipReferences(options->m_skip_references),
427 class_name_str.c_str());
428
429 lldb::TypeCategoryImplSP category;
430 DataVisualization::Categories::GetCategory(
431 ConstString(options->m_category.c_str()), category);
432
433 Status error;
434
435 for (const std::string &type_name : options->m_target_types) {
436 if (!type_name.empty()) {
437 if (!CommandObjectTypeSynthAdd::AddSynth(
438 ConstString(type_name), synth_provider,
439 options->m_regex
440 ? CommandObjectTypeSynthAdd::eRegexSynth
441 : CommandObjectTypeSynthAdd::eRegularSynth,
442 options->m_category, &error)) {
443 error_sp->Printf("error: %s\n", error.AsCString());
444 error_sp->Flush();
445 break;
446 }
447 } else {
448 error_sp->Printf("error: invalid type name.\n");
449 error_sp->Flush();
450 break;
451 }
452 }
453 }
454 } else {
455 error_sp->Printf("error: unable to generate a class.\n");
456 error_sp->Flush();
457 }
458 } else {
459 error_sp->Printf("error: no script interpreter.\n");
460 error_sp->Flush();
461 }
462 } else {
463 error_sp->Printf("error: internal synchronization data missing.\n");
464 error_sp->Flush();
465 }
466 } else {
467 error_sp->Printf("error: empty function, didn't add python command.\n");
468 error_sp->Flush();
469 }
470 } else {
471 error_sp->Printf(
472 "error: script interpreter missing, didn't add python command.\n");
473 error_sp->Flush();
474 }
475
476#endif
477 io_handler.SetIsDone(true);
478 }
479
480public:
481 enum SynthFormatType { eRegularSynth, eRegexSynth };
482
483 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
484
485 ~CommandObjectTypeSynthAdd() override = default;
486
487 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
488 SynthFormatType type, std::string category_name,
489 Status *error);
490};
491
492// CommandObjectTypeFormatAdd
493
494#define LLDB_OPTIONS_type_format_add
495#include "CommandOptions.inc"
496
497class CommandObjectTypeFormatAdd : public CommandObjectParsed {
498private:
499 class CommandOptions : public OptionGroup {
500 public:
501 CommandOptions() : OptionGroup() {}
502
503 ~CommandOptions() override = default;
504
505 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
506 return llvm::makeArrayRef(g_type_format_add_options);
507 }
508
509 void OptionParsingStarting(ExecutionContext *execution_context) override {
510 m_cascade = true;
511 m_skip_pointers = false;
512 m_skip_references = false;
513 m_regex = false;
514 m_category.assign("default");
515 m_custom_type_name.clear();
516 }
517
518 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
519 ExecutionContext *execution_context) override {
520 Status error;
521 const int short_option =
522 g_type_format_add_options[option_idx].short_option;
523 bool success;
524
525 switch (short_option) {
526 case 'C':
527 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
528 if (!success)
529 error.SetErrorStringWithFormat("invalid value for cascade: %s",
530 option_value.str().c_str());
531 break;
532 case 'p':
533 m_skip_pointers = true;
534 break;
535 case 'w':
536 m_category.assign(std::string(option_value));
537 break;
538 case 'r':
539 m_skip_references = true;
540 break;
541 case 'x':
542 m_regex = true;
543 break;
544 case 't':
545 m_custom_type_name.assign(std::string(option_value));
546 break;
547 default:
548 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 548)
;
549 }
550
551 return error;
552 }
553
554 // Instance variables to hold the values for command options.
555
556 bool m_cascade;
557 bool m_skip_references;
558 bool m_skip_pointers;
559 bool m_regex;
560 std::string m_category;
561 std::string m_custom_type_name;
562 };
563
564 OptionGroupOptions m_option_group;
565 OptionGroupFormat m_format_options;
566 CommandOptions m_command_options;
567
568 Options *GetOptions() override { return &m_option_group; }
569
570public:
571 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
572 : CommandObjectParsed(interpreter, "type format add",
573 "Add a new formatting style for a type.", nullptr),
574 m_option_group(), m_format_options(eFormatInvalid),
575 m_command_options() {
576 CommandArgumentEntry type_arg;
577 CommandArgumentData type_style_arg;
578
579 type_style_arg.arg_type = eArgTypeName;
580 type_style_arg.arg_repetition = eArgRepeatPlus;
581
582 type_arg.push_back(type_style_arg);
583
584 m_arguments.push_back(type_arg);
585
586 SetHelpLong(
587 R"(
588The following examples of 'type format add' refer to this code snippet for context:
589
590 typedef int Aint;
591 typedef float Afloat;
592 typedef Aint Bint;
593 typedef Afloat Bfloat;
594
595 Aint ix = 5;
596 Bint iy = 5;
597
598 Afloat fx = 3.14;
599 BFloat fy = 3.14;
600
601Adding default formatting:
602
603(lldb) type format add -f hex AInt
604(lldb) frame variable iy
605
606)"
607 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
608the one for Aint is used instead."
609 R"(
610
611To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
612
613
614(lldb) type format add -f hex -C no AInt
615
616Similar reasoning applies to this:
617
618(lldb) type format add -f hex -C no float -p
619
620)"
621 " All float values and float references are now formatted as hexadecimal, but not \
622pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
623
624 // Add the "--format" to all options groups
625 m_option_group.Append(&m_format_options,
626 OptionGroupFormat::OPTION_GROUP_FORMAT,
627 LLDB_OPT_SET_1(1U << 0));
628 m_option_group.Append(&m_command_options);
629 m_option_group.Finalize();
630 }
631
632 ~CommandObjectTypeFormatAdd() override = default;
633
634protected:
635 bool DoExecute(Args &command, CommandReturnObject &result) override {
636 const size_t argc = command.GetArgumentCount();
637
638 if (argc < 1) {
639 result.AppendErrorWithFormat("%s takes one or more args.\n",
640 m_cmd_name.c_str());
641 return false;
642 }
643
644 const Format format = m_format_options.GetFormat();
645 if (format == eFormatInvalid &&
646 m_command_options.m_custom_type_name.empty()) {
647 result.AppendErrorWithFormat("%s needs a valid format.\n",
648 m_cmd_name.c_str());
649 return false;
650 }
651
652 TypeFormatImplSP entry;
653
654 if (m_command_options.m_custom_type_name.empty())
655 entry = std::make_shared<TypeFormatImpl_Format>(
656 format, TypeFormatImpl::Flags()
657 .SetCascades(m_command_options.m_cascade)
658 .SetSkipPointers(m_command_options.m_skip_pointers)
659 .SetSkipReferences(m_command_options.m_skip_references));
660 else
661 entry = std::make_shared<TypeFormatImpl_EnumType>(
662 ConstString(m_command_options.m_custom_type_name.c_str()),
663 TypeFormatImpl::Flags()
664 .SetCascades(m_command_options.m_cascade)
665 .SetSkipPointers(m_command_options.m_skip_pointers)
666 .SetSkipReferences(m_command_options.m_skip_references));
667
668 // now I have a valid format, let's add it to every type
669
670 TypeCategoryImplSP category_sp;
671 DataVisualization::Categories::GetCategory(
672 ConstString(m_command_options.m_category), category_sp);
673 if (!category_sp)
674 return false;
675
676 WarnOnPotentialUnquotedUnsignedType(command, result);
677
678 for (auto &arg_entry : command.entries()) {
679 if (arg_entry.ref().empty()) {
680 result.AppendError("empty typenames not allowed");
681 return false;
682 }
683
684 ConstString typeCS(arg_entry.ref());
685 if (m_command_options.m_regex) {
686 RegularExpression typeRX(arg_entry.ref());
687 if (!typeRX.IsValid()) {
688 result.AppendError(
689 "regex format error (maybe this is not really a regex?)");
690 return false;
691 }
692 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
693 category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX),
694 entry);
695 } else
696 category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry);
697 }
698
699 result.SetStatus(eReturnStatusSuccessFinishNoResult);
700 return result.Succeeded();
701 }
702};
703
704#define LLDB_OPTIONS_type_formatter_delete
705#include "CommandOptions.inc"
706
707class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
708protected:
709 class CommandOptions : public Options {
710 public:
711 CommandOptions() : Options() {}
712
713 ~CommandOptions() override = default;
714
715 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
716 ExecutionContext *execution_context) override {
717 Status error;
718 const int short_option = m_getopt_table[option_idx].val;
719
720 switch (short_option) {
721 case 'a':
722 m_delete_all = true;
723 break;
724 case 'w':
725 m_category = std::string(option_arg);
726 break;
727 case 'l':
728 m_language = Language::GetLanguageTypeFromString(option_arg);
729 break;
730 default:
731 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 731)
;
732 }
733
734 return error;
735 }
736
737 void OptionParsingStarting(ExecutionContext *execution_context) override {
738 m_delete_all = false;
739 m_category = "default";
740 m_language = lldb::eLanguageTypeUnknown;
741 }
742
743 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
744 return llvm::makeArrayRef(g_type_formatter_delete_options);
745 }
746
747 // Instance variables to hold the values for command options.
748
749 bool m_delete_all;
750 std::string m_category;
751 lldb::LanguageType m_language;
752 };
753
754 CommandOptions m_options;
755 uint32_t m_formatter_kind_mask;
756
757 Options *GetOptions() override { return &m_options; }
758
759public:
760 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
761 uint32_t formatter_kind_mask,
762 const char *name, const char *help)
763 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
764 m_formatter_kind_mask(formatter_kind_mask) {
765 CommandArgumentEntry type_arg;
766 CommandArgumentData type_style_arg;
767
768 type_style_arg.arg_type = eArgTypeName;
769 type_style_arg.arg_repetition = eArgRepeatPlain;
770
771 type_arg.push_back(type_style_arg);
772
773 m_arguments.push_back(type_arg);
774 }
775
776 ~CommandObjectTypeFormatterDelete() override = default;
777
778 void
779 HandleArgumentCompletion(CompletionRequest &request,
780 OptionElementVector &opt_element_vector) override {
781 if (request.GetCursorIndex())
782 return;
783
784 DataVisualization::Categories::ForEach(
785 [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
786 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemValue)((m_formatter_kind_mask & (eFormatCategoryItemValue)) == (
eFormatCategoryItemValue))
)
787 category_sp->GetTypeFormatsContainer()->AutoComplete(request);
788 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexValue)((m_formatter_kind_mask & (eFormatCategoryItemRegexValue)
) == (eFormatCategoryItemRegexValue))
)
789 category_sp->GetRegexTypeFormatsContainer()->AutoComplete(request);
790
791 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSummary)((m_formatter_kind_mask & (eFormatCategoryItemSummary)) ==
(eFormatCategoryItemSummary))
)
792 category_sp->GetTypeSummariesContainer()->AutoComplete(request);
793 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSummary)((m_formatter_kind_mask & (eFormatCategoryItemRegexSummary
)) == (eFormatCategoryItemRegexSummary))
)
794 category_sp->GetRegexTypeSummariesContainer()->AutoComplete(
795 request);
796
797 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemFilter)((m_formatter_kind_mask & (eFormatCategoryItemFilter)) ==
(eFormatCategoryItemFilter))
)
798 category_sp->GetTypeFiltersContainer()->AutoComplete(request);
799 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexFilter)((m_formatter_kind_mask & (eFormatCategoryItemRegexFilter
)) == (eFormatCategoryItemRegexFilter))
)
800 category_sp->GetRegexTypeFiltersContainer()->AutoComplete(request);
801
802 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSynth)((m_formatter_kind_mask & (eFormatCategoryItemSynth)) == (
eFormatCategoryItemSynth))
)
803 category_sp->GetTypeSyntheticsContainer()->AutoComplete(request);
804 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSynth)((m_formatter_kind_mask & (eFormatCategoryItemRegexSynth)
) == (eFormatCategoryItemRegexSynth))
)
805 category_sp->GetRegexTypeSyntheticsContainer()->AutoComplete(
806 request);
807 return true;
808 });
809 }
810
811protected:
812 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
813
814 bool DoExecute(Args &command, CommandReturnObject &result) override {
815 const size_t argc = command.GetArgumentCount();
816
817 if (argc != 1) {
818 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
819 return false;
820 }
821
822 const char *typeA = command.GetArgumentAtIndex(0);
823 ConstString typeCS(typeA);
824
825 if (!typeCS) {
826 result.AppendError("empty typenames not allowed");
827 return false;
828 }
829
830 if (m_options.m_delete_all) {
831 DataVisualization::Categories::ForEach(
832 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
833 category_sp->Delete(typeCS, m_formatter_kind_mask);
834 return true;
835 });
836 result.SetStatus(eReturnStatusSuccessFinishNoResult);
837 return result.Succeeded();
838 }
839
840 bool delete_category = false;
841 bool extra_deletion = false;
842
843 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
844 lldb::TypeCategoryImplSP category;
845 DataVisualization::Categories::GetCategory(m_options.m_language,
846 category);
847 if (category)
848 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
849 extra_deletion = FormatterSpecificDeletion(typeCS);
850 } else {
851 lldb::TypeCategoryImplSP category;
852 DataVisualization::Categories::GetCategory(
853 ConstString(m_options.m_category.c_str()), category);
854 if (category)
855 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
856 extra_deletion = FormatterSpecificDeletion(typeCS);
857 }
858
859 if (delete_category || extra_deletion) {
860 result.SetStatus(eReturnStatusSuccessFinishNoResult);
861 return result.Succeeded();
862 } else {
863 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
864 return false;
865 }
866 }
867};
868
869#define LLDB_OPTIONS_type_formatter_clear
870#include "CommandOptions.inc"
871
872class CommandObjectTypeFormatterClear : public CommandObjectParsed {
873private:
874 class CommandOptions : public Options {
875 public:
876 CommandOptions() : Options() {}
877
878 ~CommandOptions() override = default;
879
880 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
881 ExecutionContext *execution_context) override {
882 Status error;
883 const int short_option = m_getopt_table[option_idx].val;
884
885 switch (short_option) {
886 case 'a':
887 m_delete_all = true;
888 break;
889 default:
890 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 890)
;
891 }
892
893 return error;
894 }
895
896 void OptionParsingStarting(ExecutionContext *execution_context) override {
897 m_delete_all = false;
898 }
899
900 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
901 return llvm::makeArrayRef(g_type_formatter_clear_options);
902 }
903
904 // Instance variables to hold the values for command options.
905 bool m_delete_all;
906 };
907
908 CommandOptions m_options;
909 uint32_t m_formatter_kind_mask;
910
911 Options *GetOptions() override { return &m_options; }
912
913public:
914 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
915 uint32_t formatter_kind_mask,
916 const char *name, const char *help)
917 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
918 m_formatter_kind_mask(formatter_kind_mask) {}
919
920 ~CommandObjectTypeFormatterClear() override = default;
921
922protected:
923 virtual void FormatterSpecificDeletion() {}
924
925 bool DoExecute(Args &command, CommandReturnObject &result) override {
926 if (m_options.m_delete_all) {
927 DataVisualization::Categories::ForEach(
928 [this](const TypeCategoryImplSP &category_sp) -> bool {
929 category_sp->Clear(m_formatter_kind_mask);
930 return true;
931 });
932 } else {
933 lldb::TypeCategoryImplSP category;
934 if (command.GetArgumentCount() > 0) {
935 const char *cat_name = command.GetArgumentAtIndex(0);
936 ConstString cat_nameCS(cat_name);
937 DataVisualization::Categories::GetCategory(cat_nameCS, category);
938 } else {
939 DataVisualization::Categories::GetCategory(ConstString(nullptr),
940 category);
941 }
942 category->Clear(m_formatter_kind_mask);
943 }
944
945 FormatterSpecificDeletion();
946
947 result.SetStatus(eReturnStatusSuccessFinishResult);
948 return result.Succeeded();
949 }
950};
951
952// CommandObjectTypeFormatDelete
953
954class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
955public:
956 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
957 : CommandObjectTypeFormatterDelete(
958 interpreter,
959 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
960 "type format delete",
961 "Delete an existing formatting style for a type.") {}
962
963 ~CommandObjectTypeFormatDelete() override = default;
964};
965
966// CommandObjectTypeFormatClear
967
968class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
969public:
970 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
971 : CommandObjectTypeFormatterClear(
972 interpreter,
973 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
974 "type format clear", "Delete all existing format styles.") {}
975};
976
977#define LLDB_OPTIONS_type_formatter_list
978#include "CommandOptions.inc"
979
980template <typename FormatterType>
981class CommandObjectTypeFormatterList : public CommandObjectParsed {
982 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
983
984 class CommandOptions : public Options {
985 public:
986 CommandOptions()
987 : Options(), m_category_regex("", ""),
988 m_category_language(lldb::eLanguageTypeUnknown,
989 lldb::eLanguageTypeUnknown) {}
990
991 ~CommandOptions() override = default;
992
993 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
994 ExecutionContext *execution_context) override {
995 Status error;
996 const int short_option = m_getopt_table[option_idx].val;
997 switch (short_option) {
998 case 'w':
999 m_category_regex.SetCurrentValue(option_arg);
1000 m_category_regex.SetOptionWasSet();
1001 break;
1002 case 'l':
1003 error = m_category_language.SetValueFromString(option_arg);
1004 if (error.Success())
1005 m_category_language.SetOptionWasSet();
1006 break;
1007 default:
1008 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 1008)
;
1009 }
1010
1011 return error;
1012 }
1013
1014 void OptionParsingStarting(ExecutionContext *execution_context) override {
1015 m_category_regex.Clear();
1016 m_category_language.Clear();
1017 }
1018
1019 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1020 return llvm::makeArrayRef(g_type_formatter_list_options);
1021 }
1022
1023 // Instance variables to hold the values for command options.
1024
1025 OptionValueString m_category_regex;
1026 OptionValueLanguage m_category_language;
1027 };
1028
1029 CommandOptions m_options;
1030
1031 Options *GetOptions() override { return &m_options; }
1032
1033public:
1034 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1035 const char *name, const char *help)
1036 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1037 CommandArgumentEntry type_arg;
1038 CommandArgumentData type_style_arg;
1039
1040 type_style_arg.arg_type = eArgTypeName;
1041 type_style_arg.arg_repetition = eArgRepeatOptional;
1042
1043 type_arg.push_back(type_style_arg);
1044
1045 m_arguments.push_back(type_arg);
1046 }
1047
1048 ~CommandObjectTypeFormatterList() override = default;
1049
1050protected:
1051 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1052 return false;
1053 }
1054
1055 bool DoExecute(Args &command, CommandReturnObject &result) override {
1056 const size_t argc = command.GetArgumentCount();
1057
1058 std::unique_ptr<RegularExpression> category_regex;
1059 std::unique_ptr<RegularExpression> formatter_regex;
1060
1061 if (m_options.m_category_regex.OptionWasSet()) {
1062 category_regex = std::make_unique<RegularExpression>(
1063 m_options.m_category_regex.GetCurrentValueAsRef());
1064 if (!category_regex->IsValid()) {
1065 result.AppendErrorWithFormat(
1066 "syntax error in category regular expression '%s'",
1067 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1068 return false;
1069 }
1070 }
1071
1072 if (argc == 1) {
1073 const char *arg = command.GetArgumentAtIndex(0);
1074 formatter_regex = std::make_unique<RegularExpression>(arg);
1075 if (!formatter_regex->IsValid()) {
1076 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1077 arg);
1078 return false;
1079 }
1080 }
1081
1082 bool any_printed = false;
1083
1084 auto category_closure =
1085 [&result, &formatter_regex,
1086 &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1087 result.GetOutputStream().Printf(
1088 "-----------------------\nCategory: %s%s\n-----------------------\n",
1089 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1090
1091 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1092 foreach
1093 .SetExact([&result, &formatter_regex, &any_printed](
1094 const TypeMatcher &type_matcher,
1095 const FormatterSharedPointer &format_sp) -> bool {
1096 if (formatter_regex) {
1097 bool escape = true;
1098 if (type_matcher.CreatedBySameMatchString(
1099 ConstString(formatter_regex->GetText()))) {
1100 escape = false;
1101 } else if (formatter_regex->Execute(
1102 type_matcher.GetMatchString().GetStringRef())) {
1103 escape = false;
1104 }
1105
1106 if (escape)
1107 return true;
1108 }
1109
1110 any_printed = true;
1111 result.GetOutputStream().Printf(
1112 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1113 format_sp->GetDescription().c_str());
1114 return true;
1115 });
1116
1117 foreach
1118 .SetWithRegex([&result, &formatter_regex, &any_printed](
1119 const TypeMatcher &type_matcher,
1120 const FormatterSharedPointer &format_sp) -> bool {
1121 if (formatter_regex) {
1122 bool escape = true;
1123 if (type_matcher.CreatedBySameMatchString(
1124 ConstString(formatter_regex->GetText()))) {
1125 escape = false;
1126 } else if (formatter_regex->Execute(
1127 type_matcher.GetMatchString().GetStringRef())) {
1128 escape = false;
1129 }
1130
1131 if (escape)
1132 return true;
1133 }
1134
1135 any_printed = true;
1136 result.GetOutputStream().Printf(
1137 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1138 format_sp->GetDescription().c_str());
1139 return true;
1140 });
1141
1142 category->ForEach(foreach);
1143 };
1144
1145 if (m_options.m_category_language.OptionWasSet()) {
1146 lldb::TypeCategoryImplSP category_sp;
1147 DataVisualization::Categories::GetCategory(
1148 m_options.m_category_language.GetCurrentValue(), category_sp);
1149 if (category_sp)
1150 category_closure(category_sp);
1151 } else {
1152 DataVisualization::Categories::ForEach(
1153 [&category_regex, &category_closure](
1154 const lldb::TypeCategoryImplSP &category) -> bool {
1155 if (category_regex) {
1156 bool escape = true;
1157 if (category->GetName() == category_regex->GetText()) {
1158 escape = false;
1159 } else if (category_regex->Execute(category->GetName())) {
1160 escape = false;
1161 }
1162
1163 if (escape)
1164 return true;
1165 }
1166
1167 category_closure(category);
1168
1169 return true;
1170 });
1171
1172 any_printed = FormatterSpecificList(result) | any_printed;
1173 }
1174
1175 if (any_printed)
1176 result.SetStatus(eReturnStatusSuccessFinishResult);
1177 else {
1178 result.GetOutputStream().PutCString("no matching results found.\n");
1179 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1180 }
1181 return result.Succeeded();
1182 }
1183};
1184
1185// CommandObjectTypeFormatList
1186
1187class CommandObjectTypeFormatList
1188 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1189public:
1190 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1191 : CommandObjectTypeFormatterList(interpreter, "type format list",
1192 "Show a list of current formats.") {}
1193};
1194
1195Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1196 uint32_t option_idx, llvm::StringRef option_arg,
1197 ExecutionContext *execution_context) {
1198 Status error;
1199 const int short_option = m_getopt_table[option_idx].val;
1200 bool success;
1201
1202 switch (short_option) {
1203 case 'C':
1204 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1205 if (!success)
1206 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1207 option_arg.str().c_str());
1208 break;
1209 case 'e':
1210 m_flags.SetDontShowChildren(false);
1211 break;
1212 case 'h':
1213 m_flags.SetHideEmptyAggregates(true);
1214 break;
1215 case 'v':
1216 m_flags.SetDontShowValue(true);
1217 break;
1218 case 'c':
1219 m_flags.SetShowMembersOneLiner(true);
1220 break;
1221 case 's':
1222 m_format_string = std::string(option_arg);
1223 break;
1224 case 'p':
1225 m_flags.SetSkipPointers(true);
1226 break;
1227 case 'r':
1228 m_flags.SetSkipReferences(true);
1229 break;
1230 case 'x':
1231 m_regex = true;
1232 break;
1233 case 'n':
1234 m_name.SetString(option_arg);
1235 break;
1236 case 'o':
1237 m_python_script = std::string(option_arg);
1238 m_is_add_script = true;
1239 break;
1240 case 'F':
1241 m_python_function = std::string(option_arg);
1242 m_is_add_script = true;
1243 break;
1244 case 'P':
1245 m_is_add_script = true;
1246 break;
1247 case 'w':
1248 m_category = std::string(option_arg);
1249 break;
1250 case 'O':
1251 m_flags.SetHideItemNames(true);
1252 break;
1253 default:
1254 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 1254)
;
1255 }
1256
1257 return error;
1258}
1259
1260void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1261 ExecutionContext *execution_context) {
1262 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1263 m_flags.SetShowMembersOneLiner(false)
1264 .SetSkipPointers(false)
1265 .SetSkipReferences(false)
1266 .SetHideItemNames(false);
1267
1268 m_regex = false;
1269 m_name.Clear();
1270 m_python_script = "";
1271 m_python_function = "";
1272 m_format_string = "";
1273 m_is_add_script = false;
1274 m_category = "default";
1275}
1276
1277#if LLDB_ENABLE_PYTHON1
1278
1279bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1280 Args &command, CommandReturnObject &result) {
1281 const size_t argc = command.GetArgumentCount();
1282
1283 if (argc < 1 && !m_options.m_name) {
1284 result.AppendErrorWithFormat("%s takes one or more args.\n",
1285 m_cmd_name.c_str());
1286 return false;
1287 }
1288
1289 TypeSummaryImplSP script_format;
1290
1291 if (!m_options.m_python_function
1292 .empty()) // we have a Python function ready to use
1293 {
1294 const char *funct_name = m_options.m_python_function.c_str();
1295 if (!funct_name || !funct_name[0]) {
1296 result.AppendError("function name empty.\n");
1297 return false;
1298 }
1299
1300 std::string code =
1301 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1302
1303 script_format = std::make_shared<ScriptSummaryFormat>(
1304 m_options.m_flags, funct_name, code.c_str());
1305
1306 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1307
1308 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1309 result.AppendWarningWithFormat(
1310 "The provided function \"%s\" does not exist - "
1311 "please define it before attempting to use this summary.\n",
1312 funct_name);
1313 } else if (!m_options.m_python_script
1314 .empty()) // we have a quick 1-line script, just use it
1315 {
1316 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1317 if (!interpreter) {
1318 result.AppendError("script interpreter missing - unable to generate "
1319 "function wrapper.\n");
1320 return false;
1321 }
1322 StringList funct_sl;
1323 funct_sl << m_options.m_python_script.c_str();
1324 std::string funct_name_str;
1325 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1326 result.AppendError("unable to generate function wrapper.\n");
1327 return false;
1328 }
1329 if (funct_name_str.empty()) {
1330 result.AppendError(
1331 "script interpreter failed to generate a valid function name.\n");
1332 return false;
1333 }
1334
1335 std::string code = " " + m_options.m_python_script;
1336
1337 script_format = std::make_shared<ScriptSummaryFormat>(
1338 m_options.m_flags, funct_name_str.c_str(), code.c_str());
1339 } else {
1340 // Use an IOHandler to grab Python code from the user
1341 ScriptAddOptions *options =
1342 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1343 m_options.m_name, m_options.m_category);
1344
1345 for (auto &entry : command.entries()) {
1346 if (entry.ref().empty()) {
1347 result.AppendError("empty typenames not allowed");
1348 return false;
1349 }
1350
1351 options->m_target_types << std::string(entry.ref());
1352 }
1353
1354 m_interpreter.GetPythonCommandsFromIOHandler(
1355 " ", // Prompt
1356 *this, // IOHandlerDelegate
1357 options); // Baton for the "io_handler" that will be passed back into
1358 // our IOHandlerDelegate functions
1359 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1360
1361 return result.Succeeded();
1362 }
1363
1364 // if I am here, script_format must point to something good, so I can add
1365 // that as a script summary to all interested parties
1366
1367 Status error;
1368
1369 for (auto &entry : command.entries()) {
1370 CommandObjectTypeSummaryAdd::AddSummary(
1371 ConstString(entry.ref()), script_format,
1372 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1373 m_options.m_category, &error);
1374 if (error.Fail()) {
1375 result.AppendError(error.AsCString());
1376 return false;
1377 }
1378 }
1379
1380 if (m_options.m_name) {
1381 AddSummary(m_options.m_name, script_format, eNamedSummary,
1382 m_options.m_category, &error);
1383 if (error.Fail()) {
1384 result.AppendError(error.AsCString());
1385 result.AppendError("added to types, but not given a name");
1386 return false;
1387 }
1388 }
1389
1390 return result.Succeeded();
1391}
1392
1393#endif
1394
1395bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1396 Args &command, CommandReturnObject &result) {
1397 const size_t argc = command.GetArgumentCount();
1398
1399 if (argc < 1 && !m_options.m_name) {
1400 result.AppendErrorWithFormat("%s takes one or more args.\n",
1401 m_cmd_name.c_str());
1402 return false;
1403 }
1404
1405 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1406 m_options.m_format_string.empty()) {
1407 result.AppendError("empty summary strings not allowed");
1408 return false;
1409 }
1410
1411 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1412 ? ""
1413 : m_options.m_format_string.c_str());
1414
1415 // ${var%S} is an endless recursion, prevent it
1416 if (strcmp(format_cstr, "${var%S}") == 0) {
1417 result.AppendError("recursive summary not allowed");
1418 return false;
1419 }
1420
1421 std::unique_ptr<StringSummaryFormat> string_format(
1422 new StringSummaryFormat(m_options.m_flags, format_cstr));
1423 if (!string_format) {
1424 result.AppendError("summary creation failed");
1425 return false;
1426 }
1427 if (string_format->m_error.Fail()) {
1428 result.AppendErrorWithFormat("syntax error: %s",
1429 string_format->m_error.AsCString("<unknown>"));
1430 return false;
1431 }
1432 lldb::TypeSummaryImplSP entry(string_format.release());
1433
1434 // now I have a valid format, let's add it to every type
1435 Status error;
1436 for (auto &arg_entry : command.entries()) {
1437 if (arg_entry.ref().empty()) {
1438 result.AppendError("empty typenames not allowed");
1439 return false;
1440 }
1441 ConstString typeCS(arg_entry.ref());
1442
1443 AddSummary(typeCS, entry,
1444 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1445 m_options.m_category, &error);
1446
1447 if (error.Fail()) {
1448 result.AppendError(error.AsCString());
1449 return false;
1450 }
1451 }
1452
1453 if (m_options.m_name) {
1454 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1455 &error);
1456 if (error.Fail()) {
1457 result.AppendError(error.AsCString());
1458 result.AppendError("added to types, but not given a name");
1459 return false;
1460 }
1461 }
1462
1463 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1464 return result.Succeeded();
1465}
1466
1467CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1468 CommandInterpreter &interpreter)
1469 : CommandObjectParsed(interpreter, "type summary add",
1470 "Add a new summary style for a type.", nullptr),
1471 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1472 CommandArgumentEntry type_arg;
1473 CommandArgumentData type_style_arg;
1474
1475 type_style_arg.arg_type = eArgTypeName;
1476 type_style_arg.arg_repetition = eArgRepeatPlus;
1477
1478 type_arg.push_back(type_style_arg);
1479
1480 m_arguments.push_back(type_arg);
1481
1482 SetHelpLong(
1483 R"(
1484The following examples of 'type summary add' refer to this code snippet for context:
1485
1486 struct JustADemo
1487 {
1488 int* ptr;
1489 float value;
1490 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1491 };
1492 JustADemo demo_instance(42, 3.14);
1493
1494 typedef JustADemo NewDemo;
1495 NewDemo new_demo_instance(42, 3.14);
1496
1497(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1498
1499 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1500
1501(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1502
1503 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1504
1505)"
1506 "Alternatively, you could define formatting for all pointers to integers and \
1507rely on that when formatting JustADemo to obtain the same result:"
1508 R"(
1509
1510(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1511(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1512
1513)"
1514 "Type summaries are automatically applied to derived typedefs, so the examples \
1515above apply to both JustADemo and NewDemo. The cascade option can be used to \
1516suppress this behavior:"
1517 R"(
1518
1519(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1520
1521 The summary will now be used for values of JustADemo but not NewDemo.
1522
1523)"
1524 "By default summaries are shown for pointers and references to values of the \
1525specified type. To suppress formatting for pointers use the -p option, or apply \
1526the corresponding -r option to suppress formatting for references:"
1527 R"(
1528
1529(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1530
1531)"
1532 "One-line summaries including all fields in a type can be inferred without supplying an \
1533explicit summary string by passing the -c option:"
1534 R"(
1535
1536(lldb) type summary add -c JustADemo
1537(lldb) frame variable demo_instance
1538(ptr=<address>, value=3.14)
1539
1540)"
1541 "Type summaries normally suppress the nested display of individual fields. To \
1542supply a summary to supplement the default structure add the -e option:"
1543 R"(
1544
1545(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1546
1547)"
1548 "Now when displaying JustADemo values the int* is displayed, followed by the \
1549standard LLDB sequence of children, one per line:"
1550 R"(
1551
1552*ptr = 42 {
1553 ptr = <address>
1554 value = 3.14
1555}
1556
1557)"
1558 "You can also add summaries written in Python. These scripts use lldb public API to \
1559gather information from your variables and produce a meaningful summary. To start a \
1560multi-line script use the -P option. The function declaration will be displayed along with \
1561a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1562itself:"
1563 R"(
1564
1565(lldb) type summary add JustADemo -P
1566def function (valobj,internal_dict):
1567"""valobj: an SBValue which you want to provide a summary for
1568internal_dict: an LLDB support object not to be used"""
1569 value = valobj.GetChildMemberWithName('value');
1570 return 'My value is ' + value.GetValue();
1571 DONE
1572
1573Alternatively, the -o option can be used when providing a simple one-line Python script:
1574
1575(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1576}
1577
1578bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1579 CommandReturnObject &result) {
1580 WarnOnPotentialUnquotedUnsignedType(command, result);
1581
1582 if (m_options.m_is_add_script) {
1583#if LLDB_ENABLE_PYTHON1
1584 return Execute_ScriptSummary(command, result);
1585#else
1586 result.AppendError("python is disabled");
1587 return false;
1588#endif
1589 }
1590
1591 return Execute_StringSummary(command, result);
1592}
1593
1594static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1595 llvm::StringRef type_name_ref(type_name.GetStringRef());
1596
1597 if (type_name_ref.endswith("[]")) {
1598 std::string type_name_str(type_name.GetCString());
1599 type_name_str.resize(type_name_str.length() - 2);
1600 if (type_name_str.back() != ' ')
1601 type_name_str.append(" ?\\[[0-9]+\\]");
1602 else
1603 type_name_str.append("\\[[0-9]+\\]");
1604 type_name.SetCString(type_name_str.c_str());
1605 return true;
1606 }
1607 return false;
1608}
1609
1610bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1611 TypeSummaryImplSP entry,
1612 SummaryFormatType type,
1613 std::string category_name,
1614 Status *error) {
1615 lldb::TypeCategoryImplSP category;
1616 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1617 category);
1618
1619 if (type == eRegularSummary) {
1620 if (FixArrayTypeNameWithRegex(type_name))
1621 type = eRegexSummary;
1622 }
1623
1624 if (type == eRegexSummary) {
1625 RegularExpression typeRX(type_name.GetStringRef());
1626 if (!typeRX.IsValid()) {
1627 if (error)
1628 error->SetErrorString(
1629 "regex format error (maybe this is not really a regex?)");
1630 return false;
1631 }
1632
1633 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1634 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry);
1635
1636 return true;
1637 } else if (type == eNamedSummary) {
1638 // system named summaries do not exist (yet?)
1639 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1640 return true;
1641 } else {
1642 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry);
1643 return true;
1644 }
1645}
1646
1647// CommandObjectTypeSummaryDelete
1648
1649class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1650public:
1651 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1652 : CommandObjectTypeFormatterDelete(
1653 interpreter,
1654 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1655 "type summary delete", "Delete an existing summary for a type.") {}
1656
1657 ~CommandObjectTypeSummaryDelete() override = default;
1658
1659protected:
1660 bool FormatterSpecificDeletion(ConstString typeCS) override {
1661 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1662 return false;
1663 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1664 }
1665};
1666
1667class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1668public:
1669 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1670 : CommandObjectTypeFormatterClear(
1671 interpreter,
1672 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1673 "type summary clear", "Delete all existing summaries.") {}
1674
1675protected:
1676 void FormatterSpecificDeletion() override {
1677 DataVisualization::NamedSummaryFormats::Clear();
1678 }
1679};
1680
1681// CommandObjectTypeSummaryList
1682
1683class CommandObjectTypeSummaryList
1684 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1685public:
1686 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1687 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1688 "Show a list of current summaries.") {}
1689
1690protected:
1691 bool FormatterSpecificList(CommandReturnObject &result) override {
1692 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1693 result.GetOutputStream().Printf("Named summaries:\n");
1694 DataVisualization::NamedSummaryFormats::ForEach(
1695 [&result](const TypeMatcher &type_matcher,
1696 const TypeSummaryImplSP &summary_sp) -> bool {
1697 result.GetOutputStream().Printf(
1698 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1699 summary_sp->GetDescription().c_str());
1700 return true;
1701 });
1702 return true;
1703 }
1704 return false;
1705 }
1706};
1707
1708// CommandObjectTypeCategoryDefine
1709#define LLDB_OPTIONS_type_category_define
1710#include "CommandOptions.inc"
1711
1712class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1713 class CommandOptions : public Options {
1714 public:
1715 CommandOptions()
1716 : Options(), m_define_enabled(false, false),
1717 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1718
1719 ~CommandOptions() override = default;
1720
1721 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1722 ExecutionContext *execution_context) override {
1723 Status error;
1724 const int short_option = m_getopt_table[option_idx].val;
1725
1726 switch (short_option) {
1727 case 'e':
1728 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1729 break;
1730 case 'l':
1731 error = m_cate_language.SetValueFromString(option_arg);
1732 break;
1733 default:
1734 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 1734)
;
1735 }
1736
1737 return error;
1738 }
1739
1740 void OptionParsingStarting(ExecutionContext *execution_context) override {
1741 m_define_enabled.Clear();
1742 m_cate_language.Clear();
1743 }
1744
1745 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1746 return llvm::makeArrayRef(g_type_category_define_options);
1747 }
1748
1749 // Instance variables to hold the values for command options.
1750
1751 OptionValueBoolean m_define_enabled;
1752 OptionValueLanguage m_cate_language;
1753 };
1754
1755 CommandOptions m_options;
1756
1757 Options *GetOptions() override { return &m_options; }
1758
1759public:
1760 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1761 : CommandObjectParsed(interpreter, "type category define",
1762 "Define a new category as a source of formatters.",
1763 nullptr),
1764 m_options() {
1765 CommandArgumentEntry type_arg;
1766 CommandArgumentData type_style_arg;
1767
1768 type_style_arg.arg_type = eArgTypeName;
1769 type_style_arg.arg_repetition = eArgRepeatPlus;
1770
1771 type_arg.push_back(type_style_arg);
1772
1773 m_arguments.push_back(type_arg);
1774 }
1775
1776 ~CommandObjectTypeCategoryDefine() override = default;
1777
1778 void
1779 HandleArgumentCompletion(CompletionRequest &request,
1780 OptionElementVector &opt_element_vector) override {
1781 CommandCompletions::InvokeCommonCompletionCallbacks(
1782 GetCommandInterpreter(),
1783 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1784 }
1785
1786protected:
1787 bool DoExecute(Args &command, CommandReturnObject &result) override {
1788 const size_t argc = command.GetArgumentCount();
1789
1790 if (argc < 1) {
1791 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1792 m_cmd_name.c_str());
1793 return false;
1794 }
1795
1796 for (auto &entry : command.entries()) {
1797 TypeCategoryImplSP category_sp;
1798 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1799 category_sp) &&
1800 category_sp) {
1801 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1802 if (m_options.m_define_enabled.GetCurrentValue())
1803 DataVisualization::Categories::Enable(category_sp,
1804 TypeCategoryMap::Default);
1805 }
1806 }
1807
1808 result.SetStatus(eReturnStatusSuccessFinishResult);
1809 return result.Succeeded();
1810 }
1811};
1812
1813// CommandObjectTypeCategoryEnable
1814#define LLDB_OPTIONS_type_category_enable
1815#include "CommandOptions.inc"
1816
1817class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1818 class CommandOptions : public Options {
1819 public:
1820 CommandOptions() : Options() {}
1821
1822 ~CommandOptions() override = default;
1823
1824 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1825 ExecutionContext *execution_context) override {
1826 Status error;
1827 const int short_option = m_getopt_table[option_idx].val;
1828
1829 switch (short_option) {
1830 case 'l':
1831 if (!option_arg.empty()) {
1832 m_language = Language::GetLanguageTypeFromString(option_arg);
1833 if (m_language == lldb::eLanguageTypeUnknown)
1834 error.SetErrorStringWithFormat("unrecognized language '%s'",
1835 option_arg.str().c_str());
1836 }
1837 break;
1838 default:
1839 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 1839)
;
1840 }
1841
1842 return error;
1843 }
1844
1845 void OptionParsingStarting(ExecutionContext *execution_context) override {
1846 m_language = lldb::eLanguageTypeUnknown;
1847 }
1848
1849 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1850 return llvm::makeArrayRef(g_type_category_enable_options);
1851 }
1852
1853 // Instance variables to hold the values for command options.
1854
1855 lldb::LanguageType m_language;
1856 };
1857
1858 CommandOptions m_options;
1859
1860 Options *GetOptions() override { return &m_options; }
1861
1862public:
1863 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1864 : CommandObjectParsed(interpreter, "type category enable",
1865 "Enable a category as a source of formatters.",
1866 nullptr),
1867 m_options() {
1868 CommandArgumentEntry type_arg;
1869 CommandArgumentData type_style_arg;
1870
1871 type_style_arg.arg_type = eArgTypeName;
1872 type_style_arg.arg_repetition = eArgRepeatPlus;
1873
1874 type_arg.push_back(type_style_arg);
1875
1876 m_arguments.push_back(type_arg);
1877 }
1878
1879 ~CommandObjectTypeCategoryEnable() override = default;
1880
1881 void
1882 HandleArgumentCompletion(CompletionRequest &request,
1883 OptionElementVector &opt_element_vector) override {
1884 CommandCompletions::InvokeCommonCompletionCallbacks(
1885 GetCommandInterpreter(),
1886 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1887 }
1888
1889protected:
1890 bool DoExecute(Args &command, CommandReturnObject &result) override {
1891 const size_t argc = command.GetArgumentCount();
1892
1893 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1894 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1895 m_cmd_name.c_str());
1896 return false;
1897 }
1898
1899 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1900 DataVisualization::Categories::EnableStar();
1901 } else if (argc > 0) {
1902 for (int i = argc - 1; i >= 0; i--) {
1903 const char *typeA = command.GetArgumentAtIndex(i);
1904 ConstString typeCS(typeA);
1905
1906 if (!typeCS) {
1907 result.AppendError("empty category name not allowed");
1908 return false;
1909 }
1910 DataVisualization::Categories::Enable(typeCS);
1911 lldb::TypeCategoryImplSP cate;
1912 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1913 if (cate->GetCount() == 0) {
1914 result.AppendWarning("empty category enabled (typo?)");
1915 }
1916 }
1917 }
1918 }
1919
1920 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1921 DataVisualization::Categories::Enable(m_options.m_language);
1922
1923 result.SetStatus(eReturnStatusSuccessFinishResult);
1924 return result.Succeeded();
1925 }
1926};
1927
1928// CommandObjectTypeCategoryDelete
1929
1930class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1931public:
1932 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1933 : CommandObjectParsed(interpreter, "type category delete",
1934 "Delete a category and all associated formatters.",
1935 nullptr) {
1936 CommandArgumentEntry type_arg;
1937 CommandArgumentData type_style_arg;
1938
1939 type_style_arg.arg_type = eArgTypeName;
1940 type_style_arg.arg_repetition = eArgRepeatPlus;
1941
1942 type_arg.push_back(type_style_arg);
1943
1944 m_arguments.push_back(type_arg);
1945 }
1946
1947 ~CommandObjectTypeCategoryDelete() override = default;
1948
1949 void
1950 HandleArgumentCompletion(CompletionRequest &request,
1951 OptionElementVector &opt_element_vector) override {
1952 CommandCompletions::InvokeCommonCompletionCallbacks(
1953 GetCommandInterpreter(),
1954 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1955 }
1956
1957protected:
1958 bool DoExecute(Args &command, CommandReturnObject &result) override {
1959 const size_t argc = command.GetArgumentCount();
1960
1961 if (argc < 1) {
1962 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1963 m_cmd_name.c_str());
1964 return false;
1965 }
1966
1967 bool success = true;
1968
1969 // the order is not relevant here
1970 for (int i = argc - 1; i >= 0; i--) {
1971 const char *typeA = command.GetArgumentAtIndex(i);
1972 ConstString typeCS(typeA);
1973
1974 if (!typeCS) {
1975 result.AppendError("empty category name not allowed");
1976 return false;
1977 }
1978 if (!DataVisualization::Categories::Delete(typeCS))
1979 success = false; // keep deleting even if we hit an error
1980 }
1981 if (success) {
1982 result.SetStatus(eReturnStatusSuccessFinishResult);
1983 return result.Succeeded();
1984 } else {
1985 result.AppendError("cannot delete one or more categories\n");
1986 return false;
1987 }
1988 }
1989};
1990
1991// CommandObjectTypeCategoryDisable
1992#define LLDB_OPTIONS_type_category_disable
1993#include "CommandOptions.inc"
1994
1995class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1996 class CommandOptions : public Options {
1997 public:
1998 CommandOptions() : Options() {}
1999
2000 ~CommandOptions() override = default;
2001
2002 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2003 ExecutionContext *execution_context) override {
2004 Status error;
2005 const int short_option = m_getopt_table[option_idx].val;
2006
2007 switch (short_option) {
2008 case 'l':
2009 if (!option_arg.empty()) {
2010 m_language = Language::GetLanguageTypeFromString(option_arg);
2011 if (m_language == lldb::eLanguageTypeUnknown)
2012 error.SetErrorStringWithFormat("unrecognized language '%s'",
2013 option_arg.str().c_str());
2014 }
2015 break;
2016 default:
2017 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 2017)
;
2018 }
2019
2020 return error;
2021 }
2022
2023 void OptionParsingStarting(ExecutionContext *execution_context) override {
2024 m_language = lldb::eLanguageTypeUnknown;
2025 }
2026
2027 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2028 return llvm::makeArrayRef(g_type_category_disable_options);
2029 }
2030
2031 // Instance variables to hold the values for command options.
2032
2033 lldb::LanguageType m_language;
2034 };
2035
2036 CommandOptions m_options;
2037
2038 Options *GetOptions() override { return &m_options; }
2039
2040public:
2041 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2042 : CommandObjectParsed(interpreter, "type category disable",
2043 "Disable a category as a source of formatters.",
2044 nullptr),
2045 m_options() {
2046 CommandArgumentEntry type_arg;
2047 CommandArgumentData type_style_arg;
2048
2049 type_style_arg.arg_type = eArgTypeName;
2050 type_style_arg.arg_repetition = eArgRepeatPlus;
2051
2052 type_arg.push_back(type_style_arg);
2053
2054 m_arguments.push_back(type_arg);
2055 }
2056
2057 ~CommandObjectTypeCategoryDisable() override = default;
2058
2059 void
2060 HandleArgumentCompletion(CompletionRequest &request,
2061 OptionElementVector &opt_element_vector) override {
2062 CommandCompletions::InvokeCommonCompletionCallbacks(
2063 GetCommandInterpreter(),
2064 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
2065 }
2066
2067protected:
2068 bool DoExecute(Args &command, CommandReturnObject &result) override {
2069 const size_t argc = command.GetArgumentCount();
2070
2071 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2072 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2073 m_cmd_name.c_str());
2074 return false;
2075 }
2076
2077 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2078 DataVisualization::Categories::DisableStar();
2079 } else if (argc > 0) {
2080 // the order is not relevant here
2081 for (int i = argc - 1; i >= 0; i--) {
2082 const char *typeA = command.GetArgumentAtIndex(i);
2083 ConstString typeCS(typeA);
2084
2085 if (!typeCS) {
2086 result.AppendError("empty category name not allowed");
2087 return false;
2088 }
2089 DataVisualization::Categories::Disable(typeCS);
2090 }
2091 }
2092
2093 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2094 DataVisualization::Categories::Disable(m_options.m_language);
2095
2096 result.SetStatus(eReturnStatusSuccessFinishResult);
2097 return result.Succeeded();
2098 }
2099};
2100
2101// CommandObjectTypeCategoryList
2102
2103class CommandObjectTypeCategoryList : public CommandObjectParsed {
2104public:
2105 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2106 : CommandObjectParsed(interpreter, "type category list",
2107 "Provide a list of all existing categories.",
2108 nullptr) {
2109 CommandArgumentEntry type_arg;
2110 CommandArgumentData type_style_arg;
2111
2112 type_style_arg.arg_type = eArgTypeName;
2113 type_style_arg.arg_repetition = eArgRepeatOptional;
2114
2115 type_arg.push_back(type_style_arg);
2116
2117 m_arguments.push_back(type_arg);
2118 }
2119
2120 ~CommandObjectTypeCategoryList() override = default;
2121
2122 void
2123 HandleArgumentCompletion(CompletionRequest &request,
2124 OptionElementVector &opt_element_vector) override {
2125 if (request.GetCursorIndex())
2126 return;
2127 CommandCompletions::InvokeCommonCompletionCallbacks(
2128 GetCommandInterpreter(),
2129 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
2130 }
2131
2132protected:
2133 bool DoExecute(Args &command, CommandReturnObject &result) override {
2134 const size_t argc = command.GetArgumentCount();
2135
2136 std::unique_ptr<RegularExpression> regex;
2137
2138 if (argc == 1) {
2139 const char *arg = command.GetArgumentAtIndex(0);
2140 regex = std::make_unique<RegularExpression>(arg);
2141 if (!regex->IsValid()) {
2142 result.AppendErrorWithFormat(
2143 "syntax error in category regular expression '%s'", arg);
2144 return false;
2145 }
2146 } else if (argc != 0) {
2147 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2148 m_cmd_name.c_str());
2149 return false;
2150 }
2151
2152 DataVisualization::Categories::ForEach(
2153 [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2154 if (regex) {
2155 bool escape = true;
2156 if (regex->GetText() == category_sp->GetName()) {
2157 escape = false;
2158 } else if (regex->Execute(category_sp->GetName())) {
2159 escape = false;
2160 }
2161
2162 if (escape)
2163 return true;
2164 }
2165
2166 result.GetOutputStream().Printf(
2167 "Category: %s\n", category_sp->GetDescription().c_str());
2168
2169 return true;
2170 });
2171
2172 result.SetStatus(eReturnStatusSuccessFinishResult);
2173 return result.Succeeded();
2174 }
2175};
2176
2177// CommandObjectTypeFilterList
2178
2179class CommandObjectTypeFilterList
2180 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2181public:
2182 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2183 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2184 "Show a list of current filters.") {}
2185};
2186
2187#if LLDB_ENABLE_PYTHON1
2188
2189// CommandObjectTypeSynthList
2190
2191class CommandObjectTypeSynthList
2192 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2193public:
2194 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2195 : CommandObjectTypeFormatterList(
2196 interpreter, "type synthetic list",
2197 "Show a list of current synthetic providers.") {}
2198};
2199
2200#endif
2201
2202// CommandObjectTypeFilterDelete
2203
2204class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2205public:
2206 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2207 : CommandObjectTypeFormatterDelete(
2208 interpreter,
2209 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2210 "type filter delete", "Delete an existing filter for a type.") {}
2211
2212 ~CommandObjectTypeFilterDelete() override = default;
2213};
2214
2215#if LLDB_ENABLE_PYTHON1
2216
2217// CommandObjectTypeSynthDelete
2218
2219class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2220public:
2221 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2222 : CommandObjectTypeFormatterDelete(
2223 interpreter,
2224 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2225 "type synthetic delete",
2226 "Delete an existing synthetic provider for a type.") {}
2227
2228 ~CommandObjectTypeSynthDelete() override = default;
2229};
2230
2231#endif
2232
2233// CommandObjectTypeFilterClear
2234
2235class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2236public:
2237 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2238 : CommandObjectTypeFormatterClear(
2239 interpreter,
2240 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2241 "type filter clear", "Delete all existing filter.") {}
2242};
2243
2244#if LLDB_ENABLE_PYTHON1
2245// CommandObjectTypeSynthClear
2246
2247class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2248public:
2249 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2250 : CommandObjectTypeFormatterClear(
2251 interpreter,
2252 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2253 "type synthetic clear",
2254 "Delete all existing synthetic providers.") {}
2255};
2256
2257bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2258 Args &command, CommandReturnObject &result) {
2259 SynthAddOptions *options = new SynthAddOptions(
4
Memory is allocated
2260 m_options.m_skip_pointers, m_options.m_skip_references,
2261 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2262
2263 for (auto &entry : command.entries()) {
5
Assuming '__begin1' is not equal to '__end1'
2264 if (entry.ref().empty()) {
6
Assuming the condition is true
7
Taking true branch
2265 result.AppendError("empty typenames not allowed");
8
Potential leak of memory pointed to by 'options'
2266 return false;
2267 }
2268
2269 options->m_target_types << std::string(entry.ref());
2270 }
2271
2272 m_interpreter.GetPythonCommandsFromIOHandler(
2273 " ", // Prompt
2274 *this, // IOHandlerDelegate
2275 options); // Baton for the "io_handler" that will be passed back into our
2276 // IOHandlerDelegate functions
2277 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2278 return result.Succeeded();
2279}
2280
2281bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2282 Args &command, CommandReturnObject &result) {
2283 const size_t argc = command.GetArgumentCount();
2284
2285 if (argc < 1) {
2286 result.AppendErrorWithFormat("%s takes one or more args.\n",
2287 m_cmd_name.c_str());
2288 return false;
2289 }
2290
2291 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2292 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2293 "directly input Python code.\n",
2294 m_cmd_name.c_str());
2295 return false;
2296 }
2297
2298 SyntheticChildrenSP entry;
2299
2300 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2301 SyntheticChildren::Flags()
2302 .SetCascades(m_options.m_cascade)
2303 .SetSkipPointers(m_options.m_skip_pointers)
2304 .SetSkipReferences(m_options.m_skip_references),
2305 m_options.m_class_name.c_str());
2306
2307 entry.reset(impl);
2308
2309 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2310
2311 if (interpreter &&
2312 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2313 result.AppendWarning("The provided class does not exist - please define it "
2314 "before attempting to use this synthetic provider");
2315
2316 // now I have a valid provider, let's add it to every type
2317
2318 lldb::TypeCategoryImplSP category;
2319 DataVisualization::Categories::GetCategory(
2320 ConstString(m_options.m_category.c_str()), category);
2321
2322 Status error;
2323
2324 for (auto &arg_entry : command.entries()) {
2325 if (arg_entry.ref().empty()) {
2326 result.AppendError("empty typenames not allowed");
2327 return false;
2328 }
2329
2330 ConstString typeCS(arg_entry.ref());
2331 if (!AddSynth(typeCS, entry,
2332 m_options.m_regex ? eRegexSynth : eRegularSynth,
2333 m_options.m_category, &error)) {
2334 result.AppendError(error.AsCString());
2335 return false;
2336 }
2337 }
2338
2339 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2340 return result.Succeeded();
2341}
2342
2343CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2344 CommandInterpreter &interpreter)
2345 : CommandObjectParsed(interpreter, "type synthetic add",
2346 "Add a new synthetic provider for a type.", nullptr),
2347 IOHandlerDelegateMultiline("DONE"), m_options() {
2348 CommandArgumentEntry type_arg;
2349 CommandArgumentData type_style_arg;
2350
2351 type_style_arg.arg_type = eArgTypeName;
2352 type_style_arg.arg_repetition = eArgRepeatPlus;
2353
2354 type_arg.push_back(type_style_arg);
2355
2356 m_arguments.push_back(type_arg);
2357}
2358
2359bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2360 SyntheticChildrenSP entry,
2361 SynthFormatType type,
2362 std::string category_name,
2363 Status *error) {
2364 lldb::TypeCategoryImplSP category;
2365 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2366 category);
2367
2368 if (type == eRegularSynth) {
2369 if (FixArrayTypeNameWithRegex(type_name))
2370 type = eRegexSynth;
2371 }
2372
2373 if (category->AnyMatches(
2374 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2375 false)) {
2376 if (error)
2377 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2378 "filter is defined in same category!",
2379 type_name.AsCString());
2380 return false;
2381 }
2382
2383 if (type == eRegexSynth) {
2384 RegularExpression typeRX(type_name.GetStringRef());
2385 if (!typeRX.IsValid()) {
2386 if (error)
2387 error->SetErrorString(
2388 "regex format error (maybe this is not really a regex?)");
2389 return false;
2390 }
2391
2392 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2393 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry);
2394
2395 return true;
2396 } else {
2397 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry);
2398 return true;
2399 }
2400}
2401
2402#endif
2403#define LLDB_OPTIONS_type_filter_add
2404#include "CommandOptions.inc"
2405
2406class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2407private:
2408 class CommandOptions : public Options {
2409 typedef std::vector<std::string> option_vector;
2410
2411 public:
2412 CommandOptions() : Options() {}
2413
2414 ~CommandOptions() override = default;
2415
2416 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2417 ExecutionContext *execution_context) override {
2418 Status error;
2419 const int short_option = m_getopt_table[option_idx].val;
2420 bool success;
2421
2422 switch (short_option) {
2423 case 'C':
2424 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2425 if (!success)
2426 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2427 option_arg.str().c_str());
2428 break;
2429 case 'c':
2430 m_expr_paths.push_back(std::string(option_arg));
2431 has_child_list = true;
2432 break;
2433 case 'p':
2434 m_skip_pointers = true;
2435 break;
2436 case 'r':
2437 m_skip_references = true;
2438 break;
2439 case 'w':
2440 m_category = std::string(option_arg);
2441 break;
2442 case 'x':
2443 m_regex = true;
2444 break;
2445 default:
2446 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 2446)
;
2447 }
2448
2449 return error;
2450 }
2451
2452 void OptionParsingStarting(ExecutionContext *execution_context) override {
2453 m_cascade = true;
2454 m_skip_pointers = false;
2455 m_skip_references = false;
2456 m_category = "default";
2457 m_expr_paths.clear();
2458 has_child_list = false;
2459 m_regex = false;
2460 }
2461
2462 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2463 return llvm::makeArrayRef(g_type_filter_add_options);
2464 }
2465
2466 // Instance variables to hold the values for command options.
2467
2468 bool m_cascade;
2469 bool m_skip_references;
2470 bool m_skip_pointers;
2471 bool m_input_python;
2472 option_vector m_expr_paths;
2473 std::string m_category;
2474 bool has_child_list;
2475 bool m_regex;
2476
2477 typedef option_vector::iterator ExpressionPathsIterator;
2478 };
2479
2480 CommandOptions m_options;
2481
2482 Options *GetOptions() override { return &m_options; }
2483
2484 enum FilterFormatType { eRegularFilter, eRegexFilter };
2485
2486 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2487 FilterFormatType type, std::string category_name,
2488 Status *error) {
2489 lldb::TypeCategoryImplSP category;
2490 DataVisualization::Categories::GetCategory(
2491 ConstString(category_name.c_str()), category);
2492
2493 if (type == eRegularFilter) {
2494 if (FixArrayTypeNameWithRegex(type_name))
2495 type = eRegexFilter;
2496 }
2497
2498 if (category->AnyMatches(
2499 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2500 false)) {
2501 if (error)
2502 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2503 "synthetic is defined in same "
2504 "category!",
2505 type_name.AsCString());
2506 return false;
2507 }
2508
2509 if (type == eRegexFilter) {
2510 RegularExpression typeRX(type_name.GetStringRef());
2511 if (!typeRX.IsValid()) {
2512 if (error)
2513 error->SetErrorString(
2514 "regex format error (maybe this is not really a regex?)");
2515 return false;
2516 }
2517
2518 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2519 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry);
2520
2521 return true;
2522 } else {
2523 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry);
2524 return true;
2525 }
2526 }
2527
2528public:
2529 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2530 : CommandObjectParsed(interpreter, "type filter add",
2531 "Add a new filter for a type.", nullptr),
2532 m_options() {
2533 CommandArgumentEntry type_arg;
2534 CommandArgumentData type_style_arg;
2535
2536 type_style_arg.arg_type = eArgTypeName;
2537 type_style_arg.arg_repetition = eArgRepeatPlus;
2538
2539 type_arg.push_back(type_style_arg);
2540
2541 m_arguments.push_back(type_arg);
2542
2543 SetHelpLong(
2544 R"(
2545The following examples of 'type filter add' refer to this code snippet for context:
2546
2547 class Foo {
2548 int a;
2549 int b;
2550 int c;
2551 int d;
2552 int e;
2553 int f;
2554 int g;
2555 int h;
2556 int i;
2557 }
2558 Foo my_foo;
2559
2560Adding a simple filter:
2561
2562(lldb) type filter add --child a --child g Foo
2563(lldb) frame variable my_foo
2564
2565)"
2566 "Produces output where only a and g are displayed. Other children of my_foo \
2567(b, c, d, e, f, h and i) are available by asking for them explicitly:"
2568 R"(
2569
2570(lldb) frame variable my_foo.b my_foo.c my_foo.i
2571
2572)"
2573 "The formatting option --raw on frame variable bypasses the filter, showing \
2574all children of my_foo as if no filter was defined:"
2575 R"(
2576
2577(lldb) frame variable my_foo --raw)");
2578 }
2579
2580 ~CommandObjectTypeFilterAdd() override = default;
2581
2582protected:
2583 bool DoExecute(Args &command, CommandReturnObject &result) override {
2584 const size_t argc = command.GetArgumentCount();
2585
2586 if (argc < 1) {
2587 result.AppendErrorWithFormat("%s takes one or more args.\n",
2588 m_cmd_name.c_str());
2589 return false;
2590 }
2591
2592 if (m_options.m_expr_paths.empty()) {
2593 result.AppendErrorWithFormat("%s needs one or more children.\n",
2594 m_cmd_name.c_str());
2595 return false;
2596 }
2597
2598 TypeFilterImplSP entry(new TypeFilterImpl(
2599 SyntheticChildren::Flags()
2600 .SetCascades(m_options.m_cascade)
2601 .SetSkipPointers(m_options.m_skip_pointers)
2602 .SetSkipReferences(m_options.m_skip_references)));
2603
2604 // go through the expression paths
2605 CommandOptions::ExpressionPathsIterator begin,
2606 end = m_options.m_expr_paths.end();
2607
2608 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2609 entry->AddExpressionPath(*begin);
2610
2611 // now I have a valid provider, let's add it to every type
2612
2613 lldb::TypeCategoryImplSP category;
2614 DataVisualization::Categories::GetCategory(
2615 ConstString(m_options.m_category.c_str()), category);
2616
2617 Status error;
2618
2619 WarnOnPotentialUnquotedUnsignedType(command, result);
2620
2621 for (auto &arg_entry : command.entries()) {
2622 if (arg_entry.ref().empty()) {
2623 result.AppendError("empty typenames not allowed");
2624 return false;
2625 }
2626
2627 ConstString typeCS(arg_entry.ref());
2628 if (!AddFilter(typeCS, entry,
2629 m_options.m_regex ? eRegexFilter : eRegularFilter,
2630 m_options.m_category, &error)) {
2631 result.AppendError(error.AsCString());
2632 return false;
2633 }
2634 }
2635
2636 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2637 return result.Succeeded();
2638 }
2639};
2640
2641// "type lookup"
2642#define LLDB_OPTIONS_type_lookup
2643#include "CommandOptions.inc"
2644
2645class CommandObjectTypeLookup : public CommandObjectRaw {
2646protected:
2647 // this function is allowed to do a more aggressive job at guessing languages
2648 // than the expression parser is comfortable with - so leave the original
2649 // call alone and add one that is specific to type lookup
2650 lldb::LanguageType GuessLanguage(StackFrame *frame) {
2651 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2652
2653 if (!frame)
2654 return lang_type;
2655
2656 lang_type = frame->GuessLanguage();
2657 if (lang_type != lldb::eLanguageTypeUnknown)
2658 return lang_type;
2659
2660 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2661 if (s)
2662 lang_type = s->GetMangled().GuessLanguage();
2663
2664 return lang_type;
2665 }
2666
2667 class CommandOptions : public OptionGroup {
2668 public:
2669 CommandOptions() : OptionGroup() {}
2670
2671 ~CommandOptions() override = default;
2672
2673 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2674 return llvm::makeArrayRef(g_type_lookup_options);
2675 }
2676
2677 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2678 ExecutionContext *execution_context) override {
2679 Status error;
2680
2681 const int short_option = g_type_lookup_options[option_idx].short_option;
2682
2683 switch (short_option) {
2684 case 'h':
2685 m_show_help = true;
2686 break;
2687
2688 case 'l':
2689 m_language = Language::GetLanguageTypeFromString(option_value);
2690 break;
2691
2692 default:
2693 llvm_unreachable("Unimplemented option")::llvm::llvm_unreachable_internal("Unimplemented option", "lldb/source/Commands/CommandObjectType.cpp"
, 2693)
;
2694 }
2695
2696 return error;
2697 }
2698
2699 void OptionParsingStarting(ExecutionContext *execution_context) override {
2700 m_show_help = false;
2701 m_language = eLanguageTypeUnknown;
2702 }
2703
2704 // Options table: Required for subclasses of Options.
2705
2706 bool m_show_help = false;
2707 lldb::LanguageType m_language = eLanguageTypeUnknown;
2708 };
2709
2710 OptionGroupOptions m_option_group;
2711 CommandOptions m_command_options;
2712
2713public:
2714 CommandObjectTypeLookup(CommandInterpreter &interpreter)
2715 : CommandObjectRaw(interpreter, "type lookup",
2716 "Lookup types and declarations in the current target, "
2717 "following language-specific naming conventions.",
2718 "type lookup <type-specifier>",
2719 eCommandRequiresTarget),
2720 m_option_group(), m_command_options() {
2721 m_option_group.Append(&m_command_options);
2722 m_option_group.Finalize();
2723 }
2724
2725 ~CommandObjectTypeLookup() override = default;
2726
2727 Options *GetOptions() override { return &m_option_group; }
2728
2729 llvm::StringRef GetHelpLong() override {
2730 if (!m_cmd_help_long.empty())
2731 return m_cmd_help_long;
2732
2733 StreamString stream;
2734 Language::ForEach([&](Language *lang) {
2735 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2736 stream.Printf("%s\n", help);
2737 return true;
2738 });
2739
2740 m_cmd_help_long = std::string(stream.GetString());
2741 return m_cmd_help_long;
2742 }
2743
2744 bool DoExecute(llvm::StringRef raw_command_line,
2745 CommandReturnObject &result) override {
2746 if (raw_command_line.empty()) {
2747 result.AppendError(
2748 "type lookup cannot be invoked without a type name as argument");
2749 return false;
2750 }
2751
2752 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2753 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2754
2755 OptionsWithRaw args(raw_command_line);
2756 const char *name_of_type = args.GetRawPart().c_str();
2757
2758 if (args.HasArgs())
2759 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2760 exe_ctx))
2761 return false;
2762
2763 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2764
2765 bool any_found = false;
2766
2767 std::vector<Language *> languages;
2768
2769 bool is_global_search = false;
2770 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2771
2772 if ((is_global_search =
2773 (m_command_options.m_language == eLanguageTypeUnknown))) {
2774 Language::ForEach([&](Language *lang) {
2775 languages.push_back(lang);
2776 return true;
2777 });
2778 } else {
2779 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2780 }
2781
2782 // This is not the most efficient way to do this, but we support very few
2783 // languages so the cost of the sort is going to be dwarfed by the actual
2784 // lookup anyway
2785 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2786 guessed_language = GuessLanguage(frame);
2787 if (guessed_language != eLanguageTypeUnknown) {
2788 llvm::sort(
2789 languages.begin(), languages.end(),
2790 [guessed_language](Language *lang1, Language *lang2) -> bool {
2791 if (!lang1 || !lang2)
2792 return false;
2793 LanguageType lt1 = lang1->GetLanguageType();
2794 LanguageType lt2 = lang2->GetLanguageType();
2795 if (lt1 == guessed_language)
2796 return true; // make the selected frame's language come first
2797 if (lt2 == guessed_language)
2798 return false; // make the selected frame's language come first
2799 return (lt1 < lt2); // normal comparison otherwise
2800 });
2801 }
2802 }
2803
2804 bool is_first_language = true;
2805
2806 for (Language *language : languages) {
2807 if (!language)
2808 continue;
2809
2810 if (auto scavenger = language->GetTypeScavenger()) {
2811 Language::TypeScavenger::ResultSet search_results;
2812 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2813 for (const auto &search_result : search_results) {
2814 if (search_result && search_result->IsValid()) {
2815 any_found = true;
2816 search_result->DumpToStream(result.GetOutputStream(),
2817 this->m_command_options.m_show_help);
2818 }
2819 }
2820 }
2821 }
2822 // this is "type lookup SomeName" and we did find a match, so get out
2823 if (any_found && is_global_search)
2824 break;
2825 else if (is_first_language && is_global_search &&
2826 guessed_language != lldb::eLanguageTypeUnknown) {
2827 is_first_language = false;
2828 result.GetOutputStream().Printf(
2829 "no type was found in the current language %s matching '%s'; "
2830 "performing a global search across all languages\n",
2831 Language::GetNameForLanguageType(guessed_language), name_of_type);
2832 }
2833 }
2834
2835 if (!any_found)
2836 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2837 name_of_type);
2838
2839 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2840 : lldb::eReturnStatusSuccessFinishNoResult);
2841 return true;
2842 }
2843};
2844
2845template <typename FormatterType>
2846class CommandObjectFormatterInfo : public CommandObjectRaw {
2847public:
2848 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2849 DiscoveryFunction;
2850 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2851 const char *formatter_name,
2852 DiscoveryFunction discovery_func)
2853 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2854 m_formatter_name(formatter_name ? formatter_name : ""),
2855 m_discovery_function(discovery_func) {
2856 StreamString name;
2857 name.Printf("type %s info", formatter_name);
2858 SetCommandName(name.GetString());
2859 StreamString help;
2860 help.Printf("This command evaluates the provided expression and shows "
2861 "which %s is applied to the resulting value (if any).",
2862 formatter_name);
2863 SetHelp(help.GetString());
2864 StreamString syntax;
2865 syntax.Printf("type %s info <expr>", formatter_name);
2866 SetSyntax(syntax.GetString());
2867 }
2868
2869 ~CommandObjectFormatterInfo() override = default;
2870
2871protected:
2872 bool DoExecute(llvm::StringRef command,
2873 CommandReturnObject &result) override {
2874 TargetSP target_sp = GetDebugger().GetSelectedTarget();
2875 Thread *thread = GetDefaultThread();
2876 if (!thread) {
2877 result.AppendError("no default thread");
2878 return false;
2879 }
2880
2881 StackFrameSP frame_sp = thread->GetSelectedFrame();
2882 ValueObjectSP result_valobj_sp;
2883 EvaluateExpressionOptions options;
2884 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2885 command, frame_sp.get(), result_valobj_sp, options);
2886 if (expr_result == eExpressionCompleted && result_valobj_sp) {
2887 result_valobj_sp =
2888 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2889 target_sp->GetPreferDynamicValue(),
2890 target_sp->GetEnableSyntheticValue());
2891 typename FormatterType::SharedPointer formatter_sp =
2892 m_discovery_function(*result_valobj_sp);
2893 if (formatter_sp) {
2894 std::string description(formatter_sp->GetDescription());
2895 result.GetOutputStream()
2896 << m_formatter_name << " applied to ("
2897 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2898 << ") " << command << " is: " << description << "\n";
2899 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2900 } else {
2901 result.GetOutputStream()
2902 << "no " << m_formatter_name << " applies to ("
2903 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2904 << ") " << command << "\n";
2905 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2906 }
2907 return true;
2908 } else {
2909 result.AppendError("failed to evaluate expression");
2910 return false;
2911 }
2912 }
2913
2914private:
2915 std::string m_formatter_name;
2916 DiscoveryFunction m_discovery_function;
2917};
2918
2919class CommandObjectTypeFormat : public CommandObjectMultiword {
2920public:
2921 CommandObjectTypeFormat(CommandInterpreter &interpreter)
2922 : CommandObjectMultiword(
2923 interpreter, "type format",
2924 "Commands for customizing value display formats.",
2925 "type format [<sub-command-options>] ") {
2926 LoadSubCommand(
2927 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2928 LoadSubCommand("clear", CommandObjectSP(
2929 new CommandObjectTypeFormatClear(interpreter)));
2930 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2931 interpreter)));
2932 LoadSubCommand(
2933 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2934 LoadSubCommand(
2935 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2936 interpreter, "format",
2937 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2938 return valobj.GetValueFormat();
2939 })));
2940 }
2941
2942 ~CommandObjectTypeFormat() override = default;
2943};
2944
2945#if LLDB_ENABLE_PYTHON1
2946
2947class CommandObjectTypeSynth : public CommandObjectMultiword {
2948public:
2949 CommandObjectTypeSynth(CommandInterpreter &interpreter)
2950 : CommandObjectMultiword(
2951 interpreter, "type synthetic",
2952 "Commands for operating on synthetic type representations.",
2953 "type synthetic [<sub-command-options>] ") {
2954 LoadSubCommand("add",
2955 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2956 LoadSubCommand(
2957 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2958 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2959 interpreter)));
2960 LoadSubCommand(
2961 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2962 LoadSubCommand(
2963 "info",
2964 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2965 interpreter, "synthetic",
2966 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2967 return valobj.GetSyntheticChildren();
2968 })));
2969 }
2970
2971 ~CommandObjectTypeSynth() override = default;
2972};
2973
2974#endif
2975
2976class CommandObjectTypeFilter : public CommandObjectMultiword {
2977public:
2978 CommandObjectTypeFilter(CommandInterpreter &interpreter)
2979 : CommandObjectMultiword(interpreter, "type filter",
2980 "Commands for operating on type filters.",
2981 "type filter [<sub-command-options>] ") {
2982 LoadSubCommand(
2983 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2984 LoadSubCommand("clear", CommandObjectSP(
2985 new CommandObjectTypeFilterClear(interpreter)));
2986 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2987 interpreter)));
2988 LoadSubCommand(
2989 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2990 }
2991
2992 ~CommandObjectTypeFilter() override = default;
2993};
2994
2995class CommandObjectTypeCategory : public CommandObjectMultiword {
2996public:
2997 CommandObjectTypeCategory(CommandInterpreter &interpreter)
2998 : CommandObjectMultiword(interpreter, "type category",
2999 "Commands for operating on type categories.",
3000 "type category [<sub-command-options>] ") {
3001 LoadSubCommand(
3002 "define",
3003 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3004 LoadSubCommand(
3005 "enable",
3006 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3007 LoadSubCommand(
3008 "disable",
3009 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3010 LoadSubCommand(
3011 "delete",
3012 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3013 LoadSubCommand("list", CommandObjectSP(
3014 new CommandObjectTypeCategoryList(interpreter)));
3015 }
3016
3017 ~CommandObjectTypeCategory() override = default;
3018};
3019
3020class CommandObjectTypeSummary : public CommandObjectMultiword {
3021public:
3022 CommandObjectTypeSummary(CommandInterpreter &interpreter)
3023 : CommandObjectMultiword(
3024 interpreter, "type summary",
3025 "Commands for editing variable summary display options.",
3026 "type summary [<sub-command-options>] ") {
3027 LoadSubCommand(
3028 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3029 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3030 interpreter)));
3031 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3032 interpreter)));
3033 LoadSubCommand(
3034 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3035 LoadSubCommand(
3036 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3037 interpreter, "summary",
3038 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3039 return valobj.GetSummaryFormat();
3040 })));
3041 }
3042
3043 ~CommandObjectTypeSummary() override = default;
3044};
3045
3046// CommandObjectType
3047
3048CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3049 : CommandObjectMultiword(interpreter, "type",
3050 "Commands for operating on the type system.",
3051 "type [<sub-command-options>]") {
3052 LoadSubCommand("category",
3053 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3054 LoadSubCommand("filter",
3055 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3056 LoadSubCommand("format",
3057 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3058 LoadSubCommand("summary",
3059 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3060#if LLDB_ENABLE_PYTHON1
3061 LoadSubCommand("synthetic",
3062 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3063#endif
3064 LoadSubCommand("lookup",
3065 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3066}
3067
3068CommandObjectType::~CommandObjectType() = default;