xref: /llvm-project/lldb/source/Commands/CommandObjectType.cpp (revision 563ef306017a47d387f1c36dd562b172c1ad0626)
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 protected:
1762   void DoExecute(Args &command, CommandReturnObject &result) override {
1763     const size_t argc = command.GetArgumentCount();
1764 
1765     if (argc < 1) {
1766       result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1767                                    m_cmd_name.c_str());
1768       return;
1769     }
1770 
1771     for (auto &entry : command.entries()) {
1772       TypeCategoryImplSP category_sp;
1773       if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1774                                                      category_sp) &&
1775           category_sp) {
1776         category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1777         if (m_options.m_define_enabled.GetCurrentValue())
1778           DataVisualization::Categories::Enable(category_sp,
1779                                                 TypeCategoryMap::Default);
1780       }
1781     }
1782 
1783     result.SetStatus(eReturnStatusSuccessFinishResult);
1784   }
1785 };
1786 
1787 // CommandObjectTypeCategoryEnable
1788 #define LLDB_OPTIONS_type_category_enable
1789 #include "CommandOptions.inc"
1790 
1791 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1792   class CommandOptions : public Options {
1793   public:
1794     CommandOptions() = default;
1795 
1796     ~CommandOptions() override = default;
1797 
1798     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1799                           ExecutionContext *execution_context) override {
1800       Status error;
1801       const int short_option = m_getopt_table[option_idx].val;
1802 
1803       switch (short_option) {
1804       case 'l':
1805         if (!option_arg.empty()) {
1806           m_language = Language::GetLanguageTypeFromString(option_arg);
1807           if (m_language == lldb::eLanguageTypeUnknown)
1808             error.SetErrorStringWithFormat("unrecognized language '%s'",
1809                                            option_arg.str().c_str());
1810         }
1811         break;
1812       default:
1813         llvm_unreachable("Unimplemented option");
1814       }
1815 
1816       return error;
1817     }
1818 
1819     void OptionParsingStarting(ExecutionContext *execution_context) override {
1820       m_language = lldb::eLanguageTypeUnknown;
1821     }
1822 
1823     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1824       return llvm::ArrayRef(g_type_category_enable_options);
1825     }
1826 
1827     // Instance variables to hold the values for command options.
1828 
1829     lldb::LanguageType m_language;
1830   };
1831 
1832   CommandOptions m_options;
1833 
1834   Options *GetOptions() override { return &m_options; }
1835 
1836 public:
1837   CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1838       : CommandObjectParsed(interpreter, "type category enable",
1839                             "Enable a category as a source of formatters.",
1840                             nullptr) {
1841     CommandArgumentEntry type_arg;
1842     CommandArgumentData type_style_arg;
1843 
1844     type_style_arg.arg_type = eArgTypeName;
1845     type_style_arg.arg_repetition = eArgRepeatPlus;
1846 
1847     type_arg.push_back(type_style_arg);
1848 
1849     m_arguments.push_back(type_arg);
1850   }
1851 
1852   ~CommandObjectTypeCategoryEnable() override = default;
1853 
1854 protected:
1855   void DoExecute(Args &command, CommandReturnObject &result) override {
1856     const size_t argc = command.GetArgumentCount();
1857 
1858     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1859       result.AppendErrorWithFormat("%s takes arguments and/or a language",
1860                                    m_cmd_name.c_str());
1861       return;
1862     }
1863 
1864     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1865       DataVisualization::Categories::EnableStar();
1866     } else if (argc > 0) {
1867       for (int i = argc - 1; i >= 0; i--) {
1868         const char *typeA = command.GetArgumentAtIndex(i);
1869         ConstString typeCS(typeA);
1870 
1871         if (!typeCS) {
1872           result.AppendError("empty category name not allowed");
1873           return;
1874         }
1875         DataVisualization::Categories::Enable(typeCS);
1876         lldb::TypeCategoryImplSP cate;
1877         if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1878           if (cate->GetCount() == 0) {
1879             result.AppendWarning("empty category enabled (typo?)");
1880           }
1881         }
1882       }
1883     }
1884 
1885     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1886       DataVisualization::Categories::Enable(m_options.m_language);
1887 
1888     result.SetStatus(eReturnStatusSuccessFinishResult);
1889   }
1890 };
1891 
1892 // CommandObjectTypeCategoryDelete
1893 
1894 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1895 public:
1896   CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1897       : CommandObjectParsed(interpreter, "type category delete",
1898                             "Delete a category and all associated formatters.",
1899                             nullptr) {
1900     CommandArgumentEntry type_arg;
1901     CommandArgumentData type_style_arg;
1902 
1903     type_style_arg.arg_type = eArgTypeName;
1904     type_style_arg.arg_repetition = eArgRepeatPlus;
1905 
1906     type_arg.push_back(type_style_arg);
1907 
1908     m_arguments.push_back(type_arg);
1909   }
1910 
1911   ~CommandObjectTypeCategoryDelete() override = default;
1912 
1913 protected:
1914   void DoExecute(Args &command, CommandReturnObject &result) override {
1915     const size_t argc = command.GetArgumentCount();
1916 
1917     if (argc < 1) {
1918       result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1919                                    m_cmd_name.c_str());
1920       return;
1921     }
1922 
1923     bool success = true;
1924 
1925     // the order is not relevant here
1926     for (int i = argc - 1; i >= 0; i--) {
1927       const char *typeA = command.GetArgumentAtIndex(i);
1928       ConstString typeCS(typeA);
1929 
1930       if (!typeCS) {
1931         result.AppendError("empty category name not allowed");
1932         return;
1933       }
1934       if (!DataVisualization::Categories::Delete(typeCS))
1935         success = false; // keep deleting even if we hit an error
1936     }
1937     if (success) {
1938       result.SetStatus(eReturnStatusSuccessFinishResult);
1939     } else {
1940       result.AppendError("cannot delete one or more categories\n");
1941     }
1942   }
1943 };
1944 
1945 // CommandObjectTypeCategoryDisable
1946 #define LLDB_OPTIONS_type_category_disable
1947 #include "CommandOptions.inc"
1948 
1949 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1950   class CommandOptions : public Options {
1951   public:
1952     CommandOptions() = default;
1953 
1954     ~CommandOptions() override = default;
1955 
1956     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1957                           ExecutionContext *execution_context) override {
1958       Status error;
1959       const int short_option = m_getopt_table[option_idx].val;
1960 
1961       switch (short_option) {
1962       case 'l':
1963         if (!option_arg.empty()) {
1964           m_language = Language::GetLanguageTypeFromString(option_arg);
1965           if (m_language == lldb::eLanguageTypeUnknown)
1966             error.SetErrorStringWithFormat("unrecognized language '%s'",
1967                                            option_arg.str().c_str());
1968         }
1969         break;
1970       default:
1971         llvm_unreachable("Unimplemented option");
1972       }
1973 
1974       return error;
1975     }
1976 
1977     void OptionParsingStarting(ExecutionContext *execution_context) override {
1978       m_language = lldb::eLanguageTypeUnknown;
1979     }
1980 
1981     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1982       return llvm::ArrayRef(g_type_category_disable_options);
1983     }
1984 
1985     // Instance variables to hold the values for command options.
1986 
1987     lldb::LanguageType m_language;
1988   };
1989 
1990   CommandOptions m_options;
1991 
1992   Options *GetOptions() override { return &m_options; }
1993 
1994 public:
1995   CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
1996       : CommandObjectParsed(interpreter, "type category disable",
1997                             "Disable a category as a source of formatters.",
1998                             nullptr) {
1999     CommandArgumentEntry type_arg;
2000     CommandArgumentData type_style_arg;
2001 
2002     type_style_arg.arg_type = eArgTypeName;
2003     type_style_arg.arg_repetition = eArgRepeatPlus;
2004 
2005     type_arg.push_back(type_style_arg);
2006 
2007     m_arguments.push_back(type_arg);
2008   }
2009 
2010   ~CommandObjectTypeCategoryDisable() override = default;
2011 
2012 protected:
2013   void DoExecute(Args &command, CommandReturnObject &result) override {
2014     const size_t argc = command.GetArgumentCount();
2015 
2016     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2017       result.AppendErrorWithFormat("%s takes arguments and/or a language",
2018                                    m_cmd_name.c_str());
2019       return;
2020     }
2021 
2022     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2023       DataVisualization::Categories::DisableStar();
2024     } else if (argc > 0) {
2025       // the order is not relevant here
2026       for (int i = argc - 1; i >= 0; i--) {
2027         const char *typeA = command.GetArgumentAtIndex(i);
2028         ConstString typeCS(typeA);
2029 
2030         if (!typeCS) {
2031           result.AppendError("empty category name not allowed");
2032           return;
2033         }
2034         DataVisualization::Categories::Disable(typeCS);
2035       }
2036     }
2037 
2038     if (m_options.m_language != lldb::eLanguageTypeUnknown)
2039       DataVisualization::Categories::Disable(m_options.m_language);
2040 
2041     result.SetStatus(eReturnStatusSuccessFinishResult);
2042   }
2043 };
2044 
2045 // CommandObjectTypeCategoryList
2046 
2047 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2048 public:
2049   CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2050       : CommandObjectParsed(interpreter, "type category list",
2051                             "Provide a list of all existing categories.",
2052                             nullptr) {
2053     CommandArgumentEntry type_arg;
2054     CommandArgumentData type_style_arg;
2055 
2056     type_style_arg.arg_type = eArgTypeName;
2057     type_style_arg.arg_repetition = eArgRepeatOptional;
2058 
2059     type_arg.push_back(type_style_arg);
2060 
2061     m_arguments.push_back(type_arg);
2062   }
2063 
2064   ~CommandObjectTypeCategoryList() override = default;
2065 
2066   void
2067   HandleArgumentCompletion(CompletionRequest &request,
2068                            OptionElementVector &opt_element_vector) override {
2069     if (request.GetCursorIndex())
2070       return;
2071     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2072         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
2073         nullptr);
2074   }
2075 
2076 protected:
2077   void DoExecute(Args &command, CommandReturnObject &result) override {
2078     const size_t argc = command.GetArgumentCount();
2079 
2080     std::unique_ptr<RegularExpression> regex;
2081 
2082     if (argc == 1) {
2083       const char *arg = command.GetArgumentAtIndex(0);
2084       regex = std::make_unique<RegularExpression>(arg);
2085       if (!regex->IsValid()) {
2086         result.AppendErrorWithFormat(
2087             "syntax error in category regular expression '%s'", arg);
2088         return;
2089       }
2090     } else if (argc != 0) {
2091       result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2092                                    m_cmd_name.c_str());
2093       return;
2094     }
2095 
2096     DataVisualization::Categories::ForEach(
2097         [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2098           if (regex) {
2099             bool escape = true;
2100             if (regex->GetText() == category_sp->GetName()) {
2101               escape = false;
2102             } else if (regex->Execute(category_sp->GetName())) {
2103               escape = false;
2104             }
2105 
2106             if (escape)
2107               return true;
2108           }
2109 
2110           result.GetOutputStream().Printf(
2111               "Category: %s\n", category_sp->GetDescription().c_str());
2112 
2113           return true;
2114         });
2115 
2116     result.SetStatus(eReturnStatusSuccessFinishResult);
2117   }
2118 };
2119 
2120 // CommandObjectTypeFilterList
2121 
2122 class CommandObjectTypeFilterList
2123     : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2124 public:
2125   CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2126       : CommandObjectTypeFormatterList(interpreter, "type filter list",
2127                                        "Show a list of current filters.") {}
2128 };
2129 
2130 // CommandObjectTypeSynthList
2131 
2132 class CommandObjectTypeSynthList
2133     : public CommandObjectTypeFormatterList<SyntheticChildren> {
2134 public:
2135   CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2136       : CommandObjectTypeFormatterList(
2137             interpreter, "type synthetic list",
2138             "Show a list of current synthetic providers.") {}
2139 };
2140 
2141 // CommandObjectTypeFilterDelete
2142 
2143 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2144 public:
2145   CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2146       : CommandObjectTypeFormatterDelete(
2147             interpreter, eFormatCategoryItemFilter) {}
2148 
2149   ~CommandObjectTypeFilterDelete() override = default;
2150 };
2151 
2152 // CommandObjectTypeSynthDelete
2153 
2154 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2155 public:
2156   CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2157       : CommandObjectTypeFormatterDelete(
2158             interpreter, eFormatCategoryItemSynth) {}
2159 
2160   ~CommandObjectTypeSynthDelete() override = default;
2161 };
2162 
2163 
2164 // CommandObjectTypeFilterClear
2165 
2166 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2167 public:
2168   CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2169       : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFilter,
2170                                         "type filter clear",
2171                                         "Delete all existing filter.") {}
2172 };
2173 
2174 // CommandObjectTypeSynthClear
2175 
2176 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2177 public:
2178   CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2179       : CommandObjectTypeFormatterClear(
2180             interpreter, eFormatCategoryItemSynth, "type synthetic clear",
2181             "Delete all existing synthetic providers.") {}
2182 };
2183 
2184 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2185     Args &command, CommandReturnObject &result) {
2186   auto options = std::make_unique<SynthAddOptions>(
2187       m_options.m_skip_pointers, m_options.m_skip_references,
2188       m_options.m_cascade, m_options.m_match_type, m_options.m_category);
2189 
2190   for (auto &entry : command.entries()) {
2191     if (entry.ref().empty()) {
2192       result.AppendError("empty typenames not allowed");
2193       return false;
2194     }
2195 
2196     options->m_target_types << std::string(entry.ref());
2197   }
2198 
2199   m_interpreter.GetPythonCommandsFromIOHandler(
2200       "    ",             // Prompt
2201       *this,              // IOHandlerDelegate
2202       options.release()); // Baton for the "io_handler" that will be passed back
2203                           // into our IOHandlerDelegate functions
2204   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2205   return result.Succeeded();
2206 }
2207 
2208 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2209     Args &command, CommandReturnObject &result) {
2210   const size_t argc = command.GetArgumentCount();
2211 
2212   if (argc < 1) {
2213     result.AppendErrorWithFormat("%s takes one or more args.\n",
2214                                  m_cmd_name.c_str());
2215     return false;
2216   }
2217 
2218   if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2219     result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2220                                  "directly input Python code.\n",
2221                                  m_cmd_name.c_str());
2222     return false;
2223   }
2224 
2225   SyntheticChildrenSP entry;
2226 
2227   ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2228       SyntheticChildren::Flags()
2229           .SetCascades(m_options.m_cascade)
2230           .SetSkipPointers(m_options.m_skip_pointers)
2231           .SetSkipReferences(m_options.m_skip_references),
2232       m_options.m_class_name.c_str());
2233 
2234   entry.reset(impl);
2235 
2236   ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2237 
2238   if (interpreter &&
2239       !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2240     result.AppendWarning("The provided class does not exist - please define it "
2241                          "before attempting to use this synthetic provider");
2242 
2243   // now I have a valid provider, let's add it to every type
2244 
2245   lldb::TypeCategoryImplSP category;
2246   DataVisualization::Categories::GetCategory(
2247       ConstString(m_options.m_category.c_str()), category);
2248 
2249   Status error;
2250 
2251   for (auto &arg_entry : command.entries()) {
2252     if (arg_entry.ref().empty()) {
2253       result.AppendError("empty typenames not allowed");
2254       return false;
2255     }
2256 
2257     ConstString typeCS(arg_entry.ref());
2258     if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category,
2259                   &error)) {
2260       result.AppendError(error.AsCString());
2261       return false;
2262     }
2263   }
2264 
2265   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2266   return result.Succeeded();
2267 }
2268 
2269 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2270     CommandInterpreter &interpreter)
2271     : CommandObjectParsed(interpreter, "type synthetic add",
2272                           "Add a new synthetic provider for a type.", nullptr),
2273       IOHandlerDelegateMultiline("DONE"), m_options() {
2274   CommandArgumentEntry type_arg;
2275   CommandArgumentData type_style_arg;
2276 
2277   type_style_arg.arg_type = eArgTypeName;
2278   type_style_arg.arg_repetition = eArgRepeatPlus;
2279 
2280   type_arg.push_back(type_style_arg);
2281 
2282   m_arguments.push_back(type_arg);
2283 }
2284 
2285 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2286                                          SyntheticChildrenSP entry,
2287                                          FormatterMatchType match_type,
2288                                          std::string category_name,
2289                                          Status *error) {
2290   lldb::TypeCategoryImplSP category;
2291   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2292                                              category);
2293 
2294   if (match_type == eFormatterMatchExact) {
2295     if (FixArrayTypeNameWithRegex(type_name))
2296       match_type = eFormatterMatchRegex;
2297   }
2298 
2299   // Only check for conflicting filters in the same category if `type_name` is
2300   // an actual type name. Matching a regex string against registered regexes
2301   // doesn't work.
2302   if (match_type == eFormatterMatchExact) {
2303     // It's not generally possible to get a type object here. For example, this
2304     // command can be run before loading any binaries. Do just a best-effort
2305     // name-based lookup here to try to prevent conflicts.
2306     FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(),
2307                                             FormattersMatchCandidate::Flags());
2308     if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter,
2309                              false)) {
2310       if (error)
2311         error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2312                                         "filter is defined in same category!",
2313                                         type_name.AsCString());
2314       return false;
2315     }
2316   }
2317 
2318   if (match_type == eFormatterMatchRegex) {
2319     RegularExpression typeRX(type_name.GetStringRef());
2320     if (!typeRX.IsValid()) {
2321       if (error)
2322         error->SetErrorString(
2323             "regex format error (maybe this is not really a regex?)");
2324       return false;
2325     }
2326   }
2327 
2328   if (match_type == eFormatterMatchCallback) {
2329     const char *function_name = type_name.AsCString();
2330     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2331     if (interpreter && !interpreter->CheckObjectExists(function_name)) {
2332       error->SetErrorStringWithFormat(
2333           "The provided recognizer function \"%s\" does not exist - "
2334           "please define it before attempting to use this summary.\n",
2335           function_name);
2336       return false;
2337     }
2338   }
2339 
2340   category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry);
2341   return true;
2342 }
2343 
2344 #define LLDB_OPTIONS_type_filter_add
2345 #include "CommandOptions.inc"
2346 
2347 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2348 private:
2349   class CommandOptions : public Options {
2350     typedef std::vector<std::string> option_vector;
2351 
2352   public:
2353     CommandOptions() = default;
2354 
2355     ~CommandOptions() override = default;
2356 
2357     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2358                           ExecutionContext *execution_context) override {
2359       Status error;
2360       const int short_option = m_getopt_table[option_idx].val;
2361       bool success;
2362 
2363       switch (short_option) {
2364       case 'C':
2365         m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2366         if (!success)
2367           error.SetErrorStringWithFormat("invalid value for cascade: %s",
2368                                          option_arg.str().c_str());
2369         break;
2370       case 'c':
2371         m_expr_paths.push_back(std::string(option_arg));
2372         has_child_list = true;
2373         break;
2374       case 'p':
2375         m_skip_pointers = true;
2376         break;
2377       case 'r':
2378         m_skip_references = true;
2379         break;
2380       case 'w':
2381         m_category = std::string(option_arg);
2382         break;
2383       case 'x':
2384         m_regex = true;
2385         break;
2386       default:
2387         llvm_unreachable("Unimplemented option");
2388       }
2389 
2390       return error;
2391     }
2392 
2393     void OptionParsingStarting(ExecutionContext *execution_context) override {
2394       m_cascade = true;
2395       m_skip_pointers = false;
2396       m_skip_references = false;
2397       m_category = "default";
2398       m_expr_paths.clear();
2399       has_child_list = false;
2400       m_regex = false;
2401     }
2402 
2403     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2404       return llvm::ArrayRef(g_type_filter_add_options);
2405     }
2406 
2407     // Instance variables to hold the values for command options.
2408 
2409     bool m_cascade;
2410     bool m_skip_references;
2411     bool m_skip_pointers;
2412     bool m_input_python;
2413     option_vector m_expr_paths;
2414     std::string m_category;
2415     bool has_child_list;
2416     bool m_regex;
2417 
2418     typedef option_vector::iterator ExpressionPathsIterator;
2419   };
2420 
2421   CommandOptions m_options;
2422 
2423   Options *GetOptions() override { return &m_options; }
2424 
2425   enum FilterFormatType { eRegularFilter, eRegexFilter };
2426 
2427   bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2428                  FilterFormatType type, std::string category_name,
2429                  Status *error) {
2430     lldb::TypeCategoryImplSP category;
2431     DataVisualization::Categories::GetCategory(
2432         ConstString(category_name.c_str()), category);
2433 
2434     if (type == eRegularFilter) {
2435       if (FixArrayTypeNameWithRegex(type_name))
2436         type = eRegexFilter;
2437     }
2438 
2439     // Only check for conflicting synthetic child providers in the same category
2440     // if `type_name` is an actual type name. Matching a regex string against
2441     // registered regexes doesn't work.
2442     if (type == eRegularFilter) {
2443       // It's not generally possible to get a type object here. For example,
2444       // this command can be run before loading any binaries. Do just a
2445       // best-effort name-based lookup here to try to prevent conflicts.
2446       FormattersMatchCandidate candidate_type(
2447           type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2448       lldb::SyntheticChildrenSP entry;
2449       if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth,
2450                                false)) {
2451         if (error)
2452           error->SetErrorStringWithFormat("cannot add filter for type %s when "
2453                                           "synthetic is defined in same "
2454                                           "category!",
2455                                           type_name.AsCString());
2456         return false;
2457       }
2458     }
2459 
2460     FormatterMatchType match_type = eFormatterMatchExact;
2461     if (type == eRegexFilter) {
2462       match_type = eFormatterMatchRegex;
2463       RegularExpression typeRX(type_name.GetStringRef());
2464       if (!typeRX.IsValid()) {
2465         if (error)
2466           error->SetErrorString(
2467               "regex format error (maybe this is not really a regex?)");
2468         return false;
2469       }
2470     }
2471     category->AddTypeFilter(type_name.GetStringRef(), match_type, entry);
2472     return true;
2473   }
2474 
2475 public:
2476   CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2477       : CommandObjectParsed(interpreter, "type filter add",
2478                             "Add a new filter for a type.", nullptr) {
2479     CommandArgumentEntry type_arg;
2480     CommandArgumentData type_style_arg;
2481 
2482     type_style_arg.arg_type = eArgTypeName;
2483     type_style_arg.arg_repetition = eArgRepeatPlus;
2484 
2485     type_arg.push_back(type_style_arg);
2486 
2487     m_arguments.push_back(type_arg);
2488 
2489     SetHelpLong(
2490         R"(
2491 The following examples of 'type filter add' refer to this code snippet for context:
2492 
2493     class Foo {
2494         int a;
2495         int b;
2496         int c;
2497         int d;
2498         int e;
2499         int f;
2500         int g;
2501         int h;
2502         int i;
2503     }
2504     Foo my_foo;
2505 
2506 Adding a simple filter:
2507 
2508 (lldb) type filter add --child a --child g Foo
2509 (lldb) frame variable my_foo
2510 
2511 )"
2512         "Produces output where only a and g are displayed.  Other children of my_foo \
2513 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2514         R"(
2515 
2516 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2517 
2518 )"
2519         "The formatting option --raw on frame variable bypasses the filter, showing \
2520 all children of my_foo as if no filter was defined:"
2521         R"(
2522 
2523 (lldb) frame variable my_foo --raw)");
2524   }
2525 
2526   ~CommandObjectTypeFilterAdd() override = default;
2527 
2528 protected:
2529   void DoExecute(Args &command, CommandReturnObject &result) override {
2530     const size_t argc = command.GetArgumentCount();
2531 
2532     if (argc < 1) {
2533       result.AppendErrorWithFormat("%s takes one or more args.\n",
2534                                    m_cmd_name.c_str());
2535       return;
2536     }
2537 
2538     if (m_options.m_expr_paths.empty()) {
2539       result.AppendErrorWithFormat("%s needs one or more children.\n",
2540                                    m_cmd_name.c_str());
2541       return;
2542     }
2543 
2544     TypeFilterImplSP entry(new TypeFilterImpl(
2545         SyntheticChildren::Flags()
2546             .SetCascades(m_options.m_cascade)
2547             .SetSkipPointers(m_options.m_skip_pointers)
2548             .SetSkipReferences(m_options.m_skip_references)));
2549 
2550     // go through the expression paths
2551     CommandOptions::ExpressionPathsIterator begin,
2552         end = m_options.m_expr_paths.end();
2553 
2554     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2555       entry->AddExpressionPath(*begin);
2556 
2557     // now I have a valid provider, let's add it to every type
2558 
2559     lldb::TypeCategoryImplSP category;
2560     DataVisualization::Categories::GetCategory(
2561         ConstString(m_options.m_category.c_str()), category);
2562 
2563     Status error;
2564 
2565     WarnOnPotentialUnquotedUnsignedType(command, result);
2566 
2567     for (auto &arg_entry : command.entries()) {
2568       if (arg_entry.ref().empty()) {
2569         result.AppendError("empty typenames not allowed");
2570         return;
2571       }
2572 
2573       ConstString typeCS(arg_entry.ref());
2574       if (!AddFilter(typeCS, entry,
2575                      m_options.m_regex ? eRegexFilter : eRegularFilter,
2576                      m_options.m_category, &error)) {
2577         result.AppendError(error.AsCString());
2578         return;
2579       }
2580     }
2581 
2582     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2583   }
2584 };
2585 
2586 // "type lookup"
2587 #define LLDB_OPTIONS_type_lookup
2588 #include "CommandOptions.inc"
2589 
2590 class CommandObjectTypeLookup : public CommandObjectRaw {
2591 protected:
2592   // this function is allowed to do a more aggressive job at guessing languages
2593   // than the expression parser is comfortable with - so leave the original
2594   // call alone and add one that is specific to type lookup
2595   lldb::LanguageType GuessLanguage(StackFrame *frame) {
2596     lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2597 
2598     if (!frame)
2599       return lang_type;
2600 
2601     lang_type = frame->GuessLanguage();
2602     if (lang_type != lldb::eLanguageTypeUnknown)
2603       return lang_type;
2604 
2605     Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2606     if (s)
2607       lang_type = s->GetMangled().GuessLanguage();
2608 
2609     return lang_type;
2610   }
2611 
2612   class CommandOptions : public OptionGroup {
2613   public:
2614     CommandOptions() = default;
2615 
2616     ~CommandOptions() override = default;
2617 
2618     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2619       return llvm::ArrayRef(g_type_lookup_options);
2620     }
2621 
2622     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2623                           ExecutionContext *execution_context) override {
2624       Status error;
2625 
2626       const int short_option = g_type_lookup_options[option_idx].short_option;
2627 
2628       switch (short_option) {
2629       case 'h':
2630         m_show_help = true;
2631         break;
2632 
2633       case 'l':
2634         m_language = Language::GetLanguageTypeFromString(option_value);
2635         break;
2636 
2637       default:
2638         llvm_unreachable("Unimplemented option");
2639       }
2640 
2641       return error;
2642     }
2643 
2644     void OptionParsingStarting(ExecutionContext *execution_context) override {
2645       m_show_help = false;
2646       m_language = eLanguageTypeUnknown;
2647     }
2648 
2649     // Options table: Required for subclasses of Options.
2650 
2651     bool m_show_help = false;
2652     lldb::LanguageType m_language = eLanguageTypeUnknown;
2653   };
2654 
2655   OptionGroupOptions m_option_group;
2656   CommandOptions m_command_options;
2657 
2658 public:
2659   CommandObjectTypeLookup(CommandInterpreter &interpreter)
2660       : CommandObjectRaw(interpreter, "type lookup",
2661                          "Lookup types and declarations in the current target, "
2662                          "following language-specific naming conventions.",
2663                          "type lookup <type-specifier>",
2664                          eCommandRequiresTarget) {
2665     m_option_group.Append(&m_command_options);
2666     m_option_group.Finalize();
2667   }
2668 
2669   ~CommandObjectTypeLookup() override = default;
2670 
2671   Options *GetOptions() override { return &m_option_group; }
2672 
2673   llvm::StringRef GetHelpLong() override {
2674     if (!m_cmd_help_long.empty())
2675       return m_cmd_help_long;
2676 
2677     StreamString stream;
2678     Language::ForEach([&](Language *lang) {
2679       if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2680         stream.Printf("%s\n", help);
2681       return true;
2682     });
2683 
2684     m_cmd_help_long = std::string(stream.GetString());
2685     return m_cmd_help_long;
2686   }
2687 
2688   void DoExecute(llvm::StringRef raw_command_line,
2689                  CommandReturnObject &result) override {
2690     if (raw_command_line.empty()) {
2691       result.AppendError(
2692           "type lookup cannot be invoked without a type name as argument");
2693       return;
2694     }
2695 
2696     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2697     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2698 
2699     OptionsWithRaw args(raw_command_line);
2700     const char *name_of_type = args.GetRawPart().c_str();
2701 
2702     if (args.HasArgs())
2703       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2704                                  exe_ctx))
2705         return;
2706 
2707     ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2708 
2709     bool any_found = false;
2710 
2711     std::vector<Language *> languages;
2712 
2713     bool is_global_search = false;
2714     LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2715 
2716     if ((is_global_search =
2717              (m_command_options.m_language == eLanguageTypeUnknown))) {
2718       Language::ForEach([&](Language *lang) {
2719         languages.push_back(lang);
2720         return true;
2721       });
2722     } else {
2723       languages.push_back(Language::FindPlugin(m_command_options.m_language));
2724     }
2725 
2726     // This is not the most efficient way to do this, but we support very few
2727     // languages so the cost of the sort is going to be dwarfed by the actual
2728     // lookup anyway
2729     if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2730       guessed_language = GuessLanguage(frame);
2731       if (guessed_language != eLanguageTypeUnknown) {
2732         llvm::sort(
2733             languages.begin(), languages.end(),
2734             [guessed_language](Language *lang1, Language *lang2) -> bool {
2735               if (!lang1 || !lang2)
2736                 return false;
2737               LanguageType lt1 = lang1->GetLanguageType();
2738               LanguageType lt2 = lang2->GetLanguageType();
2739               if (lt1 == guessed_language)
2740                 return true; // make the selected frame's language come first
2741               if (lt2 == guessed_language)
2742                 return false; // make the selected frame's language come first
2743               return (lt1 < lt2); // normal comparison otherwise
2744             });
2745       }
2746     }
2747 
2748     bool is_first_language = true;
2749 
2750     for (Language *language : languages) {
2751       if (!language)
2752         continue;
2753 
2754       if (auto scavenger = language->GetTypeScavenger()) {
2755         Language::TypeScavenger::ResultSet search_results;
2756         if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2757           for (const auto &search_result : search_results) {
2758             if (search_result && search_result->IsValid()) {
2759               any_found = true;
2760               search_result->DumpToStream(result.GetOutputStream(),
2761                                           this->m_command_options.m_show_help);
2762             }
2763           }
2764         }
2765       }
2766       // this is "type lookup SomeName" and we did find a match, so get out
2767       if (any_found && is_global_search)
2768         break;
2769       else if (is_first_language && is_global_search &&
2770                guessed_language != lldb::eLanguageTypeUnknown) {
2771         is_first_language = false;
2772         result.GetOutputStream().Printf(
2773             "no type was found in the current language %s matching '%s'; "
2774             "performing a global search across all languages\n",
2775             Language::GetNameForLanguageType(guessed_language), name_of_type);
2776       }
2777     }
2778 
2779     if (!any_found)
2780       result.AppendMessageWithFormat("no type was found matching '%s'\n",
2781                                      name_of_type);
2782 
2783     result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2784                                : lldb::eReturnStatusSuccessFinishNoResult);
2785   }
2786 };
2787 
2788 template <typename FormatterType>
2789 class CommandObjectFormatterInfo : public CommandObjectRaw {
2790 public:
2791   typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2792       DiscoveryFunction;
2793   CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2794                              const char *formatter_name,
2795                              DiscoveryFunction discovery_func)
2796       : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2797         m_formatter_name(formatter_name ? formatter_name : ""),
2798         m_discovery_function(discovery_func) {
2799     StreamString name;
2800     name.Printf("type %s info", formatter_name);
2801     SetCommandName(name.GetString());
2802     StreamString help;
2803     help.Printf("This command evaluates the provided expression and shows "
2804                 "which %s is applied to the resulting value (if any).",
2805                 formatter_name);
2806     SetHelp(help.GetString());
2807     StreamString syntax;
2808     syntax.Printf("type %s info <expr>", formatter_name);
2809     SetSyntax(syntax.GetString());
2810   }
2811 
2812   ~CommandObjectFormatterInfo() override = default;
2813 
2814 protected:
2815   void DoExecute(llvm::StringRef command,
2816                  CommandReturnObject &result) override {
2817     TargetSP target_sp = GetDebugger().GetSelectedTarget();
2818     Thread *thread = GetDefaultThread();
2819     if (!thread) {
2820       result.AppendError("no default thread");
2821       return;
2822     }
2823 
2824     StackFrameSP frame_sp =
2825         thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
2826     ValueObjectSP result_valobj_sp;
2827     EvaluateExpressionOptions options;
2828     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2829         command, frame_sp.get(), result_valobj_sp, options);
2830     if (expr_result == eExpressionCompleted && result_valobj_sp) {
2831       result_valobj_sp =
2832           result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2833               target_sp->GetPreferDynamicValue(),
2834               target_sp->GetEnableSyntheticValue());
2835       typename FormatterType::SharedPointer formatter_sp =
2836           m_discovery_function(*result_valobj_sp);
2837       if (formatter_sp) {
2838         std::string description(formatter_sp->GetDescription());
2839         result.GetOutputStream()
2840             << m_formatter_name << " applied to ("
2841             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2842             << ") " << command << " is: " << description << "\n";
2843         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2844       } else {
2845         result.GetOutputStream()
2846             << "no " << m_formatter_name << " applies to ("
2847             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2848             << ") " << command << "\n";
2849         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2850       }
2851     } else {
2852       result.AppendError("failed to evaluate expression");
2853     }
2854   }
2855 
2856 private:
2857   std::string m_formatter_name;
2858   DiscoveryFunction m_discovery_function;
2859 };
2860 
2861 class CommandObjectTypeFormat : public CommandObjectMultiword {
2862 public:
2863   CommandObjectTypeFormat(CommandInterpreter &interpreter)
2864       : CommandObjectMultiword(
2865             interpreter, "type format",
2866             "Commands for customizing value display formats.",
2867             "type format [<sub-command-options>] ") {
2868     LoadSubCommand(
2869         "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2870     LoadSubCommand("clear", CommandObjectSP(
2871                                 new CommandObjectTypeFormatClear(interpreter)));
2872     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2873                                  interpreter)));
2874     LoadSubCommand(
2875         "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2876     LoadSubCommand(
2877         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2878                     interpreter, "format",
2879                     [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2880                       return valobj.GetValueFormat();
2881                     })));
2882   }
2883 
2884   ~CommandObjectTypeFormat() override = default;
2885 };
2886 
2887 class CommandObjectTypeSynth : public CommandObjectMultiword {
2888 public:
2889   CommandObjectTypeSynth(CommandInterpreter &interpreter)
2890       : CommandObjectMultiword(
2891             interpreter, "type synthetic",
2892             "Commands for operating on synthetic type representations.",
2893             "type synthetic [<sub-command-options>] ") {
2894     LoadSubCommand("add",
2895                    CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2896     LoadSubCommand(
2897         "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2898     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2899                                  interpreter)));
2900     LoadSubCommand(
2901         "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2902     LoadSubCommand(
2903         "info",
2904         CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2905             interpreter, "synthetic",
2906             [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2907               return valobj.GetSyntheticChildren();
2908             })));
2909   }
2910 
2911   ~CommandObjectTypeSynth() override = default;
2912 };
2913 
2914 class CommandObjectTypeFilter : public CommandObjectMultiword {
2915 public:
2916   CommandObjectTypeFilter(CommandInterpreter &interpreter)
2917       : CommandObjectMultiword(interpreter, "type filter",
2918                                "Commands for operating on type filters.",
2919                                "type filter [<sub-command-options>] ") {
2920     LoadSubCommand(
2921         "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2922     LoadSubCommand("clear", CommandObjectSP(
2923                                 new CommandObjectTypeFilterClear(interpreter)));
2924     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2925                                  interpreter)));
2926     LoadSubCommand(
2927         "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2928   }
2929 
2930   ~CommandObjectTypeFilter() override = default;
2931 };
2932 
2933 class CommandObjectTypeCategory : public CommandObjectMultiword {
2934 public:
2935   CommandObjectTypeCategory(CommandInterpreter &interpreter)
2936       : CommandObjectMultiword(interpreter, "type category",
2937                                "Commands for operating on type categories.",
2938                                "type category [<sub-command-options>] ") {
2939     LoadSubCommand(
2940         "define",
2941         CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
2942     LoadSubCommand(
2943         "enable",
2944         CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
2945     LoadSubCommand(
2946         "disable",
2947         CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
2948     LoadSubCommand(
2949         "delete",
2950         CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
2951     LoadSubCommand("list", CommandObjectSP(
2952                                new CommandObjectTypeCategoryList(interpreter)));
2953   }
2954 
2955   ~CommandObjectTypeCategory() override = default;
2956 };
2957 
2958 class CommandObjectTypeSummary : public CommandObjectMultiword {
2959 public:
2960   CommandObjectTypeSummary(CommandInterpreter &interpreter)
2961       : CommandObjectMultiword(
2962             interpreter, "type summary",
2963             "Commands for editing variable summary display options.",
2964             "type summary [<sub-command-options>] ") {
2965     LoadSubCommand(
2966         "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
2967     LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
2968                                 interpreter)));
2969     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
2970                                  interpreter)));
2971     LoadSubCommand(
2972         "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
2973     LoadSubCommand(
2974         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
2975                     interpreter, "summary",
2976                     [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
2977                       return valobj.GetSummaryFormat();
2978                     })));
2979   }
2980 
2981   ~CommandObjectTypeSummary() override = default;
2982 };
2983 
2984 // CommandObjectType
2985 
2986 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
2987     : CommandObjectMultiword(interpreter, "type",
2988                              "Commands for operating on the type system.",
2989                              "type [<sub-command-options>]") {
2990   LoadSubCommand("category",
2991                  CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
2992   LoadSubCommand("filter",
2993                  CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
2994   LoadSubCommand("format",
2995                  CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
2996   LoadSubCommand("summary",
2997                  CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
2998   LoadSubCommand("synthetic",
2999                  CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3000   LoadSubCommand("lookup",
3001                  CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3002 }
3003 
3004 CommandObjectType::~CommandObjectType() = default;
3005