Bug Summary

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