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