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