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