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