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