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