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