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