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