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