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