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