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