1 //===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CommandObjectType.h"
10 
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/Host/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(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(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.reset(new 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.reset(
1048           new RegularExpression(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                       ConstString name,
1070                       const FormatterSharedPointer &format_sp) -> bool {
1071           if (formatter_regex) {
1072             bool escape = true;
1073             if (name.GetStringRef() == formatter_regex->GetText()) {
1074               escape = false;
1075             } else if (formatter_regex->Execute(name.GetStringRef())) {
1076               escape = false;
1077             }
1078 
1079             if (escape)
1080               return true;
1081           }
1082 
1083           any_printed = true;
1084           result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1085                                           format_sp->GetDescription().c_str());
1086           return true;
1087         });
1088 
1089       foreach
1090         .SetWithRegex([&result, &formatter_regex, &any_printed](
1091                           const RegularExpression &regex,
1092                           const FormatterSharedPointer &format_sp) -> bool {
1093           if (formatter_regex) {
1094             bool escape = true;
1095             if (regex.GetText() == formatter_regex->GetText()) {
1096               escape = false;
1097             } else if (formatter_regex->Execute(regex.GetText())) {
1098               escape = false;
1099             }
1100 
1101             if (escape)
1102               return true;
1103           }
1104 
1105           any_printed = true;
1106           result.GetOutputStream().Printf("%s: %s\n",
1107                                           regex.GetText().str().c_str(),
1108                                           format_sp->GetDescription().c_str());
1109           return true;
1110         });
1111 
1112       category->ForEach(foreach);
1113     };
1114 
1115     if (m_options.m_category_language.OptionWasSet()) {
1116       lldb::TypeCategoryImplSP category_sp;
1117       DataVisualization::Categories::GetCategory(
1118           m_options.m_category_language.GetCurrentValue(), category_sp);
1119       if (category_sp)
1120         category_closure(category_sp);
1121     } else {
1122       DataVisualization::Categories::ForEach(
1123           [&category_regex, &category_closure](
1124               const lldb::TypeCategoryImplSP &category) -> bool {
1125             if (category_regex) {
1126               bool escape = true;
1127               if (category->GetName() == category_regex->GetText()) {
1128                 escape = false;
1129               } else if (category_regex->Execute(
1130                              llvm::StringRef::withNullAsEmpty(
1131                                  category->GetName()))) {
1132                 escape = false;
1133               }
1134 
1135               if (escape)
1136                 return true;
1137             }
1138 
1139             category_closure(category);
1140 
1141             return true;
1142           });
1143 
1144       any_printed = FormatterSpecificList(result) | any_printed;
1145     }
1146 
1147     if (any_printed)
1148       result.SetStatus(eReturnStatusSuccessFinishResult);
1149     else {
1150       result.GetOutputStream().PutCString("no matching results found.\n");
1151       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1152     }
1153     return result.Succeeded();
1154   }
1155 };
1156 
1157 // CommandObjectTypeFormatList
1158 
1159 class CommandObjectTypeFormatList
1160     : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1161 public:
1162   CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1163       : CommandObjectTypeFormatterList(interpreter, "type format list",
1164                                        "Show a list of current formats.") {}
1165 };
1166 
1167 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1168     uint32_t option_idx, llvm::StringRef option_arg,
1169     ExecutionContext *execution_context) {
1170   Status error;
1171   const int short_option = m_getopt_table[option_idx].val;
1172   bool success;
1173 
1174   switch (short_option) {
1175   case 'C':
1176     m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1177     if (!success)
1178       error.SetErrorStringWithFormat("invalid value for cascade: %s",
1179                                      option_arg.str().c_str());
1180     break;
1181   case 'e':
1182     m_flags.SetDontShowChildren(false);
1183     break;
1184   case 'h':
1185     m_flags.SetHideEmptyAggregates(true);
1186     break;
1187   case 'v':
1188     m_flags.SetDontShowValue(true);
1189     break;
1190   case 'c':
1191     m_flags.SetShowMembersOneLiner(true);
1192     break;
1193   case 's':
1194     m_format_string = std::string(option_arg);
1195     break;
1196   case 'p':
1197     m_flags.SetSkipPointers(true);
1198     break;
1199   case 'r':
1200     m_flags.SetSkipReferences(true);
1201     break;
1202   case 'x':
1203     m_regex = true;
1204     break;
1205   case 'n':
1206     m_name.SetString(option_arg);
1207     break;
1208   case 'o':
1209     m_python_script = option_arg;
1210     m_is_add_script = true;
1211     break;
1212   case 'F':
1213     m_python_function = option_arg;
1214     m_is_add_script = true;
1215     break;
1216   case 'P':
1217     m_is_add_script = true;
1218     break;
1219   case 'w':
1220     m_category = std::string(option_arg);
1221     break;
1222   case 'O':
1223     m_flags.SetHideItemNames(true);
1224     break;
1225   default:
1226     llvm_unreachable("Unimplemented option");
1227   }
1228 
1229   return error;
1230 }
1231 
1232 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1233     ExecutionContext *execution_context) {
1234   m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1235   m_flags.SetShowMembersOneLiner(false)
1236       .SetSkipPointers(false)
1237       .SetSkipReferences(false)
1238       .SetHideItemNames(false);
1239 
1240   m_regex = false;
1241   m_name.Clear();
1242   m_python_script = "";
1243   m_python_function = "";
1244   m_format_string = "";
1245   m_is_add_script = false;
1246   m_category = "default";
1247 }
1248 
1249 #if LLDB_ENABLE_PYTHON
1250 
1251 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1252     Args &command, CommandReturnObject &result) {
1253   const size_t argc = command.GetArgumentCount();
1254 
1255   if (argc < 1 && !m_options.m_name) {
1256     result.AppendErrorWithFormat("%s takes one or more args.\n",
1257                                  m_cmd_name.c_str());
1258     result.SetStatus(eReturnStatusFailed);
1259     return false;
1260   }
1261 
1262   TypeSummaryImplSP script_format;
1263 
1264   if (!m_options.m_python_function
1265            .empty()) // we have a Python function ready to use
1266   {
1267     const char *funct_name = m_options.m_python_function.c_str();
1268     if (!funct_name || !funct_name[0]) {
1269       result.AppendError("function name empty.\n");
1270       result.SetStatus(eReturnStatusFailed);
1271       return false;
1272     }
1273 
1274     std::string code =
1275         ("    " + m_options.m_python_function + "(valobj,internal_dict)");
1276 
1277     script_format = std::make_shared<ScriptSummaryFormat>(
1278         m_options.m_flags, funct_name, code.c_str());
1279 
1280     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1281 
1282     if (interpreter && !interpreter->CheckObjectExists(funct_name))
1283       result.AppendWarningWithFormat(
1284           "The provided function \"%s\" does not exist - "
1285           "please define it before attempting to use this summary.\n",
1286           funct_name);
1287   } else if (!m_options.m_python_script
1288                   .empty()) // we have a quick 1-line script, just use it
1289   {
1290     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1291     if (!interpreter) {
1292       result.AppendError("script interpreter missing - unable to generate "
1293                          "function wrapper.\n");
1294       result.SetStatus(eReturnStatusFailed);
1295       return false;
1296     }
1297     StringList funct_sl;
1298     funct_sl << m_options.m_python_script.c_str();
1299     std::string funct_name_str;
1300     if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1301       result.AppendError("unable to generate function wrapper.\n");
1302       result.SetStatus(eReturnStatusFailed);
1303       return false;
1304     }
1305     if (funct_name_str.empty()) {
1306       result.AppendError(
1307           "script interpreter failed to generate a valid function name.\n");
1308       result.SetStatus(eReturnStatusFailed);
1309       return false;
1310     }
1311 
1312     std::string code = "    " + m_options.m_python_script;
1313 
1314     script_format = std::make_shared<ScriptSummaryFormat>(
1315         m_options.m_flags, funct_name_str.c_str(), code.c_str());
1316   } else {
1317     // Use an IOHandler to grab Python code from the user
1318     ScriptAddOptions *options =
1319         new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1320                              m_options.m_name, m_options.m_category);
1321 
1322     for (auto &entry : command.entries()) {
1323       if (entry.ref().empty()) {
1324         result.AppendError("empty typenames not allowed");
1325         result.SetStatus(eReturnStatusFailed);
1326         return false;
1327       }
1328 
1329       options->m_target_types << entry.ref();
1330     }
1331 
1332     m_interpreter.GetPythonCommandsFromIOHandler(
1333         "    ",   // Prompt
1334         *this,    // IOHandlerDelegate
1335         true,     // Run IOHandler in async mode
1336         options); // Baton for the "io_handler" that will be passed back into
1337                   // our IOHandlerDelegate functions
1338     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1339 
1340     return result.Succeeded();
1341   }
1342 
1343   // if I am here, script_format must point to something good, so I can add
1344   // that as a script summary to all interested parties
1345 
1346   Status error;
1347 
1348   for (auto &entry : command.entries()) {
1349     CommandObjectTypeSummaryAdd::AddSummary(
1350         ConstString(entry.ref()), script_format,
1351         (m_options.m_regex ? eRegexSummary : eRegularSummary),
1352         m_options.m_category, &error);
1353     if (error.Fail()) {
1354       result.AppendError(error.AsCString());
1355       result.SetStatus(eReturnStatusFailed);
1356       return false;
1357     }
1358   }
1359 
1360   if (m_options.m_name) {
1361     AddSummary(m_options.m_name, script_format, eNamedSummary,
1362                m_options.m_category, &error);
1363     if (error.Fail()) {
1364       result.AppendError(error.AsCString());
1365       result.AppendError("added to types, but not given a name");
1366       result.SetStatus(eReturnStatusFailed);
1367       return false;
1368     }
1369   }
1370 
1371   return result.Succeeded();
1372 }
1373 
1374 #endif
1375 
1376 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1377     Args &command, CommandReturnObject &result) {
1378   const size_t argc = command.GetArgumentCount();
1379 
1380   if (argc < 1 && !m_options.m_name) {
1381     result.AppendErrorWithFormat("%s takes one or more args.\n",
1382                                  m_cmd_name.c_str());
1383     result.SetStatus(eReturnStatusFailed);
1384     return false;
1385   }
1386 
1387   if (!m_options.m_flags.GetShowMembersOneLiner() &&
1388       m_options.m_format_string.empty()) {
1389     result.AppendError("empty summary strings not allowed");
1390     result.SetStatus(eReturnStatusFailed);
1391     return false;
1392   }
1393 
1394   const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1395                                  ? ""
1396                                  : m_options.m_format_string.c_str());
1397 
1398   // ${var%S} is an endless recursion, prevent it
1399   if (strcmp(format_cstr, "${var%S}") == 0) {
1400     result.AppendError("recursive summary not allowed");
1401     result.SetStatus(eReturnStatusFailed);
1402     return false;
1403   }
1404 
1405   std::unique_ptr<StringSummaryFormat> string_format(
1406       new StringSummaryFormat(m_options.m_flags, format_cstr));
1407   if (!string_format) {
1408     result.AppendError("summary creation failed");
1409     result.SetStatus(eReturnStatusFailed);
1410     return false;
1411   }
1412   if (string_format->m_error.Fail()) {
1413     result.AppendErrorWithFormat("syntax error: %s",
1414                                  string_format->m_error.AsCString("<unknown>"));
1415     result.SetStatus(eReturnStatusFailed);
1416     return false;
1417   }
1418   lldb::TypeSummaryImplSP entry(string_format.release());
1419 
1420   // now I have a valid format, let's add it to every type
1421   Status error;
1422   for (auto &arg_entry : command.entries()) {
1423     if (arg_entry.ref().empty()) {
1424       result.AppendError("empty typenames not allowed");
1425       result.SetStatus(eReturnStatusFailed);
1426       return false;
1427     }
1428     ConstString typeCS(arg_entry.ref());
1429 
1430     AddSummary(typeCS, entry,
1431                (m_options.m_regex ? eRegexSummary : eRegularSummary),
1432                m_options.m_category, &error);
1433 
1434     if (error.Fail()) {
1435       result.AppendError(error.AsCString());
1436       result.SetStatus(eReturnStatusFailed);
1437       return false;
1438     }
1439   }
1440 
1441   if (m_options.m_name) {
1442     AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1443                &error);
1444     if (error.Fail()) {
1445       result.AppendError(error.AsCString());
1446       result.AppendError("added to types, but not given a name");
1447       result.SetStatus(eReturnStatusFailed);
1448       return false;
1449     }
1450   }
1451 
1452   result.SetStatus(eReturnStatusSuccessFinishNoResult);
1453   return result.Succeeded();
1454 }
1455 
1456 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1457     CommandInterpreter &interpreter)
1458     : CommandObjectParsed(interpreter, "type summary add",
1459                           "Add a new summary style for a type.", nullptr),
1460       IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1461   CommandArgumentEntry type_arg;
1462   CommandArgumentData type_style_arg;
1463 
1464   type_style_arg.arg_type = eArgTypeName;
1465   type_style_arg.arg_repetition = eArgRepeatPlus;
1466 
1467   type_arg.push_back(type_style_arg);
1468 
1469   m_arguments.push_back(type_arg);
1470 
1471   SetHelpLong(
1472       R"(
1473 The following examples of 'type summary add' refer to this code snippet for context:
1474 
1475     struct JustADemo
1476     {
1477         int* ptr;
1478         float value;
1479         JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1480     };
1481     JustADemo demo_instance(42, 3.14);
1482 
1483     typedef JustADemo NewDemo;
1484     NewDemo new_demo_instance(42, 3.14);
1485 
1486 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1487 
1488     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1489 
1490 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1491 
1492     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1493 
1494 )"
1495       "Alternatively, you could define formatting for all pointers to integers and \
1496 rely on that when formatting JustADemo to obtain the same result:"
1497       R"(
1498 
1499 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1500 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1501 
1502 )"
1503       "Type summaries are automatically applied to derived typedefs, so the examples \
1504 above apply to both JustADemo and NewDemo.  The cascade option can be used to \
1505 suppress this behavior:"
1506       R"(
1507 
1508 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1509 
1510     The summary will now be used for values of JustADemo but not NewDemo.
1511 
1512 )"
1513       "By default summaries are shown for pointers and references to values of the \
1514 specified type.  To suppress formatting for pointers use the -p option, or apply \
1515 the corresponding -r option to suppress formatting for references:"
1516       R"(
1517 
1518 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1519 
1520 )"
1521       "One-line summaries including all fields in a type can be inferred without supplying an \
1522 explicit summary string by passing the -c option:"
1523       R"(
1524 
1525 (lldb) type summary add -c JustADemo
1526 (lldb) frame variable demo_instance
1527 (ptr=<address>, value=3.14)
1528 
1529 )"
1530       "Type summaries normally suppress the nested display of individual fields.  To \
1531 supply a summary to supplement the default structure add the -e option:"
1532       R"(
1533 
1534 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1535 
1536 )"
1537       "Now when displaying JustADemo values the int* is displayed, followed by the \
1538 standard LLDB sequence of children, one per line:"
1539       R"(
1540 
1541 *ptr = 42 {
1542   ptr = <address>
1543   value = 3.14
1544 }
1545 
1546 )"
1547       "You can also add summaries written in Python.  These scripts use lldb public API to \
1548 gather information from your variables and produce a meaningful summary.  To start a \
1549 multi-line script use the -P option.  The function declaration will be displayed along with \
1550 a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
1551 itself:"
1552       R"(
1553 
1554 (lldb) type summary add JustADemo -P
1555 def function (valobj,internal_dict):
1556 """valobj: an SBValue which you want to provide a summary for
1557 internal_dict: an LLDB support object not to be used"""
1558     value = valobj.GetChildMemberWithName('value');
1559     return 'My value is ' + value.GetValue();
1560     DONE
1561 
1562 Alternatively, the -o option can be used when providing a simple one-line Python script:
1563 
1564 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1565 }
1566 
1567 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1568                                             CommandReturnObject &result) {
1569   WarnOnPotentialUnquotedUnsignedType(command, result);
1570 
1571   if (m_options.m_is_add_script) {
1572 #if LLDB_ENABLE_PYTHON
1573     return Execute_ScriptSummary(command, result);
1574 #else
1575     result.AppendError("python is disabled");
1576     result.SetStatus(eReturnStatusFailed);
1577     return false;
1578 #endif
1579   }
1580 
1581   return Execute_StringSummary(command, result);
1582 }
1583 
1584 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1585   llvm::StringRef type_name_ref(type_name.GetStringRef());
1586 
1587   if (type_name_ref.endswith("[]")) {
1588     std::string type_name_str(type_name.GetCString());
1589     type_name_str.resize(type_name_str.length() - 2);
1590     if (type_name_str.back() != ' ')
1591       type_name_str.append(" \\[[0-9]+\\]");
1592     else
1593       type_name_str.append("\\[[0-9]+\\]");
1594     type_name.SetCString(type_name_str.c_str());
1595     return true;
1596   }
1597   return false;
1598 }
1599 
1600 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1601                                              TypeSummaryImplSP entry,
1602                                              SummaryFormatType type,
1603                                              std::string category_name,
1604                                              Status *error) {
1605   lldb::TypeCategoryImplSP category;
1606   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1607                                              category);
1608 
1609   if (type == eRegularSummary) {
1610     if (FixArrayTypeNameWithRegex(type_name))
1611       type = eRegexSummary;
1612   }
1613 
1614   if (type == eRegexSummary) {
1615     RegularExpression typeRX(type_name.GetStringRef());
1616     if (!typeRX.IsValid()) {
1617       if (error)
1618         error->SetErrorString(
1619             "regex format error (maybe this is not really a regex?)");
1620       return false;
1621     }
1622 
1623     category->GetRegexTypeSummariesContainer()->Delete(type_name);
1624     category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry);
1625 
1626     return true;
1627   } else if (type == eNamedSummary) {
1628     // system named summaries do not exist (yet?)
1629     DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1630     return true;
1631   } else {
1632     category->GetTypeSummariesContainer()->Add(std::move(type_name), entry);
1633     return true;
1634   }
1635 }
1636 
1637 // CommandObjectTypeSummaryDelete
1638 
1639 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1640 public:
1641   CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1642       : CommandObjectTypeFormatterDelete(
1643             interpreter,
1644             eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1645             "type summary delete", "Delete an existing summary for a type.") {}
1646 
1647   ~CommandObjectTypeSummaryDelete() override = default;
1648 
1649 protected:
1650   bool FormatterSpecificDeletion(ConstString typeCS) override {
1651     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1652       return false;
1653     return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1654   }
1655 };
1656 
1657 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1658 public:
1659   CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1660       : CommandObjectTypeFormatterClear(
1661             interpreter,
1662             eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1663             "type summary clear", "Delete all existing summaries.") {}
1664 
1665 protected:
1666   void FormatterSpecificDeletion() override {
1667     DataVisualization::NamedSummaryFormats::Clear();
1668   }
1669 };
1670 
1671 // CommandObjectTypeSummaryList
1672 
1673 class CommandObjectTypeSummaryList
1674     : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1675 public:
1676   CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1677       : CommandObjectTypeFormatterList(interpreter, "type summary list",
1678                                        "Show a list of current summaries.") {}
1679 
1680 protected:
1681   bool FormatterSpecificList(CommandReturnObject &result) override {
1682     if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1683       result.GetOutputStream().Printf("Named summaries:\n");
1684       DataVisualization::NamedSummaryFormats::ForEach(
1685           [&result](ConstString name,
1686                     const TypeSummaryImplSP &summary_sp) -> bool {
1687             result.GetOutputStream().Printf(
1688                 "%s: %s\n", name.AsCString(),
1689                 summary_sp->GetDescription().c_str());
1690             return true;
1691           });
1692       return true;
1693     }
1694     return false;
1695   }
1696 };
1697 
1698 // CommandObjectTypeCategoryDefine
1699 #define LLDB_OPTIONS_type_category_define
1700 #include "CommandOptions.inc"
1701 
1702 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1703   class CommandOptions : public Options {
1704   public:
1705     CommandOptions()
1706         : Options(), m_define_enabled(false, false),
1707           m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1708 
1709     ~CommandOptions() override = default;
1710 
1711     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1712                           ExecutionContext *execution_context) override {
1713       Status error;
1714       const int short_option = m_getopt_table[option_idx].val;
1715 
1716       switch (short_option) {
1717       case 'e':
1718         m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1719         break;
1720       case 'l':
1721         error = m_cate_language.SetValueFromString(option_arg);
1722         break;
1723       default:
1724         llvm_unreachable("Unimplemented option");
1725       }
1726 
1727       return error;
1728     }
1729 
1730     void OptionParsingStarting(ExecutionContext *execution_context) override {
1731       m_define_enabled.Clear();
1732       m_cate_language.Clear();
1733     }
1734 
1735     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1736       return llvm::makeArrayRef(g_type_category_define_options);
1737     }
1738 
1739     // Instance variables to hold the values for command options.
1740 
1741     OptionValueBoolean m_define_enabled;
1742     OptionValueLanguage m_cate_language;
1743   };
1744 
1745   CommandOptions m_options;
1746 
1747   Options *GetOptions() override { return &m_options; }
1748 
1749 public:
1750   CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1751       : CommandObjectParsed(interpreter, "type category define",
1752                             "Define a new category as a source of formatters.",
1753                             nullptr),
1754         m_options() {
1755     CommandArgumentEntry type_arg;
1756     CommandArgumentData type_style_arg;
1757 
1758     type_style_arg.arg_type = eArgTypeName;
1759     type_style_arg.arg_repetition = eArgRepeatPlus;
1760 
1761     type_arg.push_back(type_style_arg);
1762 
1763     m_arguments.push_back(type_arg);
1764   }
1765 
1766   ~CommandObjectTypeCategoryDefine() override = default;
1767 
1768 protected:
1769   bool DoExecute(Args &command, CommandReturnObject &result) override {
1770     const size_t argc = command.GetArgumentCount();
1771 
1772     if (argc < 1) {
1773       result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1774                                    m_cmd_name.c_str());
1775       result.SetStatus(eReturnStatusFailed);
1776       return false;
1777     }
1778 
1779     for (auto &entry : command.entries()) {
1780       TypeCategoryImplSP category_sp;
1781       if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1782                                                      category_sp) &&
1783           category_sp) {
1784         category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1785         if (m_options.m_define_enabled.GetCurrentValue())
1786           DataVisualization::Categories::Enable(category_sp,
1787                                                 TypeCategoryMap::Default);
1788       }
1789     }
1790 
1791     result.SetStatus(eReturnStatusSuccessFinishResult);
1792     return result.Succeeded();
1793   }
1794 };
1795 
1796 // CommandObjectTypeCategoryEnable
1797 #define LLDB_OPTIONS_type_category_enable
1798 #include "CommandOptions.inc"
1799 
1800 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1801   class CommandOptions : public Options {
1802   public:
1803     CommandOptions() : Options() {}
1804 
1805     ~CommandOptions() override = default;
1806 
1807     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1808                           ExecutionContext *execution_context) override {
1809       Status error;
1810       const int short_option = m_getopt_table[option_idx].val;
1811 
1812       switch (short_option) {
1813       case 'l':
1814         if (!option_arg.empty()) {
1815           m_language = Language::GetLanguageTypeFromString(option_arg);
1816           if (m_language == lldb::eLanguageTypeUnknown)
1817             error.SetErrorStringWithFormat("unrecognized language '%s'",
1818                                            option_arg.str().c_str());
1819         }
1820         break;
1821       default:
1822         llvm_unreachable("Unimplemented option");
1823       }
1824 
1825       return error;
1826     }
1827 
1828     void OptionParsingStarting(ExecutionContext *execution_context) override {
1829       m_language = lldb::eLanguageTypeUnknown;
1830     }
1831 
1832     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1833       return llvm::makeArrayRef(g_type_category_enable_options);
1834     }
1835 
1836     // Instance variables to hold the values for command options.
1837 
1838     lldb::LanguageType m_language;
1839   };
1840 
1841   CommandOptions m_options;
1842 
1843   Options *GetOptions() override { return &m_options; }
1844 
1845 public:
1846   CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1847       : CommandObjectParsed(interpreter, "type category enable",
1848                             "Enable a category as a source of formatters.",
1849                             nullptr),
1850         m_options() {
1851     CommandArgumentEntry type_arg;
1852     CommandArgumentData type_style_arg;
1853 
1854     type_style_arg.arg_type = eArgTypeName;
1855     type_style_arg.arg_repetition = eArgRepeatPlus;
1856 
1857     type_arg.push_back(type_style_arg);
1858 
1859     m_arguments.push_back(type_arg);
1860   }
1861 
1862   ~CommandObjectTypeCategoryEnable() override = default;
1863 
1864 protected:
1865   bool DoExecute(Args &command, CommandReturnObject &result) override {
1866     const size_t argc = command.GetArgumentCount();
1867 
1868     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1869       result.AppendErrorWithFormat("%s takes arguments and/or a language",
1870                                    m_cmd_name.c_str());
1871       result.SetStatus(eReturnStatusFailed);
1872       return false;
1873     }
1874 
1875     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1876       DataVisualization::Categories::EnableStar();
1877     } else if (argc > 0) {
1878       for (int i = argc - 1; i >= 0; i--) {
1879         const char *typeA = command.GetArgumentAtIndex(i);
1880         ConstString typeCS(typeA);
1881 
1882         if (!typeCS) {
1883           result.AppendError("empty category name not allowed");
1884           result.SetStatus(eReturnStatusFailed);
1885           return false;
1886         }
1887         DataVisualization::Categories::Enable(typeCS);
1888         lldb::TypeCategoryImplSP cate;
1889         if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1890           if (cate->GetCount() == 0) {
1891             result.AppendWarning("empty category enabled (typo?)");
1892           }
1893         }
1894       }
1895     }
1896 
1897     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1898       DataVisualization::Categories::Enable(m_options.m_language);
1899 
1900     result.SetStatus(eReturnStatusSuccessFinishResult);
1901     return result.Succeeded();
1902   }
1903 };
1904 
1905 // CommandObjectTypeCategoryDelete
1906 
1907 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1908 public:
1909   CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1910       : CommandObjectParsed(interpreter, "type category delete",
1911                             "Delete a category and all associated formatters.",
1912                             nullptr) {
1913     CommandArgumentEntry type_arg;
1914     CommandArgumentData type_style_arg;
1915 
1916     type_style_arg.arg_type = eArgTypeName;
1917     type_style_arg.arg_repetition = eArgRepeatPlus;
1918 
1919     type_arg.push_back(type_style_arg);
1920 
1921     m_arguments.push_back(type_arg);
1922   }
1923 
1924   ~CommandObjectTypeCategoryDelete() override = default;
1925 
1926 protected:
1927   bool DoExecute(Args &command, CommandReturnObject &result) override {
1928     const size_t argc = command.GetArgumentCount();
1929 
1930     if (argc < 1) {
1931       result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1932                                    m_cmd_name.c_str());
1933       result.SetStatus(eReturnStatusFailed);
1934       return false;
1935     }
1936 
1937     bool success = true;
1938 
1939     // the order is not relevant here
1940     for (int i = argc - 1; i >= 0; i--) {
1941       const char *typeA = command.GetArgumentAtIndex(i);
1942       ConstString typeCS(typeA);
1943 
1944       if (!typeCS) {
1945         result.AppendError("empty category name not allowed");
1946         result.SetStatus(eReturnStatusFailed);
1947         return false;
1948       }
1949       if (!DataVisualization::Categories::Delete(typeCS))
1950         success = false; // keep deleting even if we hit an error
1951     }
1952     if (success) {
1953       result.SetStatus(eReturnStatusSuccessFinishResult);
1954       return result.Succeeded();
1955     } else {
1956       result.AppendError("cannot delete one or more categories\n");
1957       result.SetStatus(eReturnStatusFailed);
1958       return false;
1959     }
1960   }
1961 };
1962 
1963 // CommandObjectTypeCategoryDisable
1964 #define LLDB_OPTIONS_type_category_disable
1965 #include "CommandOptions.inc"
1966 
1967 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1968   class CommandOptions : public Options {
1969   public:
1970     CommandOptions() : Options() {}
1971 
1972     ~CommandOptions() override = default;
1973 
1974     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1975                           ExecutionContext *execution_context) override {
1976       Status error;
1977       const int short_option = m_getopt_table[option_idx].val;
1978 
1979       switch (short_option) {
1980       case 'l':
1981         if (!option_arg.empty()) {
1982           m_language = Language::GetLanguageTypeFromString(option_arg);
1983           if (m_language == lldb::eLanguageTypeUnknown)
1984             error.SetErrorStringWithFormat("unrecognized language '%s'",
1985                                            option_arg.str().c_str());
1986         }
1987         break;
1988       default:
1989         llvm_unreachable("Unimplemented option");
1990       }
1991 
1992       return error;
1993     }
1994 
1995     void OptionParsingStarting(ExecutionContext *execution_context) override {
1996       m_language = lldb::eLanguageTypeUnknown;
1997     }
1998 
1999     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2000       return llvm::makeArrayRef(g_type_category_disable_options);
2001     }
2002 
2003     // Instance variables to hold the values for command options.
2004 
2005     lldb::LanguageType m_language;
2006   };
2007 
2008   CommandOptions m_options;
2009 
2010   Options *GetOptions() override { return &m_options; }
2011 
2012 public:
2013   CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2014       : CommandObjectParsed(interpreter, "type category disable",
2015                             "Disable a category as a source of formatters.",
2016                             nullptr),
2017         m_options() {
2018     CommandArgumentEntry type_arg;
2019     CommandArgumentData type_style_arg;
2020 
2021     type_style_arg.arg_type = eArgTypeName;
2022     type_style_arg.arg_repetition = eArgRepeatPlus;
2023 
2024     type_arg.push_back(type_style_arg);
2025 
2026     m_arguments.push_back(type_arg);
2027   }
2028 
2029   ~CommandObjectTypeCategoryDisable() override = default;
2030 
2031 protected:
2032   bool DoExecute(Args &command, CommandReturnObject &result) override {
2033     const size_t argc = command.GetArgumentCount();
2034 
2035     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2036       result.AppendErrorWithFormat("%s takes arguments and/or a language",
2037                                    m_cmd_name.c_str());
2038       result.SetStatus(eReturnStatusFailed);
2039       return false;
2040     }
2041 
2042     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2043       DataVisualization::Categories::DisableStar();
2044     } else if (argc > 0) {
2045       // the order is not relevant here
2046       for (int i = argc - 1; i >= 0; i--) {
2047         const char *typeA = command.GetArgumentAtIndex(i);
2048         ConstString typeCS(typeA);
2049 
2050         if (!typeCS) {
2051           result.AppendError("empty category name not allowed");
2052           result.SetStatus(eReturnStatusFailed);
2053           return false;
2054         }
2055         DataVisualization::Categories::Disable(typeCS);
2056       }
2057     }
2058 
2059     if (m_options.m_language != lldb::eLanguageTypeUnknown)
2060       DataVisualization::Categories::Disable(m_options.m_language);
2061 
2062     result.SetStatus(eReturnStatusSuccessFinishResult);
2063     return result.Succeeded();
2064   }
2065 };
2066 
2067 // CommandObjectTypeCategoryList
2068 
2069 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2070 public:
2071   CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2072       : CommandObjectParsed(interpreter, "type category list",
2073                             "Provide a list of all existing categories.",
2074                             nullptr) {
2075     CommandArgumentEntry type_arg;
2076     CommandArgumentData type_style_arg;
2077 
2078     type_style_arg.arg_type = eArgTypeName;
2079     type_style_arg.arg_repetition = eArgRepeatOptional;
2080 
2081     type_arg.push_back(type_style_arg);
2082 
2083     m_arguments.push_back(type_arg);
2084   }
2085 
2086   ~CommandObjectTypeCategoryList() override = default;
2087 
2088 protected:
2089   bool DoExecute(Args &command, CommandReturnObject &result) override {
2090     const size_t argc = command.GetArgumentCount();
2091 
2092     std::unique_ptr<RegularExpression> regex;
2093 
2094     if (argc == 1) {
2095       const char *arg = command.GetArgumentAtIndex(0);
2096       regex.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg)));
2097       if (!regex->IsValid()) {
2098         result.AppendErrorWithFormat(
2099             "syntax error in category regular expression '%s'", arg);
2100         result.SetStatus(eReturnStatusFailed);
2101         return false;
2102       }
2103     } else if (argc != 0) {
2104       result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2105                                    m_cmd_name.c_str());
2106       result.SetStatus(eReturnStatusFailed);
2107       return false;
2108     }
2109 
2110     DataVisualization::Categories::ForEach(
2111         [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2112           if (regex) {
2113             bool escape = true;
2114             if (regex->GetText() == category_sp->GetName()) {
2115               escape = false;
2116             } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
2117                            category_sp->GetName()))) {
2118               escape = false;
2119             }
2120 
2121             if (escape)
2122               return true;
2123           }
2124 
2125           result.GetOutputStream().Printf(
2126               "Category: %s\n", category_sp->GetDescription().c_str());
2127 
2128           return true;
2129         });
2130 
2131     result.SetStatus(eReturnStatusSuccessFinishResult);
2132     return result.Succeeded();
2133   }
2134 };
2135 
2136 // CommandObjectTypeFilterList
2137 
2138 class CommandObjectTypeFilterList
2139     : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2140 public:
2141   CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2142       : CommandObjectTypeFormatterList(interpreter, "type filter list",
2143                                        "Show a list of current filters.") {}
2144 };
2145 
2146 #if LLDB_ENABLE_PYTHON
2147 
2148 // CommandObjectTypeSynthList
2149 
2150 class CommandObjectTypeSynthList
2151     : public CommandObjectTypeFormatterList<SyntheticChildren> {
2152 public:
2153   CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2154       : CommandObjectTypeFormatterList(
2155             interpreter, "type synthetic list",
2156             "Show a list of current synthetic providers.") {}
2157 };
2158 
2159 #endif
2160 
2161 // CommandObjectTypeFilterDelete
2162 
2163 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2164 public:
2165   CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2166       : CommandObjectTypeFormatterDelete(
2167             interpreter,
2168             eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2169             "type filter delete", "Delete an existing filter for a type.") {}
2170 
2171   ~CommandObjectTypeFilterDelete() override = default;
2172 };
2173 
2174 #if LLDB_ENABLE_PYTHON
2175 
2176 // CommandObjectTypeSynthDelete
2177 
2178 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2179 public:
2180   CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2181       : CommandObjectTypeFormatterDelete(
2182             interpreter,
2183             eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2184             "type synthetic delete",
2185             "Delete an existing synthetic provider for a type.") {}
2186 
2187   ~CommandObjectTypeSynthDelete() override = default;
2188 };
2189 
2190 #endif
2191 
2192 // CommandObjectTypeFilterClear
2193 
2194 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2195 public:
2196   CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2197       : CommandObjectTypeFormatterClear(
2198             interpreter,
2199             eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2200             "type filter clear", "Delete all existing filter.") {}
2201 };
2202 
2203 #if LLDB_ENABLE_PYTHON
2204 // CommandObjectTypeSynthClear
2205 
2206 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2207 public:
2208   CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2209       : CommandObjectTypeFormatterClear(
2210             interpreter,
2211             eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2212             "type synthetic clear",
2213             "Delete all existing synthetic providers.") {}
2214 };
2215 
2216 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2217     Args &command, CommandReturnObject &result) {
2218   SynthAddOptions *options = new SynthAddOptions(
2219       m_options.m_skip_pointers, m_options.m_skip_references,
2220       m_options.m_cascade, m_options.m_regex, m_options.m_category);
2221 
2222   for (auto &entry : command.entries()) {
2223     if (entry.ref().empty()) {
2224       result.AppendError("empty typenames not allowed");
2225       result.SetStatus(eReturnStatusFailed);
2226       return false;
2227     }
2228 
2229     options->m_target_types << entry.ref();
2230   }
2231 
2232   m_interpreter.GetPythonCommandsFromIOHandler(
2233       "    ",   // Prompt
2234       *this,    // IOHandlerDelegate
2235       true,     // Run IOHandler in async mode
2236       options); // Baton for the "io_handler" that will be passed back into our
2237                 // IOHandlerDelegate functions
2238   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2239   return result.Succeeded();
2240 }
2241 
2242 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2243     Args &command, CommandReturnObject &result) {
2244   const size_t argc = command.GetArgumentCount();
2245 
2246   if (argc < 1) {
2247     result.AppendErrorWithFormat("%s takes one or more args.\n",
2248                                  m_cmd_name.c_str());
2249     result.SetStatus(eReturnStatusFailed);
2250     return false;
2251   }
2252 
2253   if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2254     result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2255                                  "directly input Python code.\n",
2256                                  m_cmd_name.c_str());
2257     result.SetStatus(eReturnStatusFailed);
2258     return false;
2259   }
2260 
2261   SyntheticChildrenSP entry;
2262 
2263   ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2264       SyntheticChildren::Flags()
2265           .SetCascades(m_options.m_cascade)
2266           .SetSkipPointers(m_options.m_skip_pointers)
2267           .SetSkipReferences(m_options.m_skip_references),
2268       m_options.m_class_name.c_str());
2269 
2270   entry.reset(impl);
2271 
2272   ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2273 
2274   if (interpreter &&
2275       !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2276     result.AppendWarning("The provided class does not exist - please define it "
2277                          "before attempting to use this synthetic provider");
2278 
2279   // now I have a valid provider, let's add it to every type
2280 
2281   lldb::TypeCategoryImplSP category;
2282   DataVisualization::Categories::GetCategory(
2283       ConstString(m_options.m_category.c_str()), category);
2284 
2285   Status error;
2286 
2287   for (auto &arg_entry : command.entries()) {
2288     if (arg_entry.ref().empty()) {
2289       result.AppendError("empty typenames not allowed");
2290       result.SetStatus(eReturnStatusFailed);
2291       return false;
2292     }
2293 
2294     ConstString typeCS(arg_entry.ref());
2295     if (!AddSynth(typeCS, entry,
2296                   m_options.m_regex ? eRegexSynth : eRegularSynth,
2297                   m_options.m_category, &error)) {
2298       result.AppendError(error.AsCString());
2299       result.SetStatus(eReturnStatusFailed);
2300       return false;
2301     }
2302   }
2303 
2304   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2305   return result.Succeeded();
2306 }
2307 
2308 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2309     CommandInterpreter &interpreter)
2310     : CommandObjectParsed(interpreter, "type synthetic add",
2311                           "Add a new synthetic provider for a type.", nullptr),
2312       IOHandlerDelegateMultiline("DONE"), m_options() {
2313   CommandArgumentEntry type_arg;
2314   CommandArgumentData type_style_arg;
2315 
2316   type_style_arg.arg_type = eArgTypeName;
2317   type_style_arg.arg_repetition = eArgRepeatPlus;
2318 
2319   type_arg.push_back(type_style_arg);
2320 
2321   m_arguments.push_back(type_arg);
2322 }
2323 
2324 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2325                                          SyntheticChildrenSP entry,
2326                                          SynthFormatType type,
2327                                          std::string category_name,
2328                                          Status *error) {
2329   lldb::TypeCategoryImplSP category;
2330   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2331                                              category);
2332 
2333   if (type == eRegularSynth) {
2334     if (FixArrayTypeNameWithRegex(type_name))
2335       type = eRegexSynth;
2336   }
2337 
2338   if (category->AnyMatches(
2339           type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2340           false)) {
2341     if (error)
2342       error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2343                                       "filter is defined in same category!",
2344                                       type_name.AsCString());
2345     return false;
2346   }
2347 
2348   if (type == eRegexSynth) {
2349     RegularExpression typeRX(type_name.GetStringRef());
2350     if (!typeRX.IsValid()) {
2351       if (error)
2352         error->SetErrorString(
2353             "regex format error (maybe this is not really a regex?)");
2354       return false;
2355     }
2356 
2357     category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2358     category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry);
2359 
2360     return true;
2361   } else {
2362     category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry);
2363     return true;
2364   }
2365 }
2366 
2367 #endif
2368 #define LLDB_OPTIONS_type_filter_add
2369 #include "CommandOptions.inc"
2370 
2371 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2372 private:
2373   class CommandOptions : public Options {
2374     typedef std::vector<std::string> option_vector;
2375 
2376   public:
2377     CommandOptions() : Options() {}
2378 
2379     ~CommandOptions() override = default;
2380 
2381     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2382                           ExecutionContext *execution_context) override {
2383       Status error;
2384       const int short_option = m_getopt_table[option_idx].val;
2385       bool success;
2386 
2387       switch (short_option) {
2388       case 'C':
2389         m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2390         if (!success)
2391           error.SetErrorStringWithFormat("invalid value for cascade: %s",
2392                                          option_arg.str().c_str());
2393         break;
2394       case 'c':
2395         m_expr_paths.push_back(option_arg);
2396         has_child_list = true;
2397         break;
2398       case 'p':
2399         m_skip_pointers = true;
2400         break;
2401       case 'r':
2402         m_skip_references = true;
2403         break;
2404       case 'w':
2405         m_category = std::string(option_arg);
2406         break;
2407       case 'x':
2408         m_regex = true;
2409         break;
2410       default:
2411         llvm_unreachable("Unimplemented option");
2412       }
2413 
2414       return error;
2415     }
2416 
2417     void OptionParsingStarting(ExecutionContext *execution_context) override {
2418       m_cascade = true;
2419       m_skip_pointers = false;
2420       m_skip_references = false;
2421       m_category = "default";
2422       m_expr_paths.clear();
2423       has_child_list = false;
2424       m_regex = false;
2425     }
2426 
2427     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2428       return llvm::makeArrayRef(g_type_filter_add_options);
2429     }
2430 
2431     // Instance variables to hold the values for command options.
2432 
2433     bool m_cascade;
2434     bool m_skip_references;
2435     bool m_skip_pointers;
2436     bool m_input_python;
2437     option_vector m_expr_paths;
2438     std::string m_category;
2439     bool has_child_list;
2440     bool m_regex;
2441 
2442     typedef option_vector::iterator ExpressionPathsIterator;
2443   };
2444 
2445   CommandOptions m_options;
2446 
2447   Options *GetOptions() override { return &m_options; }
2448 
2449   enum FilterFormatType { eRegularFilter, eRegexFilter };
2450 
2451   bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2452                  FilterFormatType type, std::string category_name,
2453                  Status *error) {
2454     lldb::TypeCategoryImplSP category;
2455     DataVisualization::Categories::GetCategory(
2456         ConstString(category_name.c_str()), category);
2457 
2458     if (type == eRegularFilter) {
2459       if (FixArrayTypeNameWithRegex(type_name))
2460         type = eRegexFilter;
2461     }
2462 
2463     if (category->AnyMatches(
2464             type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2465             false)) {
2466       if (error)
2467         error->SetErrorStringWithFormat("cannot add filter for type %s when "
2468                                         "synthetic is defined in same "
2469                                         "category!",
2470                                         type_name.AsCString());
2471       return false;
2472     }
2473 
2474     if (type == eRegexFilter) {
2475       RegularExpression typeRX(type_name.GetStringRef());
2476       if (!typeRX.IsValid()) {
2477         if (error)
2478           error->SetErrorString(
2479               "regex format error (maybe this is not really a regex?)");
2480         return false;
2481       }
2482 
2483       category->GetRegexTypeFiltersContainer()->Delete(type_name);
2484       category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry);
2485 
2486       return true;
2487     } else {
2488       category->GetTypeFiltersContainer()->Add(std::move(type_name), entry);
2489       return true;
2490     }
2491   }
2492 
2493 public:
2494   CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2495       : CommandObjectParsed(interpreter, "type filter add",
2496                             "Add a new filter for a type.", nullptr),
2497         m_options() {
2498     CommandArgumentEntry type_arg;
2499     CommandArgumentData type_style_arg;
2500 
2501     type_style_arg.arg_type = eArgTypeName;
2502     type_style_arg.arg_repetition = eArgRepeatPlus;
2503 
2504     type_arg.push_back(type_style_arg);
2505 
2506     m_arguments.push_back(type_arg);
2507 
2508     SetHelpLong(
2509         R"(
2510 The following examples of 'type filter add' refer to this code snippet for context:
2511 
2512     class Foo {
2513         int a;
2514         int b;
2515         int c;
2516         int d;
2517         int e;
2518         int f;
2519         int g;
2520         int h;
2521         int i;
2522     }
2523     Foo my_foo;
2524 
2525 Adding a simple filter:
2526 
2527 (lldb) type filter add --child a --child g Foo
2528 (lldb) frame variable my_foo
2529 
2530 )"
2531         "Produces output where only a and g are displayed.  Other children of my_foo \
2532 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2533         R"(
2534 
2535 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2536 
2537 )"
2538         "The formatting option --raw on frame variable bypasses the filter, showing \
2539 all children of my_foo as if no filter was defined:"
2540         R"(
2541 
2542 (lldb) frame variable my_foo --raw)");
2543   }
2544 
2545   ~CommandObjectTypeFilterAdd() override = default;
2546 
2547 protected:
2548   bool DoExecute(Args &command, CommandReturnObject &result) override {
2549     const size_t argc = command.GetArgumentCount();
2550 
2551     if (argc < 1) {
2552       result.AppendErrorWithFormat("%s takes one or more args.\n",
2553                                    m_cmd_name.c_str());
2554       result.SetStatus(eReturnStatusFailed);
2555       return false;
2556     }
2557 
2558     if (m_options.m_expr_paths.empty()) {
2559       result.AppendErrorWithFormat("%s needs one or more children.\n",
2560                                    m_cmd_name.c_str());
2561       result.SetStatus(eReturnStatusFailed);
2562       return false;
2563     }
2564 
2565     TypeFilterImplSP entry(new TypeFilterImpl(
2566         SyntheticChildren::Flags()
2567             .SetCascades(m_options.m_cascade)
2568             .SetSkipPointers(m_options.m_skip_pointers)
2569             .SetSkipReferences(m_options.m_skip_references)));
2570 
2571     // go through the expression paths
2572     CommandOptions::ExpressionPathsIterator begin,
2573         end = m_options.m_expr_paths.end();
2574 
2575     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2576       entry->AddExpressionPath(*begin);
2577 
2578     // now I have a valid provider, let's add it to every type
2579 
2580     lldb::TypeCategoryImplSP category;
2581     DataVisualization::Categories::GetCategory(
2582         ConstString(m_options.m_category.c_str()), category);
2583 
2584     Status error;
2585 
2586     WarnOnPotentialUnquotedUnsignedType(command, result);
2587 
2588     for (auto &arg_entry : command.entries()) {
2589       if (arg_entry.ref().empty()) {
2590         result.AppendError("empty typenames not allowed");
2591         result.SetStatus(eReturnStatusFailed);
2592         return false;
2593       }
2594 
2595       ConstString typeCS(arg_entry.ref());
2596       if (!AddFilter(typeCS, entry,
2597                      m_options.m_regex ? eRegexFilter : eRegularFilter,
2598                      m_options.m_category, &error)) {
2599         result.AppendError(error.AsCString());
2600         result.SetStatus(eReturnStatusFailed);
2601         return false;
2602       }
2603     }
2604 
2605     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2606     return result.Succeeded();
2607   }
2608 };
2609 
2610 // "type lookup"
2611 #define LLDB_OPTIONS_type_lookup
2612 #include "CommandOptions.inc"
2613 
2614 class CommandObjectTypeLookup : public CommandObjectRaw {
2615 protected:
2616   // this function is allowed to do a more aggressive job at guessing languages
2617   // than the expression parser is comfortable with - so leave the original
2618   // call alone and add one that is specific to type lookup
2619   lldb::LanguageType GuessLanguage(StackFrame *frame) {
2620     lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2621 
2622     if (!frame)
2623       return lang_type;
2624 
2625     lang_type = frame->GuessLanguage();
2626     if (lang_type != lldb::eLanguageTypeUnknown)
2627       return lang_type;
2628 
2629     Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2630     if (s)
2631       lang_type = s->GetMangled().GuessLanguage();
2632 
2633     return lang_type;
2634   }
2635 
2636   class CommandOptions : public OptionGroup {
2637   public:
2638     CommandOptions()
2639         : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
2640 
2641     ~CommandOptions() override = default;
2642 
2643     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2644       return llvm::makeArrayRef(g_type_lookup_options);
2645     }
2646 
2647     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2648                           ExecutionContext *execution_context) override {
2649       Status error;
2650 
2651       const int short_option = g_type_lookup_options[option_idx].short_option;
2652 
2653       switch (short_option) {
2654       case 'h':
2655         m_show_help = true;
2656         break;
2657 
2658       case 'l':
2659         m_language = Language::GetLanguageTypeFromString(option_value);
2660         break;
2661 
2662       default:
2663         llvm_unreachable("Unimplemented option");
2664       }
2665 
2666       return error;
2667     }
2668 
2669     void OptionParsingStarting(ExecutionContext *execution_context) override {
2670       m_show_help = false;
2671       m_language = eLanguageTypeUnknown;
2672     }
2673 
2674     // Options table: Required for subclasses of Options.
2675 
2676     bool m_show_help;
2677     lldb::LanguageType m_language;
2678   };
2679 
2680   OptionGroupOptions m_option_group;
2681   CommandOptions m_command_options;
2682 
2683 public:
2684   CommandObjectTypeLookup(CommandInterpreter &interpreter)
2685       : CommandObjectRaw(interpreter, "type lookup",
2686                          "Lookup types and declarations in the current target, "
2687                          "following language-specific naming conventions.",
2688                          "type lookup <type-specifier>",
2689                          eCommandRequiresTarget),
2690         m_option_group(), m_command_options() {
2691     m_option_group.Append(&m_command_options);
2692     m_option_group.Finalize();
2693   }
2694 
2695   ~CommandObjectTypeLookup() override = default;
2696 
2697   Options *GetOptions() override { return &m_option_group; }
2698 
2699   llvm::StringRef GetHelpLong() override {
2700     if (!m_cmd_help_long.empty())
2701       return m_cmd_help_long;
2702 
2703     StreamString stream;
2704     Language::ForEach([&](Language *lang) {
2705       if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2706         stream.Printf("%s\n", help);
2707       return true;
2708     });
2709 
2710     m_cmd_help_long = stream.GetString();
2711     return m_cmd_help_long;
2712   }
2713 
2714   bool DoExecute(llvm::StringRef raw_command_line,
2715                  CommandReturnObject &result) override {
2716     if (raw_command_line.empty()) {
2717       result.SetError(
2718           "type lookup cannot be invoked without a type name as argument");
2719       return false;
2720     }
2721 
2722     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2723     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2724 
2725     OptionsWithRaw args(raw_command_line);
2726     const char *name_of_type = args.GetRawPart().c_str();
2727 
2728     if (args.HasArgs())
2729       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2730                                  exe_ctx))
2731         return false;
2732 
2733     ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2734 
2735     bool any_found = false;
2736 
2737     std::vector<Language *> languages;
2738 
2739     bool is_global_search = false;
2740     LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2741 
2742     if ((is_global_search =
2743              (m_command_options.m_language == eLanguageTypeUnknown))) {
2744       Language::ForEach([&](Language *lang) {
2745         languages.push_back(lang);
2746         return true;
2747       });
2748     } else {
2749       languages.push_back(Language::FindPlugin(m_command_options.m_language));
2750     }
2751 
2752     // This is not the most efficient way to do this, but we support very few
2753     // languages so the cost of the sort is going to be dwarfed by the actual
2754     // lookup anyway
2755     if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2756       guessed_language = GuessLanguage(frame);
2757       if (guessed_language != eLanguageTypeUnknown) {
2758         llvm::sort(
2759             languages.begin(), languages.end(),
2760             [guessed_language](Language *lang1, Language *lang2) -> bool {
2761               if (!lang1 || !lang2)
2762                 return false;
2763               LanguageType lt1 = lang1->GetLanguageType();
2764               LanguageType lt2 = lang2->GetLanguageType();
2765               if (lt1 == guessed_language)
2766                 return true; // make the selected frame's language come first
2767               if (lt2 == guessed_language)
2768                 return false; // make the selected frame's language come first
2769               return (lt1 < lt2); // normal comparison otherwise
2770             });
2771       }
2772     }
2773 
2774     bool is_first_language = true;
2775 
2776     for (Language *language : languages) {
2777       if (!language)
2778         continue;
2779 
2780       if (auto scavenger = language->GetTypeScavenger()) {
2781         Language::TypeScavenger::ResultSet search_results;
2782         if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2783           for (const auto &search_result : search_results) {
2784             if (search_result && search_result->IsValid()) {
2785               any_found = true;
2786               search_result->DumpToStream(result.GetOutputStream(),
2787                                           this->m_command_options.m_show_help);
2788             }
2789           }
2790         }
2791       }
2792       // this is "type lookup SomeName" and we did find a match, so get out
2793       if (any_found && is_global_search)
2794         break;
2795       else if (is_first_language && is_global_search &&
2796                guessed_language != lldb::eLanguageTypeUnknown) {
2797         is_first_language = false;
2798         result.GetOutputStream().Printf(
2799             "no type was found in the current language %s matching '%s'; "
2800             "performing a global search across all languages\n",
2801             Language::GetNameForLanguageType(guessed_language), name_of_type);
2802       }
2803     }
2804 
2805     if (!any_found)
2806       result.AppendMessageWithFormat("no type was found matching '%s'\n",
2807                                      name_of_type);
2808 
2809     result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2810                                : lldb::eReturnStatusSuccessFinishNoResult);
2811     return true;
2812   }
2813 };
2814 
2815 template <typename FormatterType>
2816 class CommandObjectFormatterInfo : public CommandObjectRaw {
2817 public:
2818   typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2819       DiscoveryFunction;
2820   CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2821                              const char *formatter_name,
2822                              DiscoveryFunction discovery_func)
2823       : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2824         m_formatter_name(formatter_name ? formatter_name : ""),
2825         m_discovery_function(discovery_func) {
2826     StreamString name;
2827     name.Printf("type %s info", formatter_name);
2828     SetCommandName(name.GetString());
2829     StreamString help;
2830     help.Printf("This command evaluates the provided expression and shows "
2831                 "which %s is applied to the resulting value (if any).",
2832                 formatter_name);
2833     SetHelp(help.GetString());
2834     StreamString syntax;
2835     syntax.Printf("type %s info <expr>", formatter_name);
2836     SetSyntax(syntax.GetString());
2837   }
2838 
2839   ~CommandObjectFormatterInfo() override = default;
2840 
2841 protected:
2842   bool DoExecute(llvm::StringRef command,
2843                  CommandReturnObject &result) override {
2844     TargetSP target_sp = GetDebugger().GetSelectedTarget();
2845     Thread *thread = GetDefaultThread();
2846     if (!thread) {
2847       result.AppendError("no default thread");
2848       result.SetStatus(lldb::eReturnStatusFailed);
2849       return false;
2850     }
2851 
2852     StackFrameSP frame_sp = thread->GetSelectedFrame();
2853     ValueObjectSP result_valobj_sp;
2854     EvaluateExpressionOptions options;
2855     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2856         command, frame_sp.get(), result_valobj_sp, options);
2857     if (expr_result == eExpressionCompleted && result_valobj_sp) {
2858       result_valobj_sp =
2859           result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2860               target_sp->GetPreferDynamicValue(),
2861               target_sp->GetEnableSyntheticValue());
2862       typename FormatterType::SharedPointer formatter_sp =
2863           m_discovery_function(*result_valobj_sp);
2864       if (formatter_sp) {
2865         std::string description(formatter_sp->GetDescription());
2866         result.GetOutputStream()
2867             << m_formatter_name << " applied to ("
2868             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2869             << ") " << command << " is: " << description << "\n";
2870         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2871       } else {
2872         result.GetOutputStream()
2873             << "no " << m_formatter_name << " applies to ("
2874             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2875             << ") " << command << "\n";
2876         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2877       }
2878       return true;
2879     } else {
2880       result.AppendError("failed to evaluate expression");
2881       result.SetStatus(lldb::eReturnStatusFailed);
2882       return false;
2883     }
2884   }
2885 
2886 private:
2887   std::string m_formatter_name;
2888   DiscoveryFunction m_discovery_function;
2889 };
2890 
2891 class CommandObjectTypeFormat : public CommandObjectMultiword {
2892 public:
2893   CommandObjectTypeFormat(CommandInterpreter &interpreter)
2894       : CommandObjectMultiword(
2895             interpreter, "type format",
2896             "Commands for customizing value display formats.",
2897             "type format [<sub-command-options>] ") {
2898     LoadSubCommand(
2899         "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2900     LoadSubCommand("clear", CommandObjectSP(
2901                                 new CommandObjectTypeFormatClear(interpreter)));
2902     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2903                                  interpreter)));
2904     LoadSubCommand(
2905         "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2906     LoadSubCommand(
2907         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2908                     interpreter, "format",
2909                     [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2910                       return valobj.GetValueFormat();
2911                     })));
2912   }
2913 
2914   ~CommandObjectTypeFormat() override = default;
2915 };
2916 
2917 #if LLDB_ENABLE_PYTHON
2918 
2919 class CommandObjectTypeSynth : public CommandObjectMultiword {
2920 public:
2921   CommandObjectTypeSynth(CommandInterpreter &interpreter)
2922       : CommandObjectMultiword(
2923             interpreter, "type synthetic",
2924             "Commands for operating on synthetic type representations.",
2925             "type synthetic [<sub-command-options>] ") {
2926     LoadSubCommand("add",
2927                    CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2928     LoadSubCommand(
2929         "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2930     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2931                                  interpreter)));
2932     LoadSubCommand(
2933         "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2934     LoadSubCommand(
2935         "info",
2936         CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2937             interpreter, "synthetic",
2938             [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2939               return valobj.GetSyntheticChildren();
2940             })));
2941   }
2942 
2943   ~CommandObjectTypeSynth() override = default;
2944 };
2945 
2946 #endif
2947 
2948 class CommandObjectTypeFilter : public CommandObjectMultiword {
2949 public:
2950   CommandObjectTypeFilter(CommandInterpreter &interpreter)
2951       : CommandObjectMultiword(interpreter, "type filter",
2952                                "Commands for operating on type filters.",
2953                                "type synthetic [<sub-command-options>] ") {
2954     LoadSubCommand(
2955         "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2956     LoadSubCommand("clear", CommandObjectSP(
2957                                 new CommandObjectTypeFilterClear(interpreter)));
2958     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2959                                  interpreter)));
2960     LoadSubCommand(
2961         "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2962   }
2963 
2964   ~CommandObjectTypeFilter() override = default;
2965 };
2966 
2967 class CommandObjectTypeCategory : public CommandObjectMultiword {
2968 public:
2969   CommandObjectTypeCategory(CommandInterpreter &interpreter)
2970       : CommandObjectMultiword(interpreter, "type category",
2971                                "Commands for operating on type categories.",
2972                                "type category [<sub-command-options>] ") {
2973     LoadSubCommand(
2974         "define",
2975         CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
2976     LoadSubCommand(
2977         "enable",
2978         CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
2979     LoadSubCommand(
2980         "disable",
2981         CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
2982     LoadSubCommand(
2983         "delete",
2984         CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
2985     LoadSubCommand("list", CommandObjectSP(
2986                                new CommandObjectTypeCategoryList(interpreter)));
2987   }
2988 
2989   ~CommandObjectTypeCategory() override = default;
2990 };
2991 
2992 class CommandObjectTypeSummary : public CommandObjectMultiword {
2993 public:
2994   CommandObjectTypeSummary(CommandInterpreter &interpreter)
2995       : CommandObjectMultiword(
2996             interpreter, "type summary",
2997             "Commands for editing variable summary display options.",
2998             "type summary [<sub-command-options>] ") {
2999     LoadSubCommand(
3000         "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3001     LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3002                                 interpreter)));
3003     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3004                                  interpreter)));
3005     LoadSubCommand(
3006         "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3007     LoadSubCommand(
3008         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3009                     interpreter, "summary",
3010                     [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3011                       return valobj.GetSummaryFormat();
3012                     })));
3013   }
3014 
3015   ~CommandObjectTypeSummary() override = default;
3016 };
3017 
3018 // CommandObjectType
3019 
3020 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3021     : CommandObjectMultiword(interpreter, "type",
3022                              "Commands for operating on the type system.",
3023                              "type [<sub-command-options>]") {
3024   LoadSubCommand("category",
3025                  CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3026   LoadSubCommand("filter",
3027                  CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3028   LoadSubCommand("format",
3029                  CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3030   LoadSubCommand("summary",
3031                  CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3032 #if LLDB_ENABLE_PYTHON
3033   LoadSubCommand("synthetic",
3034                  CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3035 #endif
3036   LoadSubCommand("lookup",
3037                  CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3038 }
3039 
3040 CommandObjectType::~CommandObjectType() = default;
3041