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