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 // Other libraries and framework includes
19 #include "llvm/ADT/StringRef.h"
20 
21 // Project includes
22 #include "lldb/Core/ConstString.h"
23 #include "lldb/Core/Debugger.h"
24 #include "lldb/Core/IOHandler.h"
25 #include "lldb/Core/RegularExpression.h"
26 #include "lldb/Core/State.h"
27 #include "lldb/Core/StringList.h"
28 #include "lldb/DataFormatters/DataVisualization.h"
29 #include "lldb/Interpreter/CommandInterpreter.h"
30 #include "lldb/Interpreter/CommandObject.h"
31 #include "lldb/Interpreter/CommandReturnObject.h"
32 #include "lldb/Interpreter/OptionGroupFormat.h"
33 #include "lldb/Interpreter/OptionValueBoolean.h"
34 #include "lldb/Interpreter/OptionValueLanguage.h"
35 #include "lldb/Interpreter/OptionValueString.h"
36 #include "lldb/Interpreter/Options.h"
37 #include "lldb/Symbol/Symbol.h"
38 #include "lldb/Target/Language.h"
39 #include "lldb/Target/Process.h"
40 #include "lldb/Target/StackFrame.h"
41 #include "lldb/Target/Target.h"
42 #include "lldb/Target/Thread.h"
43 #include "lldb/Target/ThreadList.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   for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++) {
82     const char *arg = command.GetArgumentAtIndex(idx);
83     if (idx + 1 < command.GetArgumentCount()) {
84       if (arg && 0 == strcmp(arg, "unsigned")) {
85         const char *next = command.GetArgumentAtIndex(idx + 1);
86         if (next && (0 == strcmp(next, "int") || 0 == strcmp(next, "short") ||
87                      0 == strcmp(next, "char") || 0 == strcmp(next, "long"))) {
88           result.AppendWarningWithFormat("%s %s being treated as two types. if "
89                                          "you meant the combined type name use "
90                                          "quotes, as in \"%s %s\"\n",
91                                          arg, next, arg, next);
92           return true;
93         }
94       }
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, const char *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(
575             llvm::StringRef::withNullAsEmpty(option_value), true, &success);
576         if (!success)
577           error.SetErrorStringWithFormat("invalid value for cascade: %s",
578                                          option_value);
579         break;
580       case 'p':
581         m_skip_pointers = true;
582         break;
583       case 'w':
584         m_category.assign(option_value);
585         break;
586       case 'r':
587         m_skip_references = true;
588         break;
589       case 'x':
590         m_regex = true;
591         break;
592       case 't':
593         m_custom_type_name.assign(option_value);
594         break;
595       default:
596         error.SetErrorStringWithFormat("unrecognized option '%c'",
597                                        short_option);
598         break;
599       }
600 
601       return error;
602     }
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 (size_t i = 0; i < argc; i++) {
731       const char *typeA = command.GetArgumentAtIndex(i);
732       ConstString typeCS(typeA);
733       if (typeCS) {
734         if (m_command_options.m_regex) {
735           RegularExpressionSP typeRX(new RegularExpression());
736           if (!typeRX->Compile(typeCS.GetStringRef())) {
737             result.AppendError(
738                 "regex format error (maybe this is not really a regex?)");
739             result.SetStatus(eReturnStatusFailed);
740             return false;
741           }
742           category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
743           category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry);
744         } else
745           category_sp->GetTypeFormatsContainer()->Add(typeCS, entry);
746       } else {
747         result.AppendError("empty typenames not allowed");
748         result.SetStatus(eReturnStatusFailed);
749         return false;
750       }
751     }
752 
753     result.SetStatus(eReturnStatusSuccessFinishNoResult);
754     return result.Succeeded();
755   }
756 };
757 
758 static OptionDefinition g_type_formatter_delete_options[] = {
759     // clang-format off
760   { LLDB_OPT_SET_1, false, "all",      'a', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Delete from every category." },
761   { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,     "Delete from given category." },
762   { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category." }
763     // clang-format on
764 };
765 
766 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
767 protected:
768   class CommandOptions : public Options {
769   public:
770     CommandOptions() : Options() {}
771 
772     ~CommandOptions() override = default;
773 
774     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
775                          ExecutionContext *execution_context) override {
776       Error error;
777       const int short_option = m_getopt_table[option_idx].val;
778 
779       switch (short_option) {
780       case 'a':
781         m_delete_all = true;
782         break;
783       case 'w':
784         m_category = std::string(option_arg);
785         break;
786       case 'l':
787         m_language = Language::GetLanguageTypeFromString(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 
1035       switch (short_option) {
1036       case 'w':
1037         m_category_regex.SetCurrentValue(option_arg);
1038         m_category_regex.SetOptionWasSet();
1039         break;
1040       case 'l':
1041         error = m_category_language.SetValueFromString(option_arg);
1042         if (error.Success())
1043           m_category_language.SetOptionWasSet();
1044         break;
1045       default:
1046         error.SetErrorStringWithFormat("unrecognized option '%c'",
1047                                        short_option);
1048         break;
1049       }
1050 
1051       return error;
1052     }
1053 
1054     void OptionParsingStarting(ExecutionContext *execution_context) override {
1055       m_category_regex.Clear();
1056       m_category_language.Clear();
1057     }
1058 
1059     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1060       static OptionDefinition g_option_table[] = {
1061           // clang-format off
1062             {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,     "Only show categories matching this filter."},
1063             {LLDB_OPT_SET_2, false, "language",       'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}
1064           // clang-format on
1065       };
1066       return llvm::ArrayRef<OptionDefinition>(g_option_table);
1067     }
1068 
1069     // Instance variables to hold the values for command options.
1070 
1071     OptionValueString m_category_regex;
1072     OptionValueLanguage m_category_language;
1073   };
1074 
1075   CommandOptions m_options;
1076 
1077   Options *GetOptions() override { return &m_options; }
1078 
1079 public:
1080   CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1081                                  const char *name, const char *help)
1082       : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1083     CommandArgumentEntry type_arg;
1084     CommandArgumentData type_style_arg;
1085 
1086     type_style_arg.arg_type = eArgTypeName;
1087     type_style_arg.arg_repetition = eArgRepeatOptional;
1088 
1089     type_arg.push_back(type_style_arg);
1090 
1091     m_arguments.push_back(type_arg);
1092   }
1093 
1094   ~CommandObjectTypeFormatterList() override = default;
1095 
1096 protected:
1097   virtual bool FormatterSpecificList(CommandReturnObject &result) {
1098     return false;
1099   }
1100 
1101   bool DoExecute(Args &command, CommandReturnObject &result) override {
1102     const size_t argc = command.GetArgumentCount();
1103 
1104     std::unique_ptr<RegularExpression> category_regex;
1105     std::unique_ptr<RegularExpression> formatter_regex;
1106 
1107     if (m_options.m_category_regex.OptionWasSet()) {
1108       category_regex.reset(new RegularExpression());
1109       if (!category_regex->Compile(
1110               m_options.m_category_regex.GetCurrentValueAsRef())) {
1111         result.AppendErrorWithFormat(
1112             "syntax error in category regular expression '%s'",
1113             m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1114         result.SetStatus(eReturnStatusFailed);
1115         return false;
1116       }
1117     }
1118 
1119     if (argc == 1) {
1120       const char *arg = command.GetArgumentAtIndex(0);
1121       formatter_regex.reset(new RegularExpression());
1122       if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
1123         result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1124                                      arg);
1125         result.SetStatus(eReturnStatusFailed);
1126         return false;
1127       }
1128     }
1129 
1130     bool any_printed = false;
1131 
1132     auto category_closure = [&result, &formatter_regex, &any_printed](
1133         const lldb::TypeCategoryImplSP &category) -> void {
1134       result.GetOutputStream().Printf(
1135           "-----------------------\nCategory: %s%s\n-----------------------\n",
1136           category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1137 
1138       TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1139       foreach
1140         .SetExact([&result, &formatter_regex, &any_printed](
1141                       ConstString name,
1142                       const FormatterSharedPointer &format_sp) -> bool {
1143           if (formatter_regex) {
1144             bool escape = true;
1145             if (name.GetStringRef() == formatter_regex->GetText()) {
1146               escape = false;
1147             } else if (formatter_regex->Execute(name.GetStringRef())) {
1148               escape = false;
1149             }
1150 
1151             if (escape)
1152               return true;
1153           }
1154 
1155           any_printed = true;
1156           result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1157                                           format_sp->GetDescription().c_str());
1158           return true;
1159         });
1160 
1161       foreach
1162         .SetWithRegex([&result, &formatter_regex, &any_printed](
1163                           RegularExpressionSP regex_sp,
1164                           const FormatterSharedPointer &format_sp) -> bool {
1165           if (formatter_regex) {
1166             bool escape = true;
1167             if (regex_sp->GetText() == formatter_regex->GetText()) {
1168               escape = false;
1169             } else if (formatter_regex->Execute(regex_sp->GetText())) {
1170               escape = false;
1171             }
1172 
1173             if (escape)
1174               return true;
1175           }
1176 
1177           any_printed = true;
1178           result.GetOutputStream().Printf("%s: %s\n",
1179                                           regex_sp->GetText().str().c_str(),
1180                                           format_sp->GetDescription().c_str());
1181           return true;
1182         });
1183 
1184       category->ForEach(foreach);
1185     };
1186 
1187     if (m_options.m_category_language.OptionWasSet()) {
1188       lldb::TypeCategoryImplSP category_sp;
1189       DataVisualization::Categories::GetCategory(
1190           m_options.m_category_language.GetCurrentValue(), category_sp);
1191       if (category_sp)
1192         category_closure(category_sp);
1193     } else {
1194       DataVisualization::Categories::ForEach(
1195           [this, &command, &result, &category_regex, &formatter_regex,
1196            &category_closure](
1197               const lldb::TypeCategoryImplSP &category) -> bool {
1198             if (category_regex) {
1199               bool escape = true;
1200               if (category->GetName() == category_regex->GetText()) {
1201                 escape = false;
1202               } else if (category_regex->Execute(
1203                              llvm::StringRef::withNullAsEmpty(
1204                                  category->GetName()))) {
1205                 escape = false;
1206               }
1207 
1208               if (escape)
1209                 return true;
1210             }
1211 
1212             category_closure(category);
1213 
1214             return true;
1215           });
1216 
1217       any_printed = FormatterSpecificList(result) | any_printed;
1218     }
1219 
1220     if (any_printed)
1221       result.SetStatus(eReturnStatusSuccessFinishResult);
1222     else {
1223       result.GetOutputStream().PutCString("no matching results found.\n");
1224       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1225     }
1226     return result.Succeeded();
1227   }
1228 };
1229 
1230 //-------------------------------------------------------------------------
1231 // CommandObjectTypeFormatList
1232 //-------------------------------------------------------------------------
1233 
1234 class CommandObjectTypeFormatList
1235     : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1236 public:
1237   CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1238       : CommandObjectTypeFormatterList(interpreter, "type format list",
1239                                        "Show a list of current formats.") {}
1240 };
1241 
1242 #ifndef LLDB_DISABLE_PYTHON
1243 
1244 //-------------------------------------------------------------------------
1245 // CommandObjectTypeSummaryAdd
1246 //-------------------------------------------------------------------------
1247 
1248 #endif // LLDB_DISABLE_PYTHON
1249 
1250 Error CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1251     uint32_t option_idx, const char *option_arg,
1252     ExecutionContext *execution_context) {
1253   Error error;
1254   const int short_option = m_getopt_table[option_idx].val;
1255   bool success;
1256 
1257   switch (short_option) {
1258   case 'C':
1259     m_flags.SetCascades(Args::StringToBoolean(
1260         llvm::StringRef::withNullAsEmpty(option_arg), true, &success));
1261     if (!success)
1262       error.SetErrorStringWithFormat("invalid value for cascade: %s",
1263                                      option_arg);
1264     break;
1265   case 'e':
1266     m_flags.SetDontShowChildren(false);
1267     break;
1268   case 'h':
1269     m_flags.SetHideEmptyAggregates(true);
1270     break;
1271   case 'v':
1272     m_flags.SetDontShowValue(true);
1273     break;
1274   case 'c':
1275     m_flags.SetShowMembersOneLiner(true);
1276     break;
1277   case 's':
1278     m_format_string = std::string(option_arg);
1279     break;
1280   case 'p':
1281     m_flags.SetSkipPointers(true);
1282     break;
1283   case 'r':
1284     m_flags.SetSkipReferences(true);
1285     break;
1286   case 'x':
1287     m_regex = true;
1288     break;
1289   case 'n':
1290     m_name.SetCString(option_arg);
1291     break;
1292   case 'o':
1293     m_python_script = std::string(option_arg);
1294     m_is_add_script = true;
1295     break;
1296   case 'F':
1297     m_python_function = std::string(option_arg);
1298     m_is_add_script = true;
1299     break;
1300   case 'P':
1301     m_is_add_script = true;
1302     break;
1303   case 'w':
1304     m_category = std::string(option_arg);
1305     break;
1306   case 'O':
1307     m_flags.SetHideItemNames(true);
1308     break;
1309   default:
1310     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
1311     break;
1312   }
1313 
1314   return error;
1315 }
1316 
1317 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1318     ExecutionContext *execution_context) {
1319   m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1320   m_flags.SetShowMembersOneLiner(false)
1321       .SetSkipPointers(false)
1322       .SetSkipReferences(false)
1323       .SetHideItemNames(false);
1324 
1325   m_regex = false;
1326   m_name.Clear();
1327   m_python_script = "";
1328   m_python_function = "";
1329   m_format_string = "";
1330   m_is_add_script = false;
1331   m_category = "default";
1332 }
1333 
1334 #ifndef LLDB_DISABLE_PYTHON
1335 
1336 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1337     Args &command, CommandReturnObject &result) {
1338   const size_t argc = command.GetArgumentCount();
1339 
1340   if (argc < 1 && !m_options.m_name) {
1341     result.AppendErrorWithFormat("%s takes one or more args.\n",
1342                                  m_cmd_name.c_str());
1343     result.SetStatus(eReturnStatusFailed);
1344     return false;
1345   }
1346 
1347   TypeSummaryImplSP script_format;
1348 
1349   if (!m_options.m_python_function
1350            .empty()) // we have a Python function ready to use
1351   {
1352     const char *funct_name = m_options.m_python_function.c_str();
1353     if (!funct_name || !funct_name[0]) {
1354       result.AppendError("function name empty.\n");
1355       result.SetStatus(eReturnStatusFailed);
1356       return false;
1357     }
1358 
1359     std::string code =
1360         ("    " + m_options.m_python_function + "(valobj,internal_dict)");
1361 
1362     script_format.reset(
1363         new ScriptSummaryFormat(m_options.m_flags, funct_name, code.c_str()));
1364 
1365     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1366 
1367     if (interpreter && !interpreter->CheckObjectExists(funct_name))
1368       result.AppendWarningWithFormat(
1369           "The provided function \"%s\" does not exist - "
1370           "please define it before attempting to use this summary.\n",
1371           funct_name);
1372   } else if (!m_options.m_python_script
1373                   .empty()) // we have a quick 1-line script, just use it
1374   {
1375     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1376     if (!interpreter) {
1377       result.AppendError("script interpreter missing - unable to generate "
1378                          "function wrapper.\n");
1379       result.SetStatus(eReturnStatusFailed);
1380       return false;
1381     }
1382     StringList funct_sl;
1383     funct_sl << m_options.m_python_script.c_str();
1384     std::string funct_name_str;
1385     if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1386       result.AppendError("unable to generate function wrapper.\n");
1387       result.SetStatus(eReturnStatusFailed);
1388       return false;
1389     }
1390     if (funct_name_str.empty()) {
1391       result.AppendError(
1392           "script interpreter failed to generate a valid function name.\n");
1393       result.SetStatus(eReturnStatusFailed);
1394       return false;
1395     }
1396 
1397     std::string code = "    " + m_options.m_python_script;
1398 
1399     script_format.reset(new ScriptSummaryFormat(
1400         m_options.m_flags, funct_name_str.c_str(), code.c_str()));
1401   } else {
1402     // Use an IOHandler to grab Python code from the user
1403     ScriptAddOptions *options =
1404         new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1405                              m_options.m_name, m_options.m_category);
1406 
1407     for (size_t i = 0; i < argc; i++) {
1408       const char *typeA = command.GetArgumentAtIndex(i);
1409       if (typeA && *typeA)
1410         options->m_target_types << typeA;
1411       else {
1412         result.AppendError("empty typenames not allowed");
1413         result.SetStatus(eReturnStatusFailed);
1414         return false;
1415       }
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 (size_t i = 0; i < command.GetArgumentCount(); i++) {
1435     const char *type_name = command.GetArgumentAtIndex(i);
1436     CommandObjectTypeSummaryAdd::AddSummary(
1437         ConstString(type_name), script_format,
1438         (m_options.m_regex ? eRegexSummary : eRegularSummary),
1439         m_options.m_category, &error);
1440     if (error.Fail()) {
1441       result.AppendError(error.AsCString());
1442       result.SetStatus(eReturnStatusFailed);
1443       return false;
1444     }
1445   }
1446 
1447   if (m_options.m_name) {
1448     AddSummary(m_options.m_name, script_format, eNamedSummary,
1449                m_options.m_category, &error);
1450     if (error.Fail()) {
1451       result.AppendError(error.AsCString());
1452       result.AppendError("added to types, but not given a name");
1453       result.SetStatus(eReturnStatusFailed);
1454       return false;
1455     }
1456   }
1457 
1458   return result.Succeeded();
1459 }
1460 
1461 #endif // LLDB_DISABLE_PYTHON
1462 
1463 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1464     Args &command, CommandReturnObject &result) {
1465   const size_t argc = command.GetArgumentCount();
1466 
1467   if (argc < 1 && !m_options.m_name) {
1468     result.AppendErrorWithFormat("%s takes one or more args.\n",
1469                                  m_cmd_name.c_str());
1470     result.SetStatus(eReturnStatusFailed);
1471     return false;
1472   }
1473 
1474   if (!m_options.m_flags.GetShowMembersOneLiner() &&
1475       m_options.m_format_string.empty()) {
1476     result.AppendError("empty summary strings not allowed");
1477     result.SetStatus(eReturnStatusFailed);
1478     return false;
1479   }
1480 
1481   const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1482                                  ? ""
1483                                  : m_options.m_format_string.c_str());
1484 
1485   // ${var%S} is an endless recursion, prevent it
1486   if (strcmp(format_cstr, "${var%S}") == 0) {
1487     result.AppendError("recursive summary not allowed");
1488     result.SetStatus(eReturnStatusFailed);
1489     return false;
1490   }
1491 
1492   std::unique_ptr<StringSummaryFormat> string_format(
1493       new StringSummaryFormat(m_options.m_flags, format_cstr));
1494   if (!string_format) {
1495     result.AppendError("summary creation failed");
1496     result.SetStatus(eReturnStatusFailed);
1497     return false;
1498   }
1499   if (string_format->m_error.Fail()) {
1500     result.AppendErrorWithFormat("syntax error: %s",
1501                                  string_format->m_error.AsCString("<unknown>"));
1502     result.SetStatus(eReturnStatusFailed);
1503     return false;
1504   }
1505   lldb::TypeSummaryImplSP entry(string_format.release());
1506 
1507   // now I have a valid format, let's add it to every type
1508   Error error;
1509   for (size_t i = 0; i < argc; i++) {
1510     const char *typeA = command.GetArgumentAtIndex(i);
1511     if (!typeA || typeA[0] == '\0') {
1512       result.AppendError("empty typenames not allowed");
1513       result.SetStatus(eReturnStatusFailed);
1514       return false;
1515     }
1516     ConstString typeCS(typeA);
1517 
1518     AddSummary(typeCS, entry,
1519                (m_options.m_regex ? eRegexSummary : eRegularSummary),
1520                m_options.m_category, &error);
1521 
1522     if (error.Fail()) {
1523       result.AppendError(error.AsCString());
1524       result.SetStatus(eReturnStatusFailed);
1525       return false;
1526     }
1527   }
1528 
1529   if (m_options.m_name) {
1530     AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1531                &error);
1532     if (error.Fail()) {
1533       result.AppendError(error.AsCString());
1534       result.AppendError("added to types, but not given a name");
1535       result.SetStatus(eReturnStatusFailed);
1536       return false;
1537     }
1538   }
1539 
1540   result.SetStatus(eReturnStatusSuccessFinishNoResult);
1541   return result.Succeeded();
1542 }
1543 
1544 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1545     CommandInterpreter &interpreter)
1546     : CommandObjectParsed(interpreter, "type summary add",
1547                           "Add a new summary style for a type.", nullptr),
1548       IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1549   CommandArgumentEntry type_arg;
1550   CommandArgumentData type_style_arg;
1551 
1552   type_style_arg.arg_type = eArgTypeName;
1553   type_style_arg.arg_repetition = eArgRepeatPlus;
1554 
1555   type_arg.push_back(type_style_arg);
1556 
1557   m_arguments.push_back(type_arg);
1558 
1559   SetHelpLong(
1560       R"(
1561 The following examples of 'type summary add' refer to this code snippet for context:
1562 
1563     struct JustADemo
1564     {
1565         int* ptr;
1566         float value;
1567         JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1568     };
1569     JustADemo demo_instance(42, 3.14);
1570 
1571     typedef JustADemo NewDemo;
1572     NewDemo new_demo_instance(42, 3.14);
1573 
1574 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1575 
1576     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1577 
1578 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1579 
1580     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1581 
1582 )"
1583       "Alternatively, you could define formatting for all pointers to integers and \
1584 rely on that when formatting JustADemo to obtain the same result:"
1585       R"(
1586 
1587 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1588 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1589 
1590 )"
1591       "Type summaries are automatically applied to derived typedefs, so the examples \
1592 above apply to both JustADemo and NewDemo.  The cascade option can be used to \
1593 suppress this behavior:"
1594       R"(
1595 
1596 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1597 
1598     The summary will now be used for values of JustADemo but not NewDemo.
1599 
1600 )"
1601       "By default summaries are shown for pointers and references to values of the \
1602 specified type.  To suppress formatting for pointers use the -p option, or apply \
1603 the corresponding -r option to suppress formatting for references:"
1604       R"(
1605 
1606 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1607 
1608 )"
1609       "One-line summaries including all fields in a type can be inferred without supplying an \
1610 explicit summary string by passing the -c option:"
1611       R"(
1612 
1613 (lldb) type summary add -c JustADemo
1614 (lldb) frame variable demo_instance
1615 (ptr=<address>, value=3.14)
1616 
1617 )"
1618       "Type summaries normally suppress the nested display of individual fields.  To \
1619 supply a summary to supplement the default structure add the -e option:"
1620       R"(
1621 
1622 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1623 
1624 )"
1625       "Now when displaying JustADemo values the int* is displayed, followed by the \
1626 standard LLDB sequence of children, one per line:"
1627       R"(
1628 
1629 *ptr = 42 {
1630   ptr = <address>
1631   value = 3.14
1632 }
1633 
1634 )"
1635       "You can also add summaries written in Python.  These scripts use lldb public API to \
1636 gather information from your variables and produce a meaningful summary.  To start a \
1637 multi-line script use the -P option.  The function declaration will be displayed along with \
1638 a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
1639 itself:"
1640       R"(
1641 
1642 (lldb) type summary add JustADemo -P
1643 def function (valobj,internal_dict):
1644 """valobj: an SBValue which you want to provide a summary for
1645 internal_dict: an LLDB support object not to be used"""
1646     value = valobj.GetChildMemberWithName('value');
1647     return 'My value is ' + value.GetValue();
1648     DONE
1649 
1650 Alternatively, the -o option can be used when providing a simple one-line Python script:
1651 
1652 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1653 }
1654 
1655 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1656                                             CommandReturnObject &result) {
1657   WarnOnPotentialUnquotedUnsignedType(command, result);
1658 
1659   if (m_options.m_is_add_script) {
1660 #ifndef LLDB_DISABLE_PYTHON
1661     return Execute_ScriptSummary(command, result);
1662 #else
1663     result.AppendError("python is disabled");
1664     result.SetStatus(eReturnStatusFailed);
1665     return false;
1666 #endif // LLDB_DISABLE_PYTHON
1667   }
1668 
1669   return Execute_StringSummary(command, result);
1670 }
1671 
1672 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1673   llvm::StringRef type_name_ref(type_name.GetStringRef());
1674 
1675   if (type_name_ref.endswith("[]")) {
1676     std::string type_name_str(type_name.GetCString());
1677     type_name_str.resize(type_name_str.length() - 2);
1678     if (type_name_str.back() != ' ')
1679       type_name_str.append(" \\[[0-9]+\\]");
1680     else
1681       type_name_str.append("\\[[0-9]+\\]");
1682     type_name.SetCString(type_name_str.c_str());
1683     return true;
1684   }
1685   return false;
1686 }
1687 
1688 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1689                                              TypeSummaryImplSP entry,
1690                                              SummaryFormatType type,
1691                                              std::string category_name,
1692                                              Error *error) {
1693   lldb::TypeCategoryImplSP category;
1694   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1695                                              category);
1696 
1697   if (type == eRegularSummary) {
1698     if (FixArrayTypeNameWithRegex(type_name))
1699       type = eRegexSummary;
1700   }
1701 
1702   if (type == eRegexSummary) {
1703     RegularExpressionSP typeRX(new RegularExpression());
1704     if (!typeRX->Compile(type_name.GetStringRef())) {
1705       if (error)
1706         error->SetErrorString(
1707             "regex format error (maybe this is not really a regex?)");
1708       return false;
1709     }
1710 
1711     category->GetRegexTypeSummariesContainer()->Delete(type_name);
1712     category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1713 
1714     return true;
1715   } else if (type == eNamedSummary) {
1716     // system named summaries do not exist (yet?)
1717     DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1718     return true;
1719   } else {
1720     category->GetTypeSummariesContainer()->Add(type_name, entry);
1721     return true;
1722   }
1723 }
1724 
1725 //-------------------------------------------------------------------------
1726 // CommandObjectTypeSummaryDelete
1727 //-------------------------------------------------------------------------
1728 
1729 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1730 public:
1731   CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1732       : CommandObjectTypeFormatterDelete(
1733             interpreter,
1734             eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1735             "type summary delete", "Delete an existing summary for a type.") {}
1736 
1737   ~CommandObjectTypeSummaryDelete() override = default;
1738 
1739 protected:
1740   bool FormatterSpecificDeletion(ConstString typeCS) override {
1741     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1742       return false;
1743     return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1744   }
1745 };
1746 
1747 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1748 public:
1749   CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1750       : CommandObjectTypeFormatterClear(
1751             interpreter,
1752             eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1753             "type summary clear", "Delete all existing summaries.") {}
1754 
1755 protected:
1756   void FormatterSpecificDeletion() override {
1757     DataVisualization::NamedSummaryFormats::Clear();
1758   }
1759 };
1760 
1761 //-------------------------------------------------------------------------
1762 // CommandObjectTypeSummaryList
1763 //-------------------------------------------------------------------------
1764 
1765 class CommandObjectTypeSummaryList
1766     : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1767 public:
1768   CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1769       : CommandObjectTypeFormatterList(interpreter, "type summary list",
1770                                        "Show a list of current summaries.") {}
1771 
1772 protected:
1773   bool FormatterSpecificList(CommandReturnObject &result) override {
1774     if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1775       result.GetOutputStream().Printf("Named summaries:\n");
1776       DataVisualization::NamedSummaryFormats::ForEach(
1777           [&result](ConstString name,
1778                     const TypeSummaryImplSP &summary_sp) -> bool {
1779             result.GetOutputStream().Printf(
1780                 "%s: %s\n", name.AsCString(),
1781                 summary_sp->GetDescription().c_str());
1782             return true;
1783           });
1784       return true;
1785     }
1786     return false;
1787   }
1788 };
1789 
1790 //-------------------------------------------------------------------------
1791 // CommandObjectTypeCategoryDefine
1792 //-------------------------------------------------------------------------
1793 
1794 static OptionDefinition g_type_category_define_options[] = {
1795     // clang-format off
1796   { LLDB_OPT_SET_ALL, false, "enabled",  'e', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "If specified, this category will be created enabled." },
1797   { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
1798     // clang-format on
1799 };
1800 
1801 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1802   class CommandOptions : public Options {
1803   public:
1804     CommandOptions()
1805         : Options(), m_define_enabled(false, false),
1806           m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1807 
1808     ~CommandOptions() override = default;
1809 
1810     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1811                          ExecutionContext *execution_context) override {
1812       Error error;
1813       const int short_option = m_getopt_table[option_idx].val;
1814 
1815       switch (short_option) {
1816       case 'e':
1817         m_define_enabled.SetValueFromString("true");
1818         break;
1819       case 'l':
1820         error = m_cate_language.SetValueFromString(option_arg);
1821         break;
1822       default:
1823         error.SetErrorStringWithFormat("unrecognized option '%c'",
1824                                        short_option);
1825         break;
1826       }
1827 
1828       return error;
1829     }
1830 
1831     void OptionParsingStarting(ExecutionContext *execution_context) override {
1832       m_define_enabled.Clear();
1833       m_cate_language.Clear();
1834     }
1835 
1836     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1837       return llvm::makeArrayRef(g_type_category_define_options);
1838     }
1839 
1840     // Instance variables to hold the values for command options.
1841 
1842     OptionValueBoolean m_define_enabled;
1843     OptionValueLanguage m_cate_language;
1844   };
1845 
1846   CommandOptions m_options;
1847 
1848   Options *GetOptions() override { return &m_options; }
1849 
1850 public:
1851   CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1852       : CommandObjectParsed(interpreter, "type category define",
1853                             "Define a new category as a source of formatters.",
1854                             nullptr),
1855         m_options() {
1856     CommandArgumentEntry type_arg;
1857     CommandArgumentData type_style_arg;
1858 
1859     type_style_arg.arg_type = eArgTypeName;
1860     type_style_arg.arg_repetition = eArgRepeatPlus;
1861 
1862     type_arg.push_back(type_style_arg);
1863 
1864     m_arguments.push_back(type_arg);
1865   }
1866 
1867   ~CommandObjectTypeCategoryDefine() override = default;
1868 
1869 protected:
1870   bool DoExecute(Args &command, CommandReturnObject &result) override {
1871     const size_t argc = command.GetArgumentCount();
1872 
1873     if (argc < 1) {
1874       result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1875                                    m_cmd_name.c_str());
1876       result.SetStatus(eReturnStatusFailed);
1877       return false;
1878     }
1879 
1880     for (size_t i = 0; i < argc; i++) {
1881       const char *cateName = command.GetArgumentAtIndex(i);
1882       TypeCategoryImplSP category_sp;
1883       if (DataVisualization::Categories::GetCategory(ConstString(cateName),
1884                                                      category_sp) &&
1885           category_sp) {
1886         category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1887         if (m_options.m_define_enabled.GetCurrentValue())
1888           DataVisualization::Categories::Enable(category_sp,
1889                                                 TypeCategoryMap::Default);
1890       }
1891     }
1892 
1893     result.SetStatus(eReturnStatusSuccessFinishResult);
1894     return result.Succeeded();
1895   }
1896 };
1897 
1898 //-------------------------------------------------------------------------
1899 // CommandObjectTypeCategoryEnable
1900 //-------------------------------------------------------------------------
1901 
1902 static OptionDefinition g_type_category_enable_options[] = {
1903     // clang-format off
1904   { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." },
1905     // clang-format on
1906 };
1907 
1908 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1909   class CommandOptions : public Options {
1910   public:
1911     CommandOptions() : Options() {}
1912 
1913     ~CommandOptions() override = default;
1914 
1915     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1916                          ExecutionContext *execution_context) override {
1917       Error error;
1918       const int short_option = m_getopt_table[option_idx].val;
1919 
1920       switch (short_option) {
1921       case 'l':
1922         if (option_arg) {
1923           m_language = Language::GetLanguageTypeFromString(option_arg);
1924           if (m_language == lldb::eLanguageTypeUnknown)
1925             error.SetErrorStringWithFormat("unrecognized language '%s'",
1926                                            option_arg);
1927         }
1928         break;
1929       default:
1930         error.SetErrorStringWithFormat("unrecognized option '%c'",
1931                                        short_option);
1932         break;
1933       }
1934 
1935       return error;
1936     }
1937 
1938     void OptionParsingStarting(ExecutionContext *execution_context) override {
1939       m_language = lldb::eLanguageTypeUnknown;
1940     }
1941 
1942     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1943       return llvm::makeArrayRef(g_type_category_enable_options);
1944     }
1945 
1946     // Instance variables to hold the values for command options.
1947 
1948     lldb::LanguageType m_language;
1949   };
1950 
1951   CommandOptions m_options;
1952 
1953   Options *GetOptions() override { return &m_options; }
1954 
1955 public:
1956   CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1957       : CommandObjectParsed(interpreter, "type category enable",
1958                             "Enable a category as a source of formatters.",
1959                             nullptr),
1960         m_options() {
1961     CommandArgumentEntry type_arg;
1962     CommandArgumentData type_style_arg;
1963 
1964     type_style_arg.arg_type = eArgTypeName;
1965     type_style_arg.arg_repetition = eArgRepeatPlus;
1966 
1967     type_arg.push_back(type_style_arg);
1968 
1969     m_arguments.push_back(type_arg);
1970   }
1971 
1972   ~CommandObjectTypeCategoryEnable() override = default;
1973 
1974 protected:
1975   bool DoExecute(Args &command, CommandReturnObject &result) override {
1976     const size_t argc = command.GetArgumentCount();
1977 
1978     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1979       result.AppendErrorWithFormat("%s takes arguments and/or a language",
1980                                    m_cmd_name.c_str());
1981       result.SetStatus(eReturnStatusFailed);
1982       return false;
1983     }
1984 
1985     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1986       DataVisualization::Categories::EnableStar();
1987     } else if (argc > 0) {
1988       for (int i = argc - 1; i >= 0; i--) {
1989         const char *typeA = command.GetArgumentAtIndex(i);
1990         ConstString typeCS(typeA);
1991 
1992         if (!typeCS) {
1993           result.AppendError("empty category name not allowed");
1994           result.SetStatus(eReturnStatusFailed);
1995           return false;
1996         }
1997         DataVisualization::Categories::Enable(typeCS);
1998         lldb::TypeCategoryImplSP cate;
1999         if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
2000           if (cate->GetCount() == 0) {
2001             result.AppendWarning("empty category enabled (typo?)");
2002           }
2003         }
2004       }
2005     }
2006 
2007     if (m_options.m_language != lldb::eLanguageTypeUnknown)
2008       DataVisualization::Categories::Enable(m_options.m_language);
2009 
2010     result.SetStatus(eReturnStatusSuccessFinishResult);
2011     return result.Succeeded();
2012   }
2013 };
2014 
2015 //-------------------------------------------------------------------------
2016 // CommandObjectTypeCategoryDelete
2017 //-------------------------------------------------------------------------
2018 
2019 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
2020 public:
2021   CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
2022       : CommandObjectParsed(interpreter, "type category delete",
2023                             "Delete a category and all associated formatters.",
2024                             nullptr) {
2025     CommandArgumentEntry type_arg;
2026     CommandArgumentData type_style_arg;
2027 
2028     type_style_arg.arg_type = eArgTypeName;
2029     type_style_arg.arg_repetition = eArgRepeatPlus;
2030 
2031     type_arg.push_back(type_style_arg);
2032 
2033     m_arguments.push_back(type_arg);
2034   }
2035 
2036   ~CommandObjectTypeCategoryDelete() override = default;
2037 
2038 protected:
2039   bool DoExecute(Args &command, CommandReturnObject &result) override {
2040     const size_t argc = command.GetArgumentCount();
2041 
2042     if (argc < 1) {
2043       result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
2044                                    m_cmd_name.c_str());
2045       result.SetStatus(eReturnStatusFailed);
2046       return false;
2047     }
2048 
2049     bool success = true;
2050 
2051     // the order is not relevant here
2052     for (int i = argc - 1; i >= 0; i--) {
2053       const char *typeA = command.GetArgumentAtIndex(i);
2054       ConstString typeCS(typeA);
2055 
2056       if (!typeCS) {
2057         result.AppendError("empty category name not allowed");
2058         result.SetStatus(eReturnStatusFailed);
2059         return false;
2060       }
2061       if (!DataVisualization::Categories::Delete(typeCS))
2062         success = false; // keep deleting even if we hit an error
2063     }
2064     if (success) {
2065       result.SetStatus(eReturnStatusSuccessFinishResult);
2066       return result.Succeeded();
2067     } else {
2068       result.AppendError("cannot delete one or more categories\n");
2069       result.SetStatus(eReturnStatusFailed);
2070       return false;
2071     }
2072   }
2073 };
2074 
2075 //-------------------------------------------------------------------------
2076 // CommandObjectTypeCategoryDisable
2077 //-------------------------------------------------------------------------
2078 
2079 OptionDefinition g_type_category_disable_options[] = {
2080     // clang-format off
2081   { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." }
2082     // clang-format on
2083 };
2084 
2085 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
2086   class CommandOptions : public Options {
2087   public:
2088     CommandOptions() : Options() {}
2089 
2090     ~CommandOptions() override = default;
2091 
2092     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2093                          ExecutionContext *execution_context) override {
2094       Error error;
2095       const int short_option = m_getopt_table[option_idx].val;
2096 
2097       switch (short_option) {
2098       case 'l':
2099         if (option_arg) {
2100           m_language = Language::GetLanguageTypeFromString(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   const size_t argc = command.GetArgumentCount();
2357 
2358   for (size_t i = 0; i < argc; i++) {
2359     const char *typeA = command.GetArgumentAtIndex(i);
2360     if (typeA && *typeA)
2361       options->m_target_types << typeA;
2362     else {
2363       result.AppendError("empty typenames not allowed");
2364       result.SetStatus(eReturnStatusFailed);
2365       return false;
2366     }
2367   }
2368 
2369   m_interpreter.GetPythonCommandsFromIOHandler(
2370       "    ",   // Prompt
2371       *this,    // IOHandlerDelegate
2372       true,     // Run IOHandler in async mode
2373       options); // Baton for the "io_handler" that will be passed back into our
2374                 // IOHandlerDelegate functions
2375   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2376   return result.Succeeded();
2377 }
2378 
2379 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2380     Args &command, CommandReturnObject &result) {
2381   const size_t argc = command.GetArgumentCount();
2382 
2383   if (argc < 1) {
2384     result.AppendErrorWithFormat("%s takes one or more args.\n",
2385                                  m_cmd_name.c_str());
2386     result.SetStatus(eReturnStatusFailed);
2387     return false;
2388   }
2389 
2390   if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2391     result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2392                                  "directly input Python code.\n",
2393                                  m_cmd_name.c_str());
2394     result.SetStatus(eReturnStatusFailed);
2395     return false;
2396   }
2397 
2398   SyntheticChildrenSP entry;
2399 
2400   ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2401       SyntheticChildren::Flags()
2402           .SetCascades(m_options.m_cascade)
2403           .SetSkipPointers(m_options.m_skip_pointers)
2404           .SetSkipReferences(m_options.m_skip_references),
2405       m_options.m_class_name.c_str());
2406 
2407   entry.reset(impl);
2408 
2409   ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
2410 
2411   if (interpreter &&
2412       !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2413     result.AppendWarning("The provided class does not exist - please define it "
2414                          "before attempting to use this synthetic provider");
2415 
2416   // now I have a valid provider, let's add it to every type
2417 
2418   lldb::TypeCategoryImplSP category;
2419   DataVisualization::Categories::GetCategory(
2420       ConstString(m_options.m_category.c_str()), category);
2421 
2422   Error error;
2423 
2424   for (size_t i = 0; i < argc; i++) {
2425     const char *typeA = command.GetArgumentAtIndex(i);
2426     ConstString typeCS(typeA);
2427     if (typeCS) {
2428       if (!AddSynth(typeCS, entry,
2429                     m_options.m_regex ? eRegexSynth : eRegularSynth,
2430                     m_options.m_category, &error)) {
2431         result.AppendError(error.AsCString());
2432         result.SetStatus(eReturnStatusFailed);
2433         return false;
2434       }
2435     } else {
2436       result.AppendError("empty typenames not allowed");
2437       result.SetStatus(eReturnStatusFailed);
2438       return false;
2439     }
2440   }
2441 
2442   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2443   return result.Succeeded();
2444 }
2445 
2446 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2447     CommandInterpreter &interpreter)
2448     : CommandObjectParsed(interpreter, "type synthetic add",
2449                           "Add a new synthetic provider for a type.", nullptr),
2450       IOHandlerDelegateMultiline("DONE"), m_options() {
2451   CommandArgumentEntry type_arg;
2452   CommandArgumentData type_style_arg;
2453 
2454   type_style_arg.arg_type = eArgTypeName;
2455   type_style_arg.arg_repetition = eArgRepeatPlus;
2456 
2457   type_arg.push_back(type_style_arg);
2458 
2459   m_arguments.push_back(type_arg);
2460 }
2461 
2462 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2463                                          SyntheticChildrenSP entry,
2464                                          SynthFormatType type,
2465                                          std::string category_name,
2466                                          Error *error) {
2467   lldb::TypeCategoryImplSP category;
2468   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2469                                              category);
2470 
2471   if (type == eRegularSynth) {
2472     if (FixArrayTypeNameWithRegex(type_name))
2473       type = eRegexSynth;
2474   }
2475 
2476   if (category->AnyMatches(type_name, eFormatCategoryItemFilter |
2477                                           eFormatCategoryItemRegexFilter,
2478                            false)) {
2479     if (error)
2480       error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2481                                       "filter is defined in same category!",
2482                                       type_name.AsCString());
2483     return false;
2484   }
2485 
2486   if (type == eRegexSynth) {
2487     RegularExpressionSP typeRX(new RegularExpression());
2488     if (!typeRX->Compile(type_name.GetStringRef())) {
2489       if (error)
2490         error->SetErrorString(
2491             "regex format error (maybe this is not really a regex?)");
2492       return false;
2493     }
2494 
2495     category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2496     category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
2497 
2498     return true;
2499   } else {
2500     category->GetTypeSyntheticsContainer()->Add(type_name, entry);
2501     return true;
2502   }
2503 }
2504 
2505 #endif // LLDB_DISABLE_PYTHON
2506 
2507 static OptionDefinition g_type_filter_add_options[] = {
2508     // clang-format off
2509   { LLDB_OPT_SET_ALL, false, "cascade",         'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,        "If true, cascade through typedef chains." },
2510   { LLDB_OPT_SET_ALL, false, "skip-pointers",   'p', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,           "Don't use this format for pointers-to-type objects." },
2511   { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,           "Don't use this format for references-to-type objects." },
2512   { LLDB_OPT_SET_ALL, false, "category",        'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,           "Add this to the given category instead of the default one." },
2513   { LLDB_OPT_SET_ALL, false, "child",           'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
2514   { LLDB_OPT_SET_ALL, false, "regex",           'x', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,           "Type names are actually regular expressions." }
2515     // clang-format on
2516 };
2517 
2518 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2519 private:
2520   class CommandOptions : public Options {
2521     typedef std::vector<std::string> option_vector;
2522 
2523   public:
2524     CommandOptions() : Options() {}
2525 
2526     ~CommandOptions() override = default;
2527 
2528     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2529                          ExecutionContext *execution_context) override {
2530       Error error;
2531       const int short_option = m_getopt_table[option_idx].val;
2532       bool success;
2533 
2534       switch (short_option) {
2535       case 'C':
2536         m_cascade = Args::StringToBoolean(
2537             llvm::StringRef::withNullAsEmpty(option_arg), true, &success);
2538         if (!success)
2539           error.SetErrorStringWithFormat("invalid value for cascade: %s",
2540                                          option_arg);
2541         break;
2542       case 'c':
2543         m_expr_paths.push_back(option_arg);
2544         has_child_list = true;
2545         break;
2546       case 'p':
2547         m_skip_pointers = true;
2548         break;
2549       case 'r':
2550         m_skip_references = true;
2551         break;
2552       case 'w':
2553         m_category = std::string(option_arg);
2554         break;
2555       case 'x':
2556         m_regex = true;
2557         break;
2558       default:
2559         error.SetErrorStringWithFormat("unrecognized option '%c'",
2560                                        short_option);
2561         break;
2562       }
2563 
2564       return error;
2565     }
2566 
2567     void OptionParsingStarting(ExecutionContext *execution_context) override {
2568       m_cascade = true;
2569       m_skip_pointers = false;
2570       m_skip_references = false;
2571       m_category = "default";
2572       m_expr_paths.clear();
2573       has_child_list = false;
2574       m_regex = false;
2575     }
2576 
2577     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2578       return llvm::makeArrayRef(g_type_filter_add_options);
2579     }
2580 
2581     // Instance variables to hold the values for command options.
2582 
2583     bool m_cascade;
2584     bool m_skip_references;
2585     bool m_skip_pointers;
2586     bool m_input_python;
2587     option_vector m_expr_paths;
2588     std::string m_category;
2589     bool has_child_list;
2590     bool m_regex;
2591 
2592     typedef option_vector::iterator ExpressionPathsIterator;
2593   };
2594 
2595   CommandOptions m_options;
2596 
2597   Options *GetOptions() override { return &m_options; }
2598 
2599   enum FilterFormatType { eRegularFilter, eRegexFilter };
2600 
2601   bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2602                  FilterFormatType type, std::string category_name,
2603                  Error *error) {
2604     lldb::TypeCategoryImplSP category;
2605     DataVisualization::Categories::GetCategory(
2606         ConstString(category_name.c_str()), category);
2607 
2608     if (type == eRegularFilter) {
2609       if (FixArrayTypeNameWithRegex(type_name))
2610         type = eRegexFilter;
2611     }
2612 
2613     if (category->AnyMatches(type_name, eFormatCategoryItemSynth |
2614                                             eFormatCategoryItemRegexSynth,
2615                              false)) {
2616       if (error)
2617         error->SetErrorStringWithFormat("cannot add filter for type %s when "
2618                                         "synthetic is defined in same "
2619                                         "category!",
2620                                         type_name.AsCString());
2621       return false;
2622     }
2623 
2624     if (type == eRegexFilter) {
2625       RegularExpressionSP typeRX(new RegularExpression());
2626       if (!typeRX->Compile(type_name.GetStringRef())) {
2627         if (error)
2628           error->SetErrorString(
2629               "regex format error (maybe this is not really a regex?)");
2630         return false;
2631       }
2632 
2633       category->GetRegexTypeFiltersContainer()->Delete(type_name);
2634       category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
2635 
2636       return true;
2637     } else {
2638       category->GetTypeFiltersContainer()->Add(type_name, entry);
2639       return true;
2640     }
2641   }
2642 
2643 public:
2644   CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2645       : CommandObjectParsed(interpreter, "type filter add",
2646                             "Add a new filter for a type.", nullptr),
2647         m_options() {
2648     CommandArgumentEntry type_arg;
2649     CommandArgumentData type_style_arg;
2650 
2651     type_style_arg.arg_type = eArgTypeName;
2652     type_style_arg.arg_repetition = eArgRepeatPlus;
2653 
2654     type_arg.push_back(type_style_arg);
2655 
2656     m_arguments.push_back(type_arg);
2657 
2658     SetHelpLong(
2659         R"(
2660 The following examples of 'type filter add' refer to this code snippet for context:
2661 
2662     class Foo {
2663         int a;
2664         int b;
2665         int c;
2666         int d;
2667         int e;
2668         int f;
2669         int g;
2670         int h;
2671         int i;
2672     }
2673     Foo my_foo;
2674 
2675 Adding a simple filter:
2676 
2677 (lldb) type filter add --child a --child g Foo
2678 (lldb) frame variable my_foo
2679 
2680 )"
2681         "Produces output where only a and g are displayed.  Other children of my_foo \
2682 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2683         R"(
2684 
2685 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2686 
2687 )"
2688         "The formatting option --raw on frame variable bypasses the filter, showing \
2689 all children of my_foo as if no filter was defined:"
2690         R"(
2691 
2692 (lldb) frame variable my_foo --raw)");
2693   }
2694 
2695   ~CommandObjectTypeFilterAdd() override = default;
2696 
2697 protected:
2698   bool DoExecute(Args &command, CommandReturnObject &result) override {
2699     const size_t argc = command.GetArgumentCount();
2700 
2701     if (argc < 1) {
2702       result.AppendErrorWithFormat("%s takes one or more args.\n",
2703                                    m_cmd_name.c_str());
2704       result.SetStatus(eReturnStatusFailed);
2705       return false;
2706     }
2707 
2708     if (m_options.m_expr_paths.empty()) {
2709       result.AppendErrorWithFormat("%s needs one or more children.\n",
2710                                    m_cmd_name.c_str());
2711       result.SetStatus(eReturnStatusFailed);
2712       return false;
2713     }
2714 
2715     TypeFilterImplSP entry(new TypeFilterImpl(
2716         SyntheticChildren::Flags()
2717             .SetCascades(m_options.m_cascade)
2718             .SetSkipPointers(m_options.m_skip_pointers)
2719             .SetSkipReferences(m_options.m_skip_references)));
2720 
2721     // go through the expression paths
2722     CommandOptions::ExpressionPathsIterator begin,
2723         end = m_options.m_expr_paths.end();
2724 
2725     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2726       entry->AddExpressionPath(*begin);
2727 
2728     // now I have a valid provider, let's add it to every type
2729 
2730     lldb::TypeCategoryImplSP category;
2731     DataVisualization::Categories::GetCategory(
2732         ConstString(m_options.m_category.c_str()), category);
2733 
2734     Error error;
2735 
2736     WarnOnPotentialUnquotedUnsignedType(command, result);
2737 
2738     for (size_t i = 0; i < argc; i++) {
2739       const char *typeA = command.GetArgumentAtIndex(i);
2740       ConstString typeCS(typeA);
2741       if (typeCS) {
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       } else {
2750         result.AppendError("empty typenames not allowed");
2751         result.SetStatus(eReturnStatusFailed);
2752         return false;
2753       }
2754     }
2755 
2756     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2757     return result.Succeeded();
2758   }
2759 };
2760 
2761 //----------------------------------------------------------------------
2762 // "type lookup"
2763 //----------------------------------------------------------------------
2764 static OptionDefinition g_type_lookup_options[] = {
2765     // clang-format off
2766   { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Display available help for types" },
2767   { LLDB_OPT_SET_ALL, false, "language",  'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
2768     // clang-format on
2769 };
2770 
2771 class CommandObjectTypeLookup : public CommandObjectRaw {
2772 protected:
2773   // this function is allowed to do a more aggressive job at guessing languages
2774   // than the expression parser
2775   // is comfortable with - so leave the original call alone and add one that is
2776   // specific to type lookup
2777   lldb::LanguageType GuessLanguage(StackFrame *frame) {
2778     lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2779 
2780     if (!frame)
2781       return lang_type;
2782 
2783     lang_type = frame->GuessLanguage();
2784     if (lang_type != lldb::eLanguageTypeUnknown)
2785       return lang_type;
2786 
2787     Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2788     if (s)
2789       lang_type = s->GetMangled().GuessLanguage();
2790 
2791     return lang_type;
2792   }
2793 
2794   class CommandOptions : public OptionGroup {
2795   public:
2796     CommandOptions()
2797         : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
2798 
2799     ~CommandOptions() override = default;
2800 
2801     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2802       return llvm::makeArrayRef(g_type_lookup_options);
2803     }
2804 
2805     Error SetOptionValue(uint32_t option_idx, const char *option_value,
2806                          ExecutionContext *execution_context) override {
2807       Error error;
2808 
2809       const int short_option = g_type_lookup_options[option_idx].short_option;
2810 
2811       switch (short_option) {
2812       case 'h':
2813         m_show_help = true;
2814         break;
2815 
2816       case 'l':
2817         m_language = Language::GetLanguageTypeFromString(option_value);
2818         break;
2819 
2820       default:
2821         error.SetErrorStringWithFormat("invalid short option character '%c'",
2822                                        short_option);
2823         break;
2824       }
2825 
2826       return error;
2827     }
2828 
2829     void OptionParsingStarting(ExecutionContext *execution_context) override {
2830       m_show_help = false;
2831       m_language = eLanguageTypeUnknown;
2832     }
2833 
2834     // Options table: Required for subclasses of Options.
2835 
2836     bool m_show_help;
2837     lldb::LanguageType m_language;
2838   };
2839 
2840   OptionGroupOptions m_option_group;
2841   CommandOptions m_command_options;
2842 
2843 public:
2844   CommandObjectTypeLookup(CommandInterpreter &interpreter)
2845       : CommandObjectRaw(interpreter, "type lookup",
2846                          "Lookup types and declarations in the current target, "
2847                          "following language-specific naming conventions.",
2848                          "type lookup <type-specifier>",
2849                          eCommandRequiresTarget),
2850         m_option_group(), m_command_options() {
2851     m_option_group.Append(&m_command_options);
2852     m_option_group.Finalize();
2853   }
2854 
2855   ~CommandObjectTypeLookup() override = default;
2856 
2857   Options *GetOptions() override { return &m_option_group; }
2858 
2859   const char *GetHelpLong() override {
2860     if (m_cmd_help_long.empty()) {
2861       StreamString stream;
2862       // FIXME: hardcoding languages is not good
2863       lldb::LanguageType languages[] = {eLanguageTypeObjC,
2864                                         eLanguageTypeC_plus_plus};
2865 
2866       for (const auto lang_type : languages) {
2867         if (auto language = Language::FindPlugin(lang_type)) {
2868           if (const char *help =
2869                   language->GetLanguageSpecificTypeLookupHelp()) {
2870             stream.Printf("%s\n", help);
2871           }
2872         }
2873       }
2874 
2875       if (stream.GetData())
2876         m_cmd_help_long.assign(stream.GetString());
2877     }
2878     return this->CommandObject::GetHelpLong();
2879   }
2880 
2881   bool DoExecute(const char *raw_command_line,
2882                  CommandReturnObject &result) override {
2883     if (!raw_command_line || !raw_command_line[0]) {
2884       result.SetError(
2885           "type lookup cannot be invoked without a type name as argument");
2886       return false;
2887     }
2888 
2889     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2890     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2891 
2892     const char *name_of_type = nullptr;
2893 
2894     if (raw_command_line[0] == '-') {
2895       // We have some options and these options MUST end with --.
2896       const char *end_options = nullptr;
2897       const char *s = raw_command_line;
2898       while (s && s[0]) {
2899         end_options = ::strstr(s, "--");
2900         if (end_options) {
2901           end_options += 2; // Get past the "--"
2902           if (::isspace(end_options[0])) {
2903             name_of_type = end_options;
2904             while (::isspace(*name_of_type))
2905               ++name_of_type;
2906             break;
2907           }
2908         }
2909         s = end_options;
2910       }
2911 
2912       if (end_options) {
2913         Args args(
2914             llvm::StringRef(raw_command_line, end_options - raw_command_line));
2915         if (!ParseOptions(args, result))
2916           return false;
2917 
2918         Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
2919         if (error.Fail()) {
2920           result.AppendError(error.AsCString());
2921           result.SetStatus(eReturnStatusFailed);
2922           return false;
2923         }
2924       }
2925     }
2926     if (nullptr == name_of_type)
2927       name_of_type = raw_command_line;
2928 
2929     // TargetSP
2930     // target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
2931     // const bool fill_all_in = true;
2932     // ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
2933     ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2934 
2935     bool any_found = false;
2936 
2937     std::vector<Language *> languages;
2938 
2939     bool is_global_search = false;
2940     LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2941 
2942     if ((is_global_search =
2943              (m_command_options.m_language == eLanguageTypeUnknown))) {
2944       // FIXME: hardcoding languages is not good
2945       languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
2946       languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
2947     } else {
2948       languages.push_back(Language::FindPlugin(m_command_options.m_language));
2949     }
2950 
2951     // This is not the most efficient way to do this, but we support very few
2952     // languages
2953     // so the cost of the sort is going to be dwarfed by the actual lookup
2954     // anyway
2955     if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2956       guessed_language = GuessLanguage(frame);
2957       if (guessed_language != eLanguageTypeUnknown) {
2958         std::sort(
2959             languages.begin(), languages.end(),
2960             [guessed_language](Language *lang1, Language *lang2) -> bool {
2961               if (!lang1 || !lang2)
2962                 return false;
2963               LanguageType lt1 = lang1->GetLanguageType();
2964               LanguageType lt2 = lang2->GetLanguageType();
2965               if (lt1 == guessed_language)
2966                 return true; // make the selected frame's language come first
2967               if (lt2 == guessed_language)
2968                 return false; // make the selected frame's language come first
2969               return (lt1 < lt2); // normal comparison otherwise
2970             });
2971       }
2972     }
2973 
2974     bool is_first_language = true;
2975 
2976     for (Language *language : languages) {
2977       if (!language)
2978         continue;
2979 
2980       if (auto scavenger = language->GetTypeScavenger()) {
2981         Language::TypeScavenger::ResultSet search_results;
2982         if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2983           for (const auto &search_result : search_results) {
2984             if (search_result && search_result->IsValid()) {
2985               any_found = true;
2986               search_result->DumpToStream(result.GetOutputStream(),
2987                                           this->m_command_options.m_show_help);
2988             }
2989           }
2990         }
2991       }
2992       // this is "type lookup SomeName" and we did find a match, so get out
2993       if (any_found && is_global_search)
2994         break;
2995       else if (is_first_language && is_global_search &&
2996                guessed_language != lldb::eLanguageTypeUnknown) {
2997         is_first_language = false;
2998         result.GetOutputStream().Printf(
2999             "no type was found in the current language %s matching '%s'; "
3000             "performing a global search across all languages\n",
3001             Language::GetNameForLanguageType(guessed_language), name_of_type);
3002       }
3003     }
3004 
3005     if (!any_found)
3006       result.AppendMessageWithFormat("no type was found matching '%s'\n",
3007                                      name_of_type);
3008 
3009     result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
3010                                : lldb::eReturnStatusSuccessFinishNoResult);
3011     return true;
3012   }
3013 };
3014 
3015 template <typename FormatterType>
3016 class CommandObjectFormatterInfo : public CommandObjectRaw {
3017 public:
3018   typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
3019       DiscoveryFunction;
3020   CommandObjectFormatterInfo(CommandInterpreter &interpreter,
3021                              const char *formatter_name,
3022                              DiscoveryFunction discovery_func)
3023       : CommandObjectRaw(interpreter, nullptr, nullptr, nullptr,
3024                          eCommandRequiresFrame),
3025         m_formatter_name(formatter_name ? formatter_name : ""),
3026         m_discovery_function(discovery_func) {
3027     StreamString name;
3028     name.Printf("type %s info", formatter_name);
3029     SetCommandName(name.GetData());
3030     StreamString help;
3031     help.Printf("This command evaluates the provided expression and shows "
3032                 "which %s is applied to the resulting value (if any).",
3033                 formatter_name);
3034     SetHelp(help.GetData());
3035     StreamString syntax;
3036     syntax.Printf("type %s info <expr>", formatter_name);
3037     SetSyntax(syntax.GetData());
3038   }
3039 
3040   ~CommandObjectFormatterInfo() override = default;
3041 
3042 protected:
3043   bool DoExecute(const char *command, CommandReturnObject &result) override {
3044     TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
3045     Thread *thread = GetDefaultThread();
3046     if (!thread) {
3047       result.AppendError("no default thread");
3048       result.SetStatus(lldb::eReturnStatusFailed);
3049       return false;
3050     }
3051 
3052     StackFrameSP frame_sp = thread->GetSelectedFrame();
3053     ValueObjectSP result_valobj_sp;
3054     EvaluateExpressionOptions options;
3055     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
3056         command, frame_sp.get(), result_valobj_sp, options);
3057     if (expr_result == eExpressionCompleted && result_valobj_sp) {
3058       result_valobj_sp =
3059           result_valobj_sp->GetQualifiedRepresentationIfAvailable(
3060               target_sp->GetPreferDynamicValue(),
3061               target_sp->GetEnableSyntheticValue());
3062       typename FormatterType::SharedPointer formatter_sp =
3063           m_discovery_function(*result_valobj_sp);
3064       if (formatter_sp) {
3065         std::string description(formatter_sp->GetDescription());
3066         result.AppendMessageWithFormat(
3067             "%s applied to (%s) %s is: %s\n", m_formatter_name.c_str(),
3068             result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3069             command, description.c_str());
3070         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
3071       } else {
3072         result.AppendMessageWithFormat(
3073             "no %s applies to (%s) %s\n", m_formatter_name.c_str(),
3074             result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3075             command);
3076         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
3077       }
3078       return true;
3079     } else {
3080       result.AppendError("failed to evaluate expression");
3081       result.SetStatus(lldb::eReturnStatusFailed);
3082       return false;
3083     }
3084   }
3085 
3086 private:
3087   std::string m_formatter_name;
3088   DiscoveryFunction m_discovery_function;
3089 };
3090 
3091 class CommandObjectTypeFormat : public CommandObjectMultiword {
3092 public:
3093   CommandObjectTypeFormat(CommandInterpreter &interpreter)
3094       : CommandObjectMultiword(
3095             interpreter, "type format",
3096             "Commands for customizing value display formats.",
3097             "type format [<sub-command-options>] ") {
3098     LoadSubCommand(
3099         "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
3100     LoadSubCommand("clear", CommandObjectSP(
3101                                 new CommandObjectTypeFormatClear(interpreter)));
3102     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
3103                                  interpreter)));
3104     LoadSubCommand(
3105         "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
3106     LoadSubCommand(
3107         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
3108                     interpreter, "format",
3109                     [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
3110                       return valobj.GetValueFormat();
3111                     })));
3112   }
3113 
3114   ~CommandObjectTypeFormat() override = default;
3115 };
3116 
3117 #ifndef LLDB_DISABLE_PYTHON
3118 
3119 class CommandObjectTypeSynth : public CommandObjectMultiword {
3120 public:
3121   CommandObjectTypeSynth(CommandInterpreter &interpreter)
3122       : CommandObjectMultiword(
3123             interpreter, "type synthetic",
3124             "Commands for operating on synthetic type representations.",
3125             "type synthetic [<sub-command-options>] ") {
3126     LoadSubCommand("add",
3127                    CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
3128     LoadSubCommand(
3129         "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
3130     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
3131                                  interpreter)));
3132     LoadSubCommand(
3133         "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
3134     LoadSubCommand(
3135         "info",
3136         CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
3137             interpreter, "synthetic",
3138             [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
3139               return valobj.GetSyntheticChildren();
3140             })));
3141   }
3142 
3143   ~CommandObjectTypeSynth() override = default;
3144 };
3145 
3146 #endif // LLDB_DISABLE_PYTHON
3147 
3148 class CommandObjectTypeFilter : public CommandObjectMultiword {
3149 public:
3150   CommandObjectTypeFilter(CommandInterpreter &interpreter)
3151       : CommandObjectMultiword(interpreter, "type filter",
3152                                "Commands for operating on type filters.",
3153                                "type synthetic [<sub-command-options>] ") {
3154     LoadSubCommand(
3155         "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
3156     LoadSubCommand("clear", CommandObjectSP(
3157                                 new CommandObjectTypeFilterClear(interpreter)));
3158     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
3159                                  interpreter)));
3160     LoadSubCommand(
3161         "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
3162   }
3163 
3164   ~CommandObjectTypeFilter() override = default;
3165 };
3166 
3167 class CommandObjectTypeCategory : public CommandObjectMultiword {
3168 public:
3169   CommandObjectTypeCategory(CommandInterpreter &interpreter)
3170       : CommandObjectMultiword(interpreter, "type category",
3171                                "Commands for operating on type categories.",
3172                                "type category [<sub-command-options>] ") {
3173     LoadSubCommand(
3174         "define",
3175         CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3176     LoadSubCommand(
3177         "enable",
3178         CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3179     LoadSubCommand(
3180         "disable",
3181         CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3182     LoadSubCommand(
3183         "delete",
3184         CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3185     LoadSubCommand("list", CommandObjectSP(
3186                                new CommandObjectTypeCategoryList(interpreter)));
3187   }
3188 
3189   ~CommandObjectTypeCategory() override = default;
3190 };
3191 
3192 class CommandObjectTypeSummary : public CommandObjectMultiword {
3193 public:
3194   CommandObjectTypeSummary(CommandInterpreter &interpreter)
3195       : CommandObjectMultiword(
3196             interpreter, "type summary",
3197             "Commands for editing variable summary display options.",
3198             "type summary [<sub-command-options>] ") {
3199     LoadSubCommand(
3200         "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3201     LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3202                                 interpreter)));
3203     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3204                                  interpreter)));
3205     LoadSubCommand(
3206         "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3207     LoadSubCommand(
3208         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3209                     interpreter, "summary",
3210                     [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3211                       return valobj.GetSummaryFormat();
3212                     })));
3213   }
3214 
3215   ~CommandObjectTypeSummary() override = default;
3216 };
3217 
3218 //-------------------------------------------------------------------------
3219 // CommandObjectType
3220 //-------------------------------------------------------------------------
3221 
3222 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3223     : CommandObjectMultiword(interpreter, "type",
3224                              "Commands for operating on the type system.",
3225                              "type [<sub-command-options>]") {
3226   LoadSubCommand("category",
3227                  CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3228   LoadSubCommand("filter",
3229                  CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3230   LoadSubCommand("format",
3231                  CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3232   LoadSubCommand("summary",
3233                  CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3234 #ifndef LLDB_DISABLE_PYTHON
3235   LoadSubCommand("synthetic",
3236                  CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3237 #endif // LLDB_DISABLE_PYTHON
3238   LoadSubCommand("lookup",
3239                  CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3240 }
3241 
3242 CommandObjectType::~CommandObjectType() = default;
3243