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