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