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