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