Index: examples/python/bsd.py =================================================================== --- examples/python/bsd.py +++ examples/python/bsd.py @@ -1,5 +1,6 @@ #!/usr/bin/python +import cmd import optparse import os import shlex @@ -76,6 +77,22 @@ self.file.seek(saved_pos, 0) return bytes + def save(self, path=None, overwrite=False): + ''' + Save the contents of the object to disk using 'path' argument as + the path, or save it to the current working directory using the + object name. + ''' + + if path is None: + path = self.name + if not overwrite and os.path.exists(path): + print('error: outfile "%s" already exists' % (path)) + return + print('Saving "%s" to "%s"...' % (self.name, path)) + with open(path, 'w') as f: + f.write(self.get_bytes()) + class StringTable(object): def __init__(self, bytes): @@ -186,6 +203,67 @@ for obj in self.objects: obj.dump(f=f, flat=flat) +class Interactive(cmd.Cmd): + '''Interactive prompt for exploring contents of BSD archive files, type + "help" to see a list of supported commands.''' + image_option_parser = None + + def __init__(self, archives): + cmd.Cmd.__init__(self) + self.use_rawinput = False + self.intro = ('Interactive BSD archive prompt, type "help" to see a ' + 'list of supported commands.') + self.archives = archives + self.prompt = '% ' + + def default(self, line): + '''Catch all for unknown command, which will exit the interpreter.''' + print("unknown command: %s" % line) + return True + + def do_q(self, line): + '''Quit command''' + return True + + def do_quit(self, line): + '''Quit command''' + return True + + def do_extract(self, line): + args = shlex.split(line) + if args: + extracted = False + for object_name in args: + for archive in self.archives: + matches = archive.find(object_name) + if matches: + for object in matches: + object.save(overwrite=False) + extracted = True + if not extracted: + print('error: no object matches "%s" in any archives' % ( + object_name)) + else: + print('error: must specify the name of an object to extract') + + def do_ls(self, line): + args = shlex.split(line) + if args: + for object_name in args: + for archive in self.archives: + matches = archive.find(object_name) + if matches: + for object in matches: + object.dump(flat=False) + else: + print('error: no object matches "%s" in "%s"' % ( + object_name, archive.path)) + else: + for archive in self.archives: + archive.dump(flat=True) + print('') + + def main(): parser = optparse.OptionParser( @@ -243,9 +321,24 @@ 'then the extracted object file will be extracted into the ' 'current working directory if a file doesn\'t already exist ' 'with that name.')) + parser.add_option( + '-i', '--interactive', + action='store_true', + dest='interactive', + default=False, + help=('Enter an interactive shell that allows users to interactively ' + 'explore contents of .a files.')) (options, args) = parser.parse_args(sys.argv[1:]) + if options.interactive: + archives = [] + for path in args: + archives.append(Archive(path)) + interpreter = Interactive(archives) + interpreter.cmdloop() + return + for path in args: archive = Archive(path) if options.object_name: @@ -256,17 +349,7 @@ if options.extract: if len(matches) == 1: dump_all = False - if options.outfile is None: - outfile_path = matches[0].name - else: - outfile_path = options.outfile - if os.path.exists(outfile_path): - print('error: outfile "%s" already exists' % ( - outfile_path)) - else: - print('Saving file to "%s"...' % (outfile_path)) - with open(outfile_path, 'w') as outfile: - outfile.write(matches[0].get_bytes()) + matches[0].save(path=options.outfile, overwrite=False) else: print('error: multiple objects match "%s". Specify ' 'the modification time using --mtime.' % ( Index: examples/python/gdbremote.py =================================================================== --- examples/python/gdbremote.py +++ examples/python/gdbremote.py @@ -685,32 +685,33 @@ if extension == '.xml': response = Packet(rsp) xml_string = response.get_hex_ascii_str() - ch = xml_string[0] - if ch == 'l': - xml_string = xml_string[1:] - xml_root = ET.fromstring(xml_string) - for reg_element in xml_root.findall("./feature/reg"): - if not 'value_regnums' in reg_element.attrib: - reg_info = RegisterInfo([]) - if 'name' in reg_element.attrib: - reg_info.info[ - 'name'] = reg_element.attrib['name'] - else: - reg_info.info['name'] = 'unspecified' - if 'encoding' in reg_element.attrib: - reg_info.info['encoding'] = reg_element.attrib[ - 'encoding'] - else: - reg_info.info['encoding'] = 'uint' - if 'offset' in reg_element.attrib: - reg_info.info[ - 'offset'] = reg_element.attrib['offset'] - if 'bitsize' in reg_element.attrib: - reg_info.info[ - 'bitsize'] = reg_element.attrib['bitsize'] - g_register_infos.append(reg_info) - print 'XML for "%s":' % (data[2]) - ET.dump(xml_root) + if xml_string: + ch = xml_string[0] + if ch == 'l': + xml_string = xml_string[1:] + xml_root = ET.fromstring(xml_string) + for reg_element in xml_root.findall("./feature/reg"): + if not 'value_regnums' in reg_element.attrib: + reg_info = RegisterInfo([]) + if 'name' in reg_element.attrib: + reg_info.info[ + 'name'] = reg_element.attrib['name'] + else: + reg_info.info['name'] = 'unspecified' + if 'encoding' in reg_element.attrib: + reg_info.info['encoding'] = reg_element.attrib[ + 'encoding'] + else: + reg_info.info['encoding'] = 'uint' + if 'offset' in reg_element.attrib: + reg_info.info[ + 'offset'] = reg_element.attrib['offset'] + if 'bitsize' in reg_element.attrib: + reg_info.info[ + 'bitsize'] = reg_element.attrib['bitsize'] + g_register_infos.append(reg_info) + print 'XML for "%s":' % (data[2]) + ET.dump(xml_root) def cmd_A(options, cmd, args): @@ -810,6 +811,14 @@ return False +def cmd_qSpeedTest(options, cmd, args): + print("qSpeedTest: cmd='%s', args='%s'" % (cmd, args)) + + +def rsp_qSpeedTest(options, cmd, cmd_args, rsp): + print("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp, cmd, args)) + + def cmd_vCont(options, cmd, args): if args == '?': print "%s: get supported extended continue modes" % (cmd) @@ -861,8 +870,10 @@ s += 'step' elif mode == 'S': s += 'step with signal' - else: - s += 'unrecognized vCont mode: ', mode + elif mode == 't': + s += 'stop' + # else: + # s += 'unrecognized vCont mode: ', str(mode) print s elif rsp: if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X': @@ -933,7 +944,7 @@ def rsp_hex_big_endian(options, cmd, cmd_args, rsp): if rsp == '': print "%s%s is not supported" % (cmd, cmd_args) - else: + else: packet = Packet(rsp) uval = packet.get_hex_uint('big') print '%s: 0x%x' % (cmd, uval) @@ -1225,6 +1236,7 @@ 'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"}, 'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"}, 'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"}, + 'qSpeedTest': {'cmd':cmd_qSpeedTest, 'rsp': rsp_qSpeedTest, 'name': 'speed test packdet'}, 'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"}, 'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"}, 's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"}, @@ -1283,6 +1295,49 @@ f.close() +def round_up(n, incr): + return float(((int(n) + incr) / incr) * incr) + + +def plot_latencies(sec_times): + # import numpy as np + import matplotlib.pyplot as plt + + for (i, name) in enumerate(sec_times.keys()): + times = sec_times[name] + if len(times) <= 1: + continue + plt.subplot(2, 1, 1) + plt.title('Packet "%s" Times' % (name)) + plt.xlabel('Packet') + units = 'ms' + adj_times = [] + max_time = 0.0 + for time in times: + time = time * 1000.0 + adj_times.append(time) + if time > max_time: + max_time = time + if max_time < 1.0: + units = 'us' + max_time = 0.0 + for i in range(len(adj_times)): + adj_times[i] *= 1000.0 + if adj_times[i] > max_time: + max_time = adj_times[i] + plt.ylabel('Time (%s)' % (units)) + max_y = None + for i in [5.0, 10.0, 25.0, 50.0]: + if max_time < i: + max_y = round_up(max_time, i) + break + if max_y is None: + max_y = round_up(max_time, 100.0) + plt.ylim(0.0, max_y) + plt.plot(adj_times, 'o-') + plt.show() + + def parse_gdb_log(file, options): '''Parse a GDB log file that was generated by enabling logging with: (lldb) log enable --threadsafe --timestamp --file gdb-remote packets @@ -1306,10 +1361,11 @@ base_time = 0.0 last_time = 0.0 - packet_send_time = 0.0 + min_time = 100000000.0 packet_total_times = {} - packet_times = [] - packet_count = {} + all_packet_times = [] + packet_times = {} + packet_counts = {} lines = file.read().splitlines() last_command = None last_command_args = None @@ -1412,32 +1468,39 @@ curr_time = float(match.group(2)) if last_time and not is_command: delta = curr_time - last_time - packet_times.append(delta) + all_packet_times.append(delta) delta = 0.0 if base_time: delta = curr_time - last_time else: base_time = curr_time - if is_command: - packet_send_time = curr_time - elif line.find('read packet: $') >= 0 and packet_name: - if packet_name in packet_total_times: - packet_total_times[packet_name] += delta - packet_count[packet_name] += 1 - else: - packet_total_times[packet_name] = delta - packet_count[packet_name] = 1 - packet_name = None + if not is_command: + if line.find('read packet: $') >= 0 and packet_name: + if packet_name in packet_total_times: + packet_total_times[packet_name] += delta + packet_counts[packet_name] += 1 + else: + packet_total_times[packet_name] = delta + packet_counts[packet_name] = 1 + if packet_name not in packet_times: + packet_times[packet_name] = [] + packet_times[packet_name].append(delta) + packet_name = None + if min_time > delta: + min_time = delta if not options or not options.quiet: - print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3)) + print '%s%.6f %+.6f%s' % (match.group(1), + curr_time - base_time, + delta, + match.group(3)) last_time = curr_time # else: # print line - (average, std_dev) = calculate_mean_and_standard_deviation(packet_times) + (average, std_dev) = calculate_mean_and_standard_deviation(all_packet_times) if average and std_dev: - print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev) + print '%u packets with average packet time of %f and standard deviation of %f' % (len(all_packet_times), average, std_dev) if packet_total_times: total_packet_time = 0.0 total_packet_count = 0 @@ -1446,19 +1509,21 @@ # print 'value = (%s) %s' % (type(vvv), vvv) # if type(vvv) == 'float': total_packet_time += vvv - for key, vvv in packet_count.items(): + for key, vvv in packet_counts.items(): total_packet_count += vvv - print '#---------------------------------------------------' + print '#------------------------------------------------------------' print '# Packet timing summary:' - print '# Totals: time = %6f, count = %6d' % (total_packet_time, total_packet_count) - print '#---------------------------------------------------' - print '# Packet Time (sec) Percent Count ' - print '#------------------------- ---------- ------- ------' + print '# Totals: time = %6f, count = %6d' % (total_packet_time, + total_packet_count) + print '# Min packet time: time = %6f' % (min_time) + print '#------------------------------------------------------------' + print '# Packet Time (sec) Percent Count Latency' + print '#------------------------- ----------- ------- ------ -------' if options and options.sort_count: res = sorted( - packet_count, - key=packet_count.__getitem__, + packet_counts, + key=packet_counts.__getitem__, reverse=True) else: res = sorted( @@ -1471,11 +1536,12 @@ packet_total_time = packet_total_times[item] packet_percent = ( packet_total_time / total_packet_time) * 100.0 - if packet_percent >= 10.0: - print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) - else: - print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) - + packet_count = packet_counts[item] + print " %24s %11.6f %5.2f%% %6d %9.6f" % ( + item, packet_total_time, packet_percent, packet_count, + float(packet_total_time) / float(packet_count)) + if options.plot: + plot_latencies(packet_times) if __name__ == '__main__': usage = "usage: gdbremote [options]" @@ -1491,6 +1557,12 @@ dest='verbose', help='display verbose debug info', default=False) + parser.add_option( + '--plot', + action='store_true', + dest='plot', + help='plot packet latencies by packet type', + default=False) parser.add_option( '-q', '--quiet', Index: include/lldb/Interpreter/OptionArgParser.h =================================================================== --- include/lldb/Interpreter/OptionArgParser.h +++ include/lldb/Interpreter/OptionArgParser.h @@ -24,7 +24,7 @@ static char ToChar(llvm::StringRef s, char fail_value, bool *success_ptr); static int64_t ToOptionEnum(llvm::StringRef s, - OptionEnumValueElement *enum_values, + const OptionEnumValues &enum_values, int32_t fail_value, Status &error); static lldb::ScriptLanguage ToScriptLanguage(llvm::StringRef s, Index: include/lldb/Interpreter/OptionValueEnumeration.h =================================================================== --- include/lldb/Interpreter/OptionValueEnumeration.h +++ include/lldb/Interpreter/OptionValueEnumeration.h @@ -30,8 +30,7 @@ typedef UniqueCStringMap EnumerationMap; typedef EnumerationMap::Entry EnumerationMapEntry; - OptionValueEnumeration(const OptionEnumValueElement *enumerators, - enum_type value); + OptionValueEnumeration(const OptionEnumValues &enumerators, enum_type value); ~OptionValueEnumeration() override; @@ -80,7 +79,7 @@ void SetDefaultValue(enum_type value) { m_default_value = value; } protected: - void SetEnumerations(const OptionEnumValueElement *enumerators); + void SetEnumerations(const OptionEnumValues &enumerators); enum_type m_current_value; enum_type m_default_value; Index: include/lldb/Interpreter/OptionValueProperties.h =================================================================== --- include/lldb/Interpreter/OptionValueProperties.h +++ include/lldb/Interpreter/OptionValueProperties.h @@ -62,7 +62,7 @@ void Apropos(llvm::StringRef keyword, std::vector &matching_properties) const; - void Initialize(const PropertyDefinition *setting_definitions); + void Initialize(const PropertyDefinitions &setting_definitions); // bool // GetQualifiedName (Stream &strm); Index: include/lldb/Interpreter/Property.h =================================================================== --- include/lldb/Interpreter/Property.h +++ include/lldb/Interpreter/Property.h @@ -28,10 +28,12 @@ bool global; // false == this setting is a global setting by default uintptr_t default_uint_value; const char *default_cstr_value; - OptionEnumValueElement *enum_values; + OptionEnumValues enum_values; const char *description; }; +using PropertyDefinitions = llvm::ArrayRef; + class Property { public: Property(const PropertyDefinition &definition); Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -377,7 +377,17 @@ const CompilerType &result_type, const CompilerType *args, unsigned num_args, bool is_variadic, - unsigned type_quals); + unsigned type_quals, + clang::CallingConv cc); + + static CompilerType CreateFunctionType(clang::ASTContext *ast, + const CompilerType &result_type, + const CompilerType *args, + unsigned num_args, bool is_variadic, + unsigned type_quals) { + return ClangASTContext::CreateFunctionType( + ast, result_type, args, num_args, is_variadic, type_quals, clang::CC_C); + } CompilerType CreateFunctionType(const CompilerType &result_type, const CompilerType *args, unsigned num_args, @@ -386,6 +396,15 @@ getASTContext(), result_type, args, num_args, is_variadic, type_quals); } + CompilerType CreateFunctionType(const CompilerType &result_type, + const CompilerType *args, unsigned num_args, + bool is_variadic, unsigned type_quals, + clang::CallingConv cc) { + return ClangASTContext::CreateFunctionType(getASTContext(), result_type, + args, num_args, is_variadic, + type_quals, cc); + } + clang::ParmVarDecl *CreateParameterDeclaration(const char *name, const CompilerType ¶m_type, int storage); Index: include/lldb/Target/Target.h =================================================================== --- include/lldb/Target/Target.h +++ include/lldb/Target/Target.h @@ -41,7 +41,7 @@ namespace lldb_private { -extern OptionEnumValueElement g_dynamic_value_types[]; +OptionEnumValues GetDynamicValueTypes(); typedef enum InlineStrategy { eInlineBreakpointsNever = 0, Index: include/lldb/Target/Thread.h =================================================================== --- include/lldb/Target/Thread.h +++ include/lldb/Target/Thread.h @@ -57,6 +57,8 @@ bool GetStepInAvoidsNoDebug() const; bool GetStepOutAvoidsNoDebug() const; + + uint64_t GetMaxBacktraceDepth() const; }; typedef std::shared_ptr ThreadPropertiesSP; Index: include/lldb/lldb-private-types.h =================================================================== --- include/lldb/lldb-private-types.h +++ include/lldb/lldb-private-types.h @@ -95,6 +95,8 @@ const char *usage; }; +using OptionEnumValues = llvm::ArrayRef; + struct OptionValidator { virtual ~OptionValidator() {} virtual bool IsValid(Platform &platform, @@ -112,9 +114,8 @@ int short_option; // Single character for this option. int option_has_arg; // no_argument, required_argument or optional_argument OptionValidator *validator; // If non-NULL, option is valid iff - // |validator->IsValid()|, otherwise always - // valid. - OptionEnumValueElement *enum_values; // If non-NULL an array of enum values. + // |validator->IsValid()|, otherwise always valid. + OptionEnumValues enum_values; // If not empty, an array of enum values. uint32_t completion_type; // Cookie the option class can use to do define the // argument completion. lldb::CommandArgumentType argument_type; // Type of argument this option takes Index: lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp =================================================================== --- /dev/null +++ lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp @@ -0,0 +1,20 @@ +int FuncCCall() { return 0; } +auto FuncCCallPtr = &FuncCCall; + +int __stdcall FuncStdCall() { return 0; } +auto FuncStdCallPtr = &FuncStdCall; + +int __fastcall FuncFastCall() { return 0; } +auto FuncFastCallPtr = &FuncFastCall; + +int __vectorcall FuncVectorCall() { return 0; } +auto FuncVectorCallPtr = &FuncVectorCall; + +struct S { + int FuncThisCall() { return 0; } +}; +auto FuncThisCallPtr = &S::FuncThisCall; + +int main() { + return 0; +} Index: lit/SymbolFile/PDB/calling-conventions.test =================================================================== --- /dev/null +++ lit/SymbolFile/PDB/calling-conventions.test @@ -0,0 +1,11 @@ +REQUIRES: windows, lld +RUN: clang-cl -m32 /Zi /GS- /c %S/Inputs/CallingConventionsTest.cpp /o %t.obj +RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe +RUN: lldb-test symbols -dump-ast %t.exe | FileCheck %s + +CHECK: Module: {{.*}} +CHECK-DAG: int (*FuncCCallPtr)(); +CHECK-DAG: int (*FuncStdCallPtr)() __attribute__((stdcall)); +CHECK-DAG: int (*FuncFastCallPtr)() __attribute__((fastcall)); +CHECK-DAG: int (*FuncVectorCallPtr)() __attribute__((vectorcall)); +CHECK-DAG: int (S::*FuncThisCallPtr)() __attribute__((thiscall)); Index: lit/SymbolFile/PDB/pointers.test =================================================================== --- lit/SymbolFile/PDB/pointers.test +++ lit/SymbolFile/PDB/pointers.test @@ -28,7 +28,7 @@ MAIN: Variable{{.*}}, name = "p_member_field" MAIN-SAME: (int ST::*), scope = local MAIN: Variable{{.*}}, name = "p_member_method" -MAIN-SAME: (int (ST::*)(int)), scope = local +MAIN-SAME: (int (ST::*)(int) __attribute__((thiscall))), scope = local F: Function{[[FID2:.*]]}, demangled = {{.*}}f(int) F-NEXT: Block{[[FID2]]} Index: lit/tools/lldb-mi/target/inputs/target-select-so-path.py =================================================================== --- lit/tools/lldb-mi/target/inputs/target-select-so-path.py +++ lit/tools/lldb-mi/target/inputs/target-select-so-path.py @@ -1,13 +1,16 @@ -#!/usr/bin/env python2 - import os import sys import subprocess +from threading import Timer hostname = 'localhost' (r, w) = os.pipe() +kwargs = {} +if sys.version_info >= (3,2): + kwargs['pass_fds'] = [w] + args = sys.argv # Get debugserver, lldb-mi and FileCheck executables' paths with arguments. debugserver = ' '.join([args[1], '--pipe', str(w), hostname + ':0']) @@ -16,24 +19,32 @@ filecheck = 'FileCheck ' + test_file # Run debugserver, lldb-mi and FileCheck. -debugserver_proc = subprocess.Popen(debugserver.split()) +debugserver_proc = subprocess.Popen(debugserver.split(), **kwargs) lldbmi_proc = subprocess.Popen(lldbmi, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) -filecheck_proc = subprocess.Popen(filecheck, stdin=lldbmi_proc.stdout, +filecheck_proc = subprocess.Popen(filecheck, stdin=subprocess.PIPE, shell=True) -# Get a tcp port chosen by debugserver. -# The number quite big to get lldb-server's output and to not hang. -bytes_to_read = 10 -port_bytes = os.read(r, bytes_to_read) -port = str(port_bytes.decode('utf-8').strip('\x00')) - -with open(test_file, 'r') as f: - # Replace '$PORT' with a free port number and pass - # test's content to lldb-mi. - lldbmi_proc.stdin.write(f.read().replace('$PORT', port)) - lldbmi_proc.wait() - filecheck_proc.wait() +timeout_sec = 30 +timer = Timer(timeout_sec, exit, [filecheck_proc.returncode]) +try: + timer.start() + + # Get a tcp port chosen by debugserver. + # The number quite big to get lldb-server's output and to not hang. + bytes_to_read = 10 + port_bytes = os.read(r, bytes_to_read) + port = str(port_bytes.decode('utf-8').strip('\x00')) + + with open(test_file, 'r') as f: + # Replace '$PORT' with a free port number and pass + # test's content to lldb-mi. + lldbmi_proc.stdin.write(f.read().replace('$PORT', port).encode('utf-8')) + out, err = lldbmi_proc.communicate() + filecheck_proc.stdin.write(out) + filecheck_proc.communicate() +finally: + timer.cancel() debugserver_proc.kill() exit(filecheck_proc.returncode) Index: lit/tools/lldb-mi/target/target-select-so-path.test =================================================================== --- lit/tools/lldb-mi/target/target-select-so-path.test +++ lit/tools/lldb-mi/target/target-select-so-path.test @@ -1,7 +1,7 @@ # UNSUPPORTED: windows, darwin # # RUN: %cc -o %t %p/inputs/main.c -g -# RUN: python %p/inputs/target-select-so-path.py "%debugserver" "%lldbmi %t" %s +# RUN: %python %p/inputs/target-select-so-path.py "%debugserver" "%lldbmi %t" %s # Test that -target-select command can hook up a path # added by gdb-set solib-search-path. Index: packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py +++ packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py @@ -30,12 +30,14 @@ self.expect( "image list", msg, matching=should_match, substrs=['[ 1]']) + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files def test_dependents_implicit_default_exe(self): """Test default behavior""" exe = self.getBuildArtifact("a.out") self.runCmd("target create " + exe, CURRENT_EXECUTABLE_SET) self.has_exactly_one_image(False) + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files def test_dependents_explicit_default_exe(self): """Test default behavior""" exe = self.getBuildArtifact("a.out") @@ -48,6 +50,7 @@ self.runCmd("target create -dtrue " + exe, CURRENT_EXECUTABLE_SET) self.has_exactly_one_image(True) + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files def test_dependents_explicit_false_exe(self): """Test default behavior""" exe = self.getBuildArtifact("a.out") @@ -81,6 +84,7 @@ self.runCmd("target create -dtrue " + lib, CURRENT_EXECUTABLE_SET) self.has_exactly_one_image(True) + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files def test_dependents_explicit_false_lib(self): ctx = self.platformContext dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension Index: packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +CXXFLAGS += -std=c++11 +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py @@ -0,0 +1,31 @@ +""" +Test that the target.process.thread.max-backtrace-depth setting works. +""" + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BacktraceLimitSettingTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def test_backtrace_depth(self): + """Test that the max-backtrace-depth setting limits backtraces.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("settings set target.process.thread.max-backtrace-depth 30", result) + self.assertEqual(True, result.Succeeded()) + self.assertEqual(30, thread.GetNumFrames()) Index: packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp @@ -0,0 +1,13 @@ +int bottom () { + return 1; // Set a breakpoint here +} +int foo(int in) { + if (in > 0) + return foo(--in) + 5; + else + return bottom(); +} +int main() +{ + return foo(500); +} Index: packages/Python/lldbsuite/test/lldbinline.py =================================================================== --- packages/Python/lldbsuite/test/lldbinline.py +++ packages/Python/lldbsuite/test/lldbinline.py @@ -195,7 +195,6 @@ # Derive the test name from the current file name file_basename = os.path.basename(__file) - InlineTest.mydir = TestBase.compute_mydir(__file) test_name, _ = os.path.splitext(file_basename) @@ -209,4 +208,5 @@ # Keep track of the original test filename so we report it # correctly in test results. test_class.test_filename = __file + test_class.mydir = TestBase.compute_mydir(__file) return test_class Index: scripts/Python/python-typemaps.swig =================================================================== --- scripts/Python/python-typemaps.swig +++ scripts/Python/python-typemaps.swig @@ -139,30 +139,9 @@ // typemap for an outgoing buffer // See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len). -%typemap(in) (const char *cstr, uint32_t cstr_len) { - using namespace lldb_private; - if (PythonString::Check($input)) { - PythonString str(PyRefType::Borrowed, $input); - $1 = (char*)str.GetString().data(); - $2 = str.GetSize(); - } - else if(PythonByteArray::Check($input)) { - PythonByteArray bytearray(PyRefType::Borrowed, $input); - $1 = (char*)bytearray.GetBytes().data(); - $2 = bytearray.GetSize(); - } - else if (PythonBytes::Check($input)) { - PythonBytes bytes(PyRefType::Borrowed, $input); - $1 = (char*)bytes.GetBytes().data(); - $2 = bytes.GetSize(); - } - else { - PyErr_SetString(PyExc_ValueError, "Expecting a string"); - return NULL; - } -} // Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len). -%typemap(in) (const char *src, size_t src_len) { +%typemap(in) (const char *cstr, uint32_t cstr_len), + (const char *src, size_t src_len) { using namespace lldb_private; if (PythonString::Check($input)) { PythonString str(PyRefType::Borrowed, $input); @@ -184,32 +163,9 @@ return NULL; } } -// And SBProcess::WriteMemory. -%typemap(in) (const void *buf, size_t size) { - using namespace lldb_private; - if (PythonString::Check($input)) { - PythonString str(PyRefType::Borrowed, $input); - $1 = (void*)str.GetString().data(); - $2 = str.GetSize(); - } - else if(PythonByteArray::Check($input)) { - PythonByteArray bytearray(PyRefType::Borrowed, $input); - $1 = (void*)bytearray.GetBytes().data(); - $2 = bytearray.GetSize(); - } - else if (PythonBytes::Check($input)) { - PythonBytes bytes(PyRefType::Borrowed, $input); - $1 = (void*)bytes.GetBytes().data(); - $2 = bytes.GetSize(); - } - else { - PyErr_SetString(PyExc_ValueError, "Expecting a buffer"); - return NULL; - } -} - -// For SBDebugger::DispatchInput -%typemap(in) (const void *data, size_t data_len) { +// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput. +%typemap(in) (const void *buf, size_t size), + (const void *data, size_t data_len) { using namespace lldb_private; if (PythonString::Check($input)) { PythonString str(PyRefType::Borrowed, $input); @@ -264,142 +220,70 @@ free($1); } -// these typemaps allow Python users to pass list objects -// and have them turn into C++ arrays (this is useful, for instance -// when creating SBData objects from lists of numbers) -%typemap(in) (uint64_t* array, size_t array_len) { - /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $2 = size; - $1 = (uint64_t*) malloc(size * sizeof(uint64_t)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyInt_Check(o)) { - $1[i] = PyInt_AsLong(o); - } - else if (PyLong_Check(o)) { - $1[i] = PyLong_AsUnsignedLongLong(o); - } - else { - PyErr_SetString(PyExc_TypeError,"list must contain numbers"); - free($1); - return NULL; - } - - if (PyErr_Occurred()) { - free($1); - return NULL; - } - } - } else if ($input == Py_None) { - $1 = NULL; - $2 = 0; - } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } +%{ +namespace { +template +T PyLongAsT(PyObject *obj) { + static_assert(true, "unsupported type"); } -%typemap(freearg) (uint64_t* array, size_t array_len) { - free($1); +template <> uint64_t PyLongAsT(PyObject *obj) { + return static_cast(PyLong_AsUnsignedLongLong(obj)); } -%typemap(in) (uint32_t* array, size_t array_len) { - /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $2 = size; - $1 = (uint32_t*) malloc(size * sizeof(uint32_t)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyInt_Check(o)) { - $1[i] = PyInt_AsLong(o); - } - else if (PyLong_Check(o)) { - $1[i] = PyLong_AsUnsignedLong(o); - } - else { - PyErr_SetString(PyExc_TypeError,"list must contain numbers"); - free($1); - return NULL; - } +template <> uint32_t PyLongAsT(PyObject *obj) { + return static_cast(PyLong_AsUnsignedLong(obj)); +} - if (PyErr_Occurred()) { - free($1); - return NULL; - } - } - } else if ($input == Py_None) { - $1 = NULL; - $2 = 0; - } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } +template <> int64_t PyLongAsT(PyObject *obj) { + return static_cast(PyLong_AsLongLong(obj)); } -%typemap(freearg) (uint32_t* array, size_t array_len) { - free($1); +template <> int32_t PyLongAsT(PyObject *obj) { + return static_cast(PyLong_AsLong(obj)); } -%typemap(in) (int64_t* array, size_t array_len) { - /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $2 = size; - $1 = (int64_t*) malloc(size * sizeof(int64_t)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyInt_Check(o)) { - $1[i] = PyInt_AsLong(o); - } - else if (PyLong_Check(o)) { - $1[i] = PyLong_AsLongLong(o); - } - else { - PyErr_SetString(PyExc_TypeError,"list must contain numbers"); - free($1); - return NULL; - } +template +bool SetNumberFromPyObject(T &number, PyObject *obj) { + if (PyInt_Check(obj)) + number = static_cast(PyInt_AsLong(obj)); + else if (PyLong_Check(obj)) + number = PyLongAsT(obj); + else return false; - if (PyErr_Occurred()) { - free($1); - return NULL; - } - } - } else if ($input == Py_None) { - $1 = NULL; - $2 = 0; - } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } + return true; } -%typemap(freearg) (int64_t* array, size_t array_len) { - free($1); +template <> +bool SetNumberFromPyObject(double &number, PyObject *obj) { + if (PyFloat_Check(obj)) { + number = PyFloat_AsDouble(obj); + return true; + } + + return false; } -%typemap(in) (int32_t* array, size_t array_len) { +} // namespace +%} + +// these typemaps allow Python users to pass list objects +// and have them turn into C++ arrays (this is useful, for instance +// when creating SBData objects from lists of numbers) +%typemap(in) (uint64_t* array, size_t array_len), + (uint32_t* array, size_t array_len), + (int64_t* array, size_t array_len), + (int32_t* array, size_t array_len), + (double* array, size_t array_len) { /* Check if is a list */ if (PyList_Check($input)) { int size = PyList_Size($input); int i = 0; $2 = size; - $1 = (int32_t*) malloc(size * sizeof(int32_t)); + $1 = ($1_type) malloc(size * sizeof($*1_type)); for (i = 0; i < size; i++) { PyObject *o = PyList_GetItem($input,i); - if (PyInt_Check(o)) { - $1[i] = PyInt_AsLong(o); - } - else if (PyLong_Check(o)) { - $1[i] = PyLong_AsLong(o); - } - else { + if (!SetNumberFromPyObject($1[i], o)) { PyErr_SetString(PyExc_TypeError,"list must contain numbers"); free($1); return NULL; @@ -419,38 +303,11 @@ } } -%typemap(freearg) (int32_t* array, size_t array_len) { - free($1); -} - -%typemap(in) (double* array, size_t array_len) { - /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $2 = size; - $1 = (double*) malloc(size * sizeof(double)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyFloat_Check(o)) { - $1[i] = PyFloat_AsDouble(o); - } - else { - PyErr_SetString(PyExc_TypeError,"list must contain floating-point numbers"); - free($1); - return NULL; - } - } - } else if ($input == Py_None) { - $1 = NULL; - $2 = 0; - } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } -} - -%typemap(freearg) (double* array, size_t array_len) { +%typemap(freearg) (uint64_t* array, size_t array_len), + (uint32_t* array, size_t array_len), + (int64_t* array, size_t array_len), + (int32_t* array, size_t array_len), + (double* array, size_t array_len) { free($1); } Index: source/Breakpoint/Breakpoint.cpp =================================================================== --- source/Breakpoint/Breakpoint.cpp +++ source/Breakpoint/Breakpoint.cpp @@ -785,8 +785,8 @@ // we go. if (old_id_vec.size() == new_id_vec.size()) { - llvm::sort(old_id_vec.begin(), old_id_vec.end()); - llvm::sort(new_id_vec.begin(), new_id_vec.end()); + llvm::sort(old_id_vec); + llvm::sort(new_id_vec); size_t num_elements = old_id_vec.size(); for (size_t idx = 0; idx < num_elements; idx++) { BreakpointLocationSP old_loc_sp = Index: source/Commands/CommandObjectBreakpoint.cpp =================================================================== --- source/Commands/CommandObjectBreakpoint.cpp +++ source/Commands/CommandObjectBreakpoint.cpp @@ -50,19 +50,19 @@ // Modifiable Breakpoint Options //------------------------------------------------------------------------- #pragma mark Modify::CommandOptions -static OptionDefinition g_breakpoint_modify_options[] = { +static constexpr OptionDefinition g_breakpoint_modify_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, - { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, - { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, - { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, - { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, - { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, + { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, + { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, + { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, + { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, + { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, + { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, + { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, + { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, + { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." }, + { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." }, + { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, // clang-format on }; class lldb_private::BreakpointOptionGroup : public OptionGroup @@ -198,9 +198,9 @@ BreakpointOptions m_bp_opts; }; -static OptionDefinition g_breakpoint_dummy_options[] = { +static constexpr OptionDefinition g_breakpoint_dummy_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " "which prime new targets." }, // clang-format on }; @@ -252,16 +252,16 @@ #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) -static OptionDefinition g_breakpoint_set_options[] = { +static constexpr OptionDefinition g_breakpoint_set_options[] = { // clang-format off - { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " + { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " "multiple times to specify multiple shared libraries." }, - { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, - { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " + { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, + { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " "lldb only looks for files that are #included if they use the standard include " "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " "#included, set target.inline-breakpoint-strategy to \"always\"." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, // Comment out this option for the moment, as we don't actually use it, but // will in the future. This way users won't see it, but the infrastructure is @@ -269,7 +269,7 @@ // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "", // "Set the breakpoint by source location at this particular column."}, - { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " + { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " "a particular binary, then the address will be converted to a \"file\" " "address, so that the breakpoint will track that binary+offset no matter where " "the binary eventually loads. Alternately, if you also specify the module - " @@ -278,50 +278,50 @@ "that offset on subsequent reloads. The module need not have been loaded at " "the time you specify this breakpoint, and will get resolved when the module " "is loaded." }, - { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " + { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " "one breakpoint for multiple names" }, - { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " + { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " "functions. Can be repeated multiple times." }, - { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " + { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " "namespaces and all arguments, and for Objective-C this means a full function " "prototype with class and selector. Can be repeated multiple times to make " "one breakpoint for multiple names." }, - { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " + { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " "make one breakpoint for multiple Selectors." }, - { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " + { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " "make one breakpoint for multiple methods." }, - { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " + { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " "the function name(s)." }, - { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " + { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " "ignored). Can be repeated multiple times to make one breakpoint for multiple " "symbols." }, - { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " + { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " "against the source text in a source file or files specified with the -f " "option. The -f option can be specified more than once. If no source files " "are specified, uses the current \"default source file\". If you want to " "match against all source files, pass the \"--all-files\" option." }, - { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." }, - { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, - { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " + { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." }, + { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, + { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, + { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, + { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " "options, on throw but not catch.)" }, - { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, - { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, + { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, + { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, // Don't add this option till it actually does something useful... // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, - { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " + { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " "(note: currently only implemented for setting breakpoints on identifiers). " "If not set the target.language setting is used." }, - { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " + { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " "If not set the target.skip-prologue setting is used." }, - { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, - { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " + { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, + { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, - { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " + { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " "setting is used." }, // clang-format on }; @@ -1261,15 +1261,15 @@ //------------------------------------------------------------------------- #pragma mark List::CommandOptions -static OptionDefinition g_breakpoint_list_options[] = { +static constexpr OptionDefinition g_breakpoint_list_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, - { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, + { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" }, + { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, // FIXME: We need to add an "internal" command, and then add this sort of thing to it. // But I need to see it for now, and don't want to wait. - { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, - { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, + { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, + { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, // clang-format on }; @@ -1427,10 +1427,10 @@ //------------------------------------------------------------------------- #pragma mark Clear::CommandOptions -static OptionDefinition g_breakpoint_clear_options[] = { +static constexpr OptionDefinition g_breakpoint_clear_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } // clang-format on }; @@ -1585,10 +1585,10 @@ //------------------------------------------------------------------------- // CommandObjectBreakpointDelete //------------------------------------------------------------------------- -static OptionDefinition g_breakpoint_delete_options[] = { +static constexpr OptionDefinition g_breakpoint_delete_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, + { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, // clang-format on }; @@ -1742,12 +1742,12 @@ // CommandObjectBreakpointName //------------------------------------------------------------------------- -static OptionDefinition g_breakpoint_name_options[] = { +static constexpr OptionDefinition g_breakpoint_name_options[] = { // clang-format off - {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, - {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, - {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, - {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."}, + {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, + {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, + {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."}, // clang-format on }; class BreakpointNameOptionGroup : public OptionGroup { @@ -1811,23 +1811,20 @@ OptionValueString m_help_string; }; -static OptionDefinition g_breakpoint_access_options[] = { +static constexpr OptionDefinition g_breakpoint_access_options[] = { // clang-format off - {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, - {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, - {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, + {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, + {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, + {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, // clang-format on }; -class BreakpointAccessOptionGroup : public OptionGroup -{ +class BreakpointAccessOptionGroup : public OptionGroup { public: - BreakpointAccessOptionGroup() : - OptionGroup() - {} - + BreakpointAccessOptionGroup() : OptionGroup() {} + ~BreakpointAccessOptionGroup() override = default; - + llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_breakpoint_access_options); } @@ -2283,10 +2280,10 @@ // CommandObjectBreakpointRead //------------------------------------------------------------------------- #pragma mark Read::CommandOptions -static OptionDefinition g_breakpoint_read_options[] = { +static constexpr OptionDefinition g_breakpoint_read_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, - {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, + {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, + {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, // clang-format on }; @@ -2413,10 +2410,10 @@ // CommandObjectBreakpointWrite //------------------------------------------------------------------------- #pragma mark Write::CommandOptions -static OptionDefinition g_breakpoint_write_options[] = { +static constexpr OptionDefinition g_breakpoint_write_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, - { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, + { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, + { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, // clang-format on }; Index: source/Commands/CommandObjectBreakpointCommand.cpp =================================================================== --- source/Commands/CommandObjectBreakpointCommand.cpp +++ source/Commands/CommandObjectBreakpointCommand.cpp @@ -40,21 +40,24 @@ // language to lldb and have it pickable here without having to change this // enumeration by hand and rebuild lldb proper. -static OptionEnumValueElement g_script_option_enumeration[4] = { +static constexpr OptionEnumValueElement g_script_option_enumeration[] = { {eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, {eScriptLanguagePython, "python", "Commands are in the Python language."}, {eSortOrderByName, "default-script", - "Commands are in the default scripting language."}, - {0, nullptr, nullptr}}; + "Commands are in the default scripting language."} }; -static OptionDefinition g_breakpoint_add_options[] = { +static constexpr OptionEnumValues ScriptOptionEnum() { + return OptionEnumValues(g_script_option_enumeration); +} + +static constexpr OptionDefinition g_breakpoint_add_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, - { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, - { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, + { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, + { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, + { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, + { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." }, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, // clang-format on }; @@ -475,9 +478,9 @@ // CommandObjectBreakpointCommandDelete //------------------------------------------------------------------------- -static OptionDefinition g_breakpoint_delete_options[] = { +static constexpr OptionDefinition g_breakpoint_delete_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, // clang-format on }; Index: source/Commands/CommandObjectCommands.cpp =================================================================== --- source/Commands/CommandObjectCommands.cpp +++ source/Commands/CommandObjectCommands.cpp @@ -38,12 +38,12 @@ // CommandObjectCommandsSource //------------------------------------------------------------------------- -static OptionDefinition g_history_options[] = { +static constexpr OptionDefinition g_history_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, - { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, - { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, - { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." }, + { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, + { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, + { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, + { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." }, // clang-format on }; @@ -197,11 +197,11 @@ // CommandObjectCommandsSource //------------------------------------------------------------------------- -static OptionDefinition g_source_options[] = { +static constexpr OptionDefinition g_source_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, - { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, - { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, + { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, + { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, + { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, // clang-format on }; @@ -340,10 +340,10 @@ // CommandObjectCommandsAlias //------------------------------------------------------------------------- -static OptionDefinition g_alias_options[] = { +static constexpr OptionDefinition g_alias_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" }, - { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" }, + { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" }, + { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" }, // clang-format on }; @@ -914,10 +914,10 @@ // CommandObjectCommandsAddRegex //------------------------------------------------------------------------- -static OptionDefinition g_regex_options[] = { +static constexpr OptionDefinition g_regex_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." }, - { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, + { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." }, + { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, // clang-format on }; @@ -1394,9 +1394,9 @@ // CommandObjectCommandsScriptImport //------------------------------------------------------------------------- -OptionDefinition g_script_import_options[] = { +static constexpr OptionDefinition g_script_import_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." }, + { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." }, // clang-format on }; @@ -1519,22 +1519,24 @@ //------------------------------------------------------------------------- // CommandObjectCommandsScriptAdd //------------------------------------------------------------------------- +static constexpr OptionEnumValueElement g_script_synchro_type[] = { + {eScriptedCommandSynchronicitySynchronous, "synchronous", + "Run synchronous"}, + {eScriptedCommandSynchronicityAsynchronous, "asynchronous", + "Run asynchronous"}, + {eScriptedCommandSynchronicityCurrentValue, "current", + "Do not alter current setting"} }; + +static constexpr OptionEnumValues ScriptSynchroType() { + return OptionEnumValues(g_script_synchro_type); +} -static OptionEnumValueElement g_script_synchro_type[] = { - {eScriptedCommandSynchronicitySynchronous, "synchronous", - "Run synchronous"}, - {eScriptedCommandSynchronicityAsynchronous, "asynchronous", - "Run asynchronous"}, - {eScriptedCommandSynchronicityCurrentValue, "current", - "Do not alter current setting"}, - {0, nullptr, nullptr}}; - -static OptionDefinition g_script_add_options[] = { +static constexpr OptionDefinition g_script_add_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, - { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." }, - { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, + { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, + { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, + { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." }, + { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, // clang-format on }; Index: source/Commands/CommandObjectDisassemble.cpp =================================================================== --- source/Commands/CommandObjectDisassemble.cpp +++ source/Commands/CommandObjectDisassemble.cpp @@ -35,30 +35,30 @@ using namespace lldb; using namespace lldb_private; -static OptionDefinition g_disassemble_options[] = { +static constexpr OptionDefinition g_disassemble_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling." }, - { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show." }, - { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display." }, - { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." }, - { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " + { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show opcode bytes when disassembling." }, + { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of context lines of source to show." }, + { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable mixed source and assembly display." }, + { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print raw disassembly with no symbol information." }, + { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." }, + { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " "Currently the only valid options are default, and for Intel " "architectures, att and intel." }, - { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." }, + { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." }, { LLDB_OPT_SET_1 | - LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." }, - { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." }, + LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." }, + { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." }, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | - LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." }, - { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." }, - { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc." }, - { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line " + LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of instructions to display." }, + { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." }, + { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." }, + { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble around the current pc." }, + { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line " "table information, else disassemble around the pc." }, - { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." }, + { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." }, // clang-format on }; Index: source/Commands/CommandObjectExpression.cpp =================================================================== --- source/Commands/CommandObjectExpression.cpp +++ source/Commands/CommandObjectExpression.cpp @@ -43,29 +43,32 @@ CommandObjectExpression::CommandOptions::~CommandOptions() = default; -static OptionEnumValueElement g_description_verbosity_type[] = { +static constexpr OptionEnumValueElement g_description_verbosity_type[] = { {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", - "Show the full output, including persistent variable's name and type"}, - {0, nullptr, nullptr}}; + "Show the full output, including persistent variable's name and type"} }; -static OptionDefinition g_expression_options[] = { +static constexpr OptionEnumValues DescriptionVerbosityTypes() { + return OptionEnumValues(g_description_verbosity_type); +} + +static constexpr OptionDefinition g_expression_options[] = { // clang-format off - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " "setting is used." }, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, - {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, + {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " "context. Allows declaration of persistent, top-level entities without a $ prefix."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " "the interpreter (defaults to true)."} // clang-format on }; Index: source/Commands/CommandObjectFrame.cpp =================================================================== --- source/Commands/CommandObjectFrame.cpp +++ source/Commands/CommandObjectFrame.cpp @@ -61,11 +61,11 @@ // CommandObjectFrameDiagnose //------------------------------------------------------------------------- -static OptionDefinition g_frame_diag_options[] = { +static constexpr OptionDefinition g_frame_diag_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegisterName, "A register to diagnose." }, - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "An address to diagnose." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "An optional offset. Requires --register." } + { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName, "A register to diagnose." }, + { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "An address to diagnose." }, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "An optional offset. Requires --register." } // clang-format on }; @@ -251,7 +251,7 @@ static OptionDefinition g_frame_select_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." }, + { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." }, // clang-format on }; Index: source/Commands/CommandObjectHelp.cpp =================================================================== --- source/Commands/CommandObjectHelp.cpp +++ source/Commands/CommandObjectHelp.cpp @@ -71,11 +71,11 @@ CommandObjectHelp::~CommandObjectHelp() = default; -static OptionDefinition g_help_options[] = { +static constexpr OptionDefinition g_help_options[] = { // clang-format off - {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."}, - {LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."}, - {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."}, + {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Hide aliases in the command list."}, + {LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Hide user-defined commands from the list."}, + {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include commands prefixed with an underscore."}, // clang-format on }; Index: source/Commands/CommandObjectLog.cpp =================================================================== --- source/Commands/CommandObjectLog.cpp +++ source/Commands/CommandObjectLog.cpp @@ -36,18 +36,18 @@ using namespace lldb; using namespace lldb_private; -static OptionDefinition g_log_options[] = { +static constexpr OptionDefinition g_log_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Set the destination file to log to." }, - { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, - { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose logging." }, - { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, - { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, - { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, - { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, - { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, - { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, - { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." }, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Set the destination file to log to." }, + { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, + { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose logging." }, + { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, + { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, + { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, + { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, + { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, + { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, + { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." }, // clang-format on }; Index: source/Commands/CommandObjectMemory.cpp =================================================================== --- source/Commands/CommandObjectMemory.cpp +++ source/Commands/CommandObjectMemory.cpp @@ -50,16 +50,16 @@ using namespace lldb; using namespace lldb_private; -static OptionDefinition g_read_memory_options[] = { +static constexpr OptionDefinition g_read_memory_options[] = { // clang-format off - {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, - {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " + {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, + {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " "uses the format, size, count and number per line settings." }, - {LLDB_OPT_SET_3, true , "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The name of a type to view memory as." }, - {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." }, + {LLDB_OPT_SET_3, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The name of a type to view memory as." }, + {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." }, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | - LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." }, + LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." }, // clang-format on }; @@ -884,12 +884,12 @@ CompilerType m_prev_clang_ast_type; }; -OptionDefinition g_memory_find_option_table[] = { +static constexpr OptionDefinition g_memory_find_option_table[] = { // clang-format off - {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, - {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Use text to find a byte pattern."}, - {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many times to perform the search."}, - {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, + {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, + {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Use text to find a byte pattern."}, + {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many times to perform the search."}, + {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, // clang-format on }; @@ -1179,10 +1179,10 @@ OptionGroupFindMemory m_memory_options; }; -OptionDefinition g_memory_write_option_table[] = { +static constexpr OptionDefinition g_memory_write_option_table[] = { // clang-format off - {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."}, - {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, + {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Write memory using the contents of a file."}, + {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, // clang-format on }; Index: source/Commands/CommandObjectPlatform.cpp =================================================================== --- source/Commands/CommandObjectPlatform.cpp +++ source/Commands/CommandObjectPlatform.cpp @@ -63,19 +63,19 @@ return user | group | world; } -static OptionDefinition g_permissions_options[] = { +static constexpr OptionDefinition g_permissions_options[] = { // clang-format off - {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"}, - {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."}, - {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to read."}, - {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to write."}, - {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to execute."}, - {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to read."}, - {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to write."}, - {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to execute."}, - {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to read."}, - {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to write."}, - {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to execute."}, + {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"}, + {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."}, + {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to read."}, + {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to write."}, + {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to execute."}, + {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to read."}, + {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to write."}, + {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to execute."}, + {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to read."}, + {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to write."}, + {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to execute."}, // clang-format on }; @@ -614,10 +614,10 @@ // "platform fread" //---------------------------------------------------------------------- -static OptionDefinition g_platform_fread_options[] = { +static constexpr OptionDefinition g_platform_fread_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file." }, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, + { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Number of bytes to read from the file." }, // clang-format on }; @@ -709,10 +709,10 @@ // "platform fwrite" //---------------------------------------------------------------------- -static OptionDefinition g_platform_fwrite_options[] = { +static constexpr OptionDefinition g_platform_fwrite_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file." }, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, + { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Text to write to the file." }, // clang-format on }; @@ -1102,22 +1102,22 @@ // "platform process list" //---------------------------------------------------------------------- -OptionDefinition g_platform_process_list_options[] = { +static OptionDefinition g_platform_process_list_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "List the process info for a specific process ID." }, - { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." }, - { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." }, - { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." }, - { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." }, - { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "Find processes that have a matching parent process ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose output." }, + { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "List the process info for a specific process ID." }, + { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." }, + { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." }, + { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." }, + { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." }, + { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "Find processes that have a matching parent process ID." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." }, + { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." }, + { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." }, + { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose output." }, // clang-format on }; @@ -1488,12 +1488,12 @@ } }; -static OptionDefinition g_platform_process_attach_options[] = { +static constexpr OptionDefinition g_platform_process_attach_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with to launch." }, + { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, + { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, + { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, + { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with to launch." }, // clang-format on }; @@ -1673,9 +1673,9 @@ //---------------------------------------------------------------------- // "platform shell" //---------------------------------------------------------------------- -static OptionDefinition g_platform_shell_options[] = { +static constexpr OptionDefinition g_platform_shell_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." }, + { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." }, // clang-format on }; Index: source/Commands/CommandObjectProcess.cpp =================================================================== --- source/Commands/CommandObjectProcess.cpp +++ source/Commands/CommandObjectProcess.cpp @@ -304,14 +304,14 @@ // CommandObjectProcessAttach //------------------------------------------------------------------------- -static OptionDefinition g_process_attach_options[] = { +static constexpr OptionDefinition g_process_attach_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with to launch." }, + { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Immediately continue the process once attached." }, + { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, + { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, + { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, + { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, + { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with to launch." }, // clang-format on }; @@ -556,9 +556,9 @@ // CommandObjectProcessContinue //------------------------------------------------------------------------- -static OptionDefinition g_process_continue_options[] = { +static constexpr OptionDefinition g_process_continue_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Ignore crossings of the breakpoint (if it exists) for the currently selected thread." } + { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Ignore crossings of the breakpoint (if it exists) for the currently selected thread." } // clang-format on }; @@ -719,9 +719,9 @@ //------------------------------------------------------------------------- // CommandObjectProcessDetach //------------------------------------------------------------------------- -static OptionDefinition g_process_detach_options[] = { +static constexpr OptionDefinition g_process_detach_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, + { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, // clang-format on }; @@ -818,9 +818,9 @@ // CommandObjectProcessConnect //------------------------------------------------------------------------- -static OptionDefinition g_process_connect_options[] = { +static constexpr OptionDefinition g_process_connect_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, + { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, // clang-format on }; @@ -947,9 +947,9 @@ // CommandObjectProcessLoad //------------------------------------------------------------------------- -static OptionDefinition g_process_load_options[] = { +static constexpr OptionDefinition g_process_load_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." }, + { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." }, // clang-format on }; @@ -1343,11 +1343,11 @@ // CommandObjectProcessHandle //------------------------------------------------------------------------- -static OptionDefinition g_process_handle_options[] = { +static constexpr OptionDefinition g_process_handle_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, - { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, - { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." } + { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, + { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, + { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." } // clang-format on }; Index: source/Commands/CommandObjectRegister.cpp =================================================================== --- source/Commands/CommandObjectRegister.cpp +++ source/Commands/CommandObjectRegister.cpp @@ -36,11 +36,11 @@ // "register read" //---------------------------------------------------------------------- -static OptionDefinition g_register_read_options[] = { +static constexpr OptionDefinition g_register_read_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." }, - { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Specify which register sets to dump by index." }, - { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show all register sets." }, + { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." }, + { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Specify which register sets to dump by index." }, + { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show all register sets." }, // clang-format on }; Index: source/Commands/CommandObjectSettings.cpp =================================================================== --- source/Commands/CommandObjectSettings.cpp +++ source/Commands/CommandObjectSettings.cpp @@ -28,9 +28,9 @@ // CommandObjectSettingsSet //------------------------------------------------------------------------- -static OptionDefinition g_settings_set_options[] = { +static constexpr OptionDefinition g_settings_set_options[] = { // clang-format off - { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value." } + { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Apply the new value to the global default value." } // clang-format on }; Index: source/Commands/CommandObjectSource.cpp =================================================================== --- source/Commands/CommandObjectSource.cpp +++ source/Commands/CommandObjectSource.cpp @@ -41,15 +41,15 @@ // CommandObjectSourceInfo - debug line entries dumping command //---------------------------------------------------------------------- -static OptionDefinition g_source_info_options[] = { +static constexpr OptionDefinition g_source_info_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of line entries to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, + { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of line entries to display." }, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." }, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, + { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." }, + { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." }, + { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, + { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, // clang-format on }; @@ -653,16 +653,16 @@ // CommandObjectSourceList //------------------------------------------------------------------------- -static OptionDefinition g_source_list_options[] = { +static constexpr OptionDefinition g_source_list_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of source lines to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." }, - { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to start the display source." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, - { LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." }, + { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of source lines to display." }, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." }, + { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints." }, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, + { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the display source." }, + { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, + { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, + { LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." }, // clang-format on }; Index: source/Commands/CommandObjectTarget.cpp =================================================================== --- source/Commands/CommandObjectTarget.cpp +++ source/Commands/CommandObjectTarget.cpp @@ -140,19 +140,18 @@ // Note that the negation in the argument name causes a slightly confusing // mapping of the enum values, -static OptionEnumValueElement g_dependents_enumaration[4] = { +static constexpr OptionEnumValueElement g_dependents_enumaration[] = { {eLoadDependentsDefault, "default", "Only load dependents when the target is an executable."}, {eLoadDependentsNo, "true", "Don't load dependents, even if the target is an executable."}, {eLoadDependentsYes, "false", - "Load dependents, even if the target is not an executable."}, - {0, nullptr, nullptr}}; + "Load dependents, even if the target is not an executable."}}; -static OptionDefinition g_dependents_options[1] = { +static constexpr OptionDefinition g_dependents_options[] = { {LLDB_OPT_SET_1, false, "no-dependents", 'd', - OptionParser::eOptionalArgument, nullptr, g_dependents_enumaration, 0, - eArgTypeValue, + OptionParser::eOptionalArgument, nullptr, + OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue, "Whether or not to load dependents when creating a target. If the option " "is not specified, the value is implicitly 'default'. If the option is " "specified but without a value, the value is implicitly 'true'."}}; @@ -1984,16 +1983,15 @@ #pragma mark CommandObjectTargetModulesDumpSymtab -static OptionEnumValueElement g_sort_option_enumeration[4] = { +static constexpr OptionEnumValueElement g_sort_option_enumeration[] = { {eSortOrderNone, "none", "No sorting, use the original symbol table order."}, {eSortOrderByAddress, "address", "Sort output by symbol address."}, - {eSortOrderByName, "name", "Sort output by symbol name."}, - {0, nullptr, nullptr}}; + {eSortOrderByName, "name", "Sort output by symbol name."} }; -static OptionDefinition g_target_modules_dump_symtab_options[] = { +static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." } + { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(g_sort_option_enumeration), 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." } // clang-format on }; @@ -2884,23 +2882,23 @@ // List images with associated information //---------------------------------------------------------------------- -static OptionDefinition g_target_modules_list_options[] = { +static constexpr OptionDefinition g_target_modules_list_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Display the image at this address." }, - { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the architecture when listing images." }, - { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the triple when listing images." }, - { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)." }, - { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the UUID when listing images." }, - { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image object file." }, - { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." }, - { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file." }, - { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the modification time with optional width of the module." }, - { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache." }, - { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the module pointer." }, - { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." } + { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." }, + { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the architecture when listing images." }, + { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the triple when listing images." }, + { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise." }, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)." }, + { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the UUID when listing images." }, + { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image object file." }, + { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." }, + { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." }, + { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." }, + { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file." }, + { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the modification time with optional width of the module." }, + { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache." }, + { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone, "Display the module pointer." }, + { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." } // clang-format on }; @@ -3250,10 +3248,10 @@ // Lookup unwind information in images //---------------------------------------------------------------------- -static OptionDefinition g_target_modules_show_unwind_options[] = { +static constexpr OptionDefinition g_target_modules_show_unwind_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." }, - { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" } + { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." }, + { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" } // clang-format on }; @@ -3556,21 +3554,21 @@ // Lookup information in images //---------------------------------------------------------------------- -static OptionDefinition g_target_modules_lookup_options[] = { +static constexpr OptionDefinition g_target_modules_lookup_options[] = { // clang-format off - { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When looking up an address subtract from any addresses before doing the lookup." }, + { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." }, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When looking up an address subtract from any addresses before doing the lookup." }, /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ - { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The argument for name lookups are regular expressions." }, - { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules." }, - { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." }, - { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." }, - { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." }, - { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." }, - { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose lookup information." }, - { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." }, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "The argument for name lookups are regular expressions." }, + { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules." }, + { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." }, + { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." }, + { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." }, + { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules." }, + { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." }, + { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules." }, + { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose lookup information." }, + { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." }, // clang-format on }; @@ -4436,19 +4434,19 @@ // CommandObjectTargetStopHookAdd //------------------------------------------------------------------------- -static OptionDefinition g_target_stop_hook_add_options[] = { +static constexpr OptionDefinition g_target_stop_hook_add_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." }, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." }, + { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, + { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." }, + { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." }, + { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." }, + { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." }, + { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." }, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." }, + { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." }, + { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." }, + { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." }, + { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." }, // clang-format on }; Index: source/Commands/CommandObjectThread.cpp =================================================================== --- source/Commands/CommandObjectThread.cpp +++ source/Commands/CommandObjectThread.cpp @@ -247,11 +247,11 @@ // CommandObjectThreadBacktrace //------------------------------------------------------------------------- -static OptionDefinition g_thread_backtrace_options[] = { +static constexpr OptionDefinition g_thread_backtrace_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many frames to display (-1 for all)" }, - { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" }, - { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the extended backtrace, if available" } + { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many frames to display (-1 for all)" }, + { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" }, + { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Show the extended backtrace, if available" } // clang-format on }; @@ -402,28 +402,26 @@ enum StepScope { eStepScopeSource, eStepScopeInstruction }; -static OptionEnumValueElement g_tri_running_mode[] = { +static constexpr OptionEnumValueElement g_tri_running_mode[] = { {eOnlyThisThread, "this-thread", "Run only this thread"}, {eAllThreads, "all-threads", "Run all threads"}, {eOnlyDuringStepping, "while-stepping", - "Run only this thread while stepping"}, - {0, nullptr, nullptr}}; + "Run only this thread while stepping"} }; -static OptionEnumValueElement g_duo_running_mode[] = { - {eOnlyThisThread, "this-thread", "Run only this thread"}, - {eAllThreads, "all-threads", "Run all threads"}, - {0, nullptr, nullptr}}; +static constexpr OptionEnumValues TriRunningModes() { + return OptionEnumValues(g_tri_running_mode); +} -static OptionDefinition g_thread_step_scope_options[] = { +static constexpr OptionDefinition g_thread_step_scope_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information." }, - { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information." }, - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." }, - { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over. You can also pass the string 'block' to step to the end of the current block. This is particularly useful in conjunction with --step-target to step through a complex calling sequence." }, - { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread." }, - { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in." }, - { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into." }, - { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step." } + { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information." }, + { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information." }, + { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." }, + { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, {}, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over. You can also pass the string 'block' to step to the end of the current block. This is particularly useful in conjunction with --step-target to step through a complex calling sequence." }, + { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, TriRunningModes(), 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread." }, + { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in." }, + { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into." }, + { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step." } // clang-format on }; @@ -483,8 +481,7 @@ break; case 'm': { - OptionEnumValueElement *enum_values = - GetDefinitions()[option_idx].enum_values; + auto enum_values = GetDefinitions()[option_idx].enum_values; m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( option_arg, enum_values, eOnlyDuringStepping, error); } break; @@ -997,12 +994,20 @@ // CommandObjectThreadUntil //------------------------------------------------------------------------- -static OptionDefinition g_thread_until_options[] = { +static constexpr OptionEnumValueElement g_duo_running_mode[] = { + {eOnlyThisThread, "this-thread", "Run only this thread"}, + {eAllThreads, "all-threads", "Run all threads"} }; + +static constexpr OptionEnumValues DuoRunningModes() { + return OptionEnumValues(g_duo_running_mode); +} + +static constexpr OptionDefinition g_thread_until_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0" }, - { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation" }, - { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one" }, - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." } + { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0" }, + { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation" }, + { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, DuoRunningModes(), 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one" }, + { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." } // clang-format on }; @@ -1050,8 +1055,7 @@ } break; case 'm': { - OptionEnumValueElement *enum_values = - GetDefinitions()[option_idx].enum_values; + auto enum_values = GetDefinitions()[option_idx].enum_values; lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( option_arg, enum_values, eOnlyDuringStepping, error); @@ -1419,10 +1423,10 @@ // CommandObjectThreadInfo //------------------------------------------------------------------------- -static OptionDefinition g_thread_info_options[] = { +static constexpr OptionDefinition g_thread_info_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the thread info in JSON format." }, - { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the extended stop info in JSON format." } + { LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the thread info in JSON format." }, + { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the extended stop info in JSON format." } // clang-format on }; @@ -1514,9 +1518,9 @@ // CommandObjectThreadReturn //------------------------------------------------------------------------- -static OptionDefinition g_thread_return_options[] = { +static constexpr OptionDefinition g_thread_return_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Return from the innermost expression evaluation." } + { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Return from the innermost expression evaluation." } // clang-format on }; @@ -1692,13 +1696,13 @@ // CommandObjectThreadJump //------------------------------------------------------------------------- -static OptionDefinition g_thread_jump_options[] = { +static constexpr OptionDefinition g_thread_jump_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number to jump to." }, - { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line." }, - { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Jumps to a specific address." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allows the PC to leave the current function." } + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to." }, + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number to jump to." }, + { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line." }, + { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Jumps to a specific address." }, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allows the PC to leave the current function." } // clang-format on }; @@ -1844,10 +1848,10 @@ // CommandObjectThreadPlanList //------------------------------------------------------------------------- -static OptionDefinition g_thread_plan_list_options[] = { +static constexpr OptionDefinition g_thread_plan_list_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display more information about the thread plans" }, - { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display internal as well as user thread plans" } + { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display more information about the thread plans" }, + { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display internal as well as user thread plans" } // clang-format on }; Index: source/Commands/CommandObjectType.cpp =================================================================== --- source/Commands/CommandObjectType.cpp +++ source/Commands/CommandObjectType.cpp @@ -99,23 +99,23 @@ return false; } -static OptionDefinition g_type_summary_add_options[] = { +static constexpr OptionDefinition g_type_summary_add_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." }, - { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, - { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." }, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }, - { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string." }, - { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display." }, - { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." }, - { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." }, - { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." }, - { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually." }, - { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." }, - { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not expand aggregate data types with no children." }, - { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string." } + { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." }, + { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, + { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." }, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }, + { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, inline all child values into summary string." }, + { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, omit value names in the summary display." }, + { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." }, + { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." }, + { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." }, + { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Input Python code to use for this type manually." }, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." }, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Do not expand aggregate data types with no children." }, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "A name for this summary string." } // clang-format on }; @@ -301,15 +301,15 @@ " '''Optional'''\n" "class synthProvider:\n"; -static OptionDefinition g_type_synth_add_options[] = { +static constexpr OptionDefinition g_type_synth_add_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." }, - { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." }, - { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." } + { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." }, + { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." }, + { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." }, + { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." } // clang-format on }; @@ -531,14 +531,14 @@ // CommandObjectTypeFormatAdd //------------------------------------------------------------------------- -static OptionDefinition g_type_format_add_options[] = { +static constexpr OptionDefinition g_type_format_add_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." }, - { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }, - { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type." } + { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." }, + { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }, + { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Format variables as if they were of this type." } // clang-format on }; @@ -754,11 +754,11 @@ } }; -static OptionDefinition g_type_formatter_delete_options[] = { +static constexpr OptionDefinition g_type_formatter_delete_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category." }, - { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category." }, - { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category." } + { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete from every category." }, + { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Delete from given category." }, + { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Delete from given language's category." } // clang-format on }; @@ -896,9 +896,9 @@ } }; -static OptionDefinition g_type_formatter_clear_options[] = { +static constexpr OptionDefinition g_type_formatter_clear_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category." } + { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Clear every category." } // clang-format on }; @@ -1055,10 +1055,10 @@ } llvm::ArrayRef GetDefinitions() override { - static OptionDefinition g_option_table[] = { + static constexpr OptionDefinition g_option_table[] = { // clang-format off - {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."}, - {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."} + {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Only show categories matching this filter."}, + {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Only show the category for a specific language."} // clang-format on }; return llvm::ArrayRef(g_option_table); @@ -1784,10 +1784,10 @@ // CommandObjectTypeCategoryDefine //------------------------------------------------------------------------- -static OptionDefinition g_type_category_define_options[] = { +static constexpr OptionDefinition g_type_category_define_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled." }, - { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for." } + { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If specified, this category will be created enabled." }, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specify the language that this category is supported for." } // clang-format on }; @@ -1891,9 +1891,9 @@ // CommandObjectTypeCategoryEnable //------------------------------------------------------------------------- -static OptionDefinition g_type_category_enable_options[] = { +static constexpr OptionDefinition g_type_category_enable_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." }, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." }, // clang-format on }; @@ -2068,9 +2068,9 @@ // CommandObjectTypeCategoryDisable //------------------------------------------------------------------------- -OptionDefinition g_type_category_disable_options[] = { +OptionDefinition constexpr g_type_category_disable_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." } + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." } // clang-format on }; @@ -2492,14 +2492,14 @@ #endif // LLDB_DISABLE_PYTHON -static OptionDefinition g_type_filter_add_options[] = { +static constexpr OptionDefinition g_type_filter_add_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, - { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." }, - { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." } + { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." }, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." }, + { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." }, + { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." }, + { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." } // clang-format on }; @@ -2747,10 +2747,10 @@ //---------------------------------------------------------------------- // "type lookup" //---------------------------------------------------------------------- -static OptionDefinition g_type_lookup_options[] = { +static constexpr OptionDefinition g_type_lookup_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types" }, - { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be" } + { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display available help for types" }, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Which language's types should the search scope be" } // clang-format on }; Index: source/Commands/CommandObjectWatchpoint.cpp =================================================================== --- source/Commands/CommandObjectWatchpoint.cpp +++ source/Commands/CommandObjectWatchpoint.cpp @@ -158,11 +158,11 @@ //------------------------------------------------------------------------- #pragma mark List::CommandOptions -static OptionDefinition g_watchpoint_list_options[] = { +static constexpr OptionDefinition g_watchpoint_list_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." }, - { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." }, - { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." } + { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." }, + { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." }, + { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." } // clang-format on }; @@ -529,9 +529,9 @@ //------------------------------------------------------------------------- #pragma mark Ignore::CommandOptions -static OptionDefinition g_watchpoint_ignore_options[] = { +static constexpr OptionDefinition g_watchpoint_ignore_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." } + { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." } // clang-format on }; @@ -651,9 +651,9 @@ #pragma mark Modify::CommandOptions -static OptionDefinition g_watchpoint_modify_options[] = { +static constexpr OptionDefinition g_watchpoint_modify_options[] = { // clang-format off - { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." } + { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." } // clang-format on }; Index: source/Commands/CommandObjectWatchpointCommand.cpp =================================================================== --- source/Commands/CommandObjectWatchpointCommand.cpp +++ source/Commands/CommandObjectWatchpointCommand.cpp @@ -38,20 +38,23 @@ // language to lldb and have it pickable here without having to change this // enumeration by hand and rebuild lldb proper. -static OptionEnumValueElement g_script_option_enumeration[4] = { +static constexpr OptionEnumValueElement g_script_option_enumeration[] = { {eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, {eScriptLanguagePython, "python", "Commands are in the Python language."}, {eSortOrderByName, "default-script", - "Commands are in the default scripting language."}, - {0, nullptr, nullptr}}; + "Commands are in the default scripting language."} }; -static OptionDefinition g_watchpoint_command_add_options[] = { +static constexpr OptionEnumValues ScriptOptionEnum() { + return OptionEnumValues(g_script_option_enumeration); +} + +static constexpr OptionDefinition g_watchpoint_command_add_options[] = { // clang-format off - { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether watchpoint command execution should terminate on error." }, - { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, - { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate." } + { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." }, + { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether watchpoint command execution should terminate on error." }, + { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, + { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate." } // clang-format on }; Index: source/Core/Debugger.cpp =================================================================== --- source/Core/Debugger.cpp +++ source/Core/Debugger.cpp @@ -91,7 +91,7 @@ static DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain -OptionEnumValueElement g_show_disassembly_enum_values[] = { +static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { {Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", @@ -100,16 +100,14 @@ "Show disassembly when there is no source information, or the source file " "is missing when displaying a stop context."}, {Debugger::eStopDisassemblyTypeAlways, "always", - "Always show disassembly when displaying a stop context."}, - {0, nullptr, nullptr}}; + "Always show disassembly when displaying a stop context."} }; -OptionEnumValueElement g_language_enumerators[] = { +static constexpr OptionEnumValueElement g_language_enumerators[] = { {eScriptLanguageNone, "none", "Disable scripting languages."}, {eScriptLanguagePython, "python", "Select python as the default scripting language."}, {eScriptLanguageDefault, "default", - "Select the lldb default as the default scripting language."}, - {0, nullptr, nullptr}}; + "Select the lldb default as the default scripting language."} }; #define MODULE_WITH_FUNC \ "{ " \ @@ -180,7 +178,7 @@ // args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name- // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}: -static OptionEnumValueElement s_stop_show_column_values[] = { +static constexpr OptionEnumValueElement s_stop_show_column_values[] = { {eStopShowColumnAnsiOrCaret, "ansi-or-caret", "Highlight the stop column with ANSI terminal codes when color/ANSI mode " "is enabled; otherwise, fall back to using a text-only caret (^) as if " @@ -192,100 +190,95 @@ "Highlight the stop column with a caret character (^) underneath the stop " "column. This method introduces a new line in source listings that " "display thread stop locations."}, - {eStopShowColumnNone, "none", "Do not highlight the stop column."}, - {0, nullptr, nullptr}}; + {eStopShowColumnNone, "none", "Do not highlight the stop column."}}; -static PropertyDefinition g_properties[] = { - {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, +static constexpr PropertyDefinition g_properties[] = { + {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {}, "If true all confirmation prompts will receive their default reply."}, {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_DISASSEMBLY_FORMAT, nullptr, + DEFAULT_DISASSEMBLY_FORMAT, {}, "The default disassembly format " "string to use when disassembling " "instruction sequences."}, {"frame-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_FRAME_FORMAT, nullptr, + DEFAULT_FRAME_FORMAT, {}, "The default frame format string to use " "when displaying stack frame information " "for threads."}, - {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, + {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {}, "Notify the user explicitly if an expression returns void (default: " "false)."}, {"prompt", OptionValue::eTypeString, true, - OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", - nullptr, "The debugger command line prompt displayed for the user."}, + OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {}, + "The debugger command line prompt displayed for the user."}, {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython, - nullptr, g_language_enumerators, + nullptr, OptionEnumValues(g_language_enumerators), "The script language to be used for evaluating user-written scripts."}, - {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, - nullptr, + {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {}, "The number of disassembly lines to show when displaying a " "stopped context."}, {"stop-disassembly-display", OptionValue::eTypeEnum, true, Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr, - g_show_disassembly_enum_values, + OptionEnumValues(g_show_disassembly_enum_values), "Control when to display disassembly when displaying a stopped context."}, - {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, - nullptr, + {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {}, "The number of sources lines to display that come after the " "current source line when displaying a stopped context."}, - {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, - nullptr, + {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {}, "The number of sources lines to display that come before the " "current source line when displaying a stopped context."}, - {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, "If true, LLDB will highlight the displayed source code."}, + {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {}, + "If true, LLDB will highlight the displayed source code."}, {"stop-show-column", OptionValue::eTypeEnum, false, - eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values, + eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values), "If true, LLDB will use the column information from the debug info to " "mark the current position when displaying a stopped context."}, {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0, - "${ansi.underline}", nullptr, + "${ansi.underline}", {}, "When displaying the column marker in a color-enabled (i.e. ANSI) " "terminal, use the ANSI terminal code specified in this format at the " "immediately before the column to be marked."}, {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0, - "${ansi.normal}", nullptr, + "${ansi.normal}", {}, "When displaying the column marker in a color-enabled (i.e. ANSI) " "terminal, use the ANSI terminal code specified in this format " "immediately after the column to be marked."}, - {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr, + {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {}, "The maximum number of columns to use for displaying text."}, {"thread-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_THREAD_FORMAT, nullptr, + DEFAULT_THREAD_FORMAT, {}, "The default thread format string to use " "when displaying thread information."}, {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_THREAD_STOP_FORMAT, nullptr, + DEFAULT_THREAD_STOP_FORMAT, {}, "The default thread format " "string to use when displaying thread " "information as part of the stop display."}, - {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "Whether to use an external editor or not."}, - {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {}, + "Whether to use an external editor or not."}, + {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {}, "Whether to use Ansi color codes or not."}, {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, + {}, "If true, LLDB will automatically display small structs in " "one-liner format (default: true)."}, - {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {}, "If true, LLDB will auto indent/outdent code. Currently only supported in " "the REPL (default: true)."}, - {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {}, "If true, LLDB will print the values of variables declared in an " "expression. Currently only supported in the REPL (default: true)."}, - {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr, + {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {}, "The tab size to use when indenting code in multi-line input mode " "(default: 4)."}, {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, + {}, "If true, LLDB will automatically escape non-printable and " "escape characters when formatting strings."}, {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_FRAME_FORMAT_NO_ARGS, nullptr, + DEFAULT_FRAME_FORMAT_NO_ARGS, {}, "The default frame format string to use when displaying stack frame" - "information for threads from thread backtrace unique."}, - {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; + "information for threads from thread backtrace unique."}}; enum { ePropertyAutoConfirm = 0, Index: source/Core/ModuleList.cpp =================================================================== --- source/Core/ModuleList.cpp +++ source/Core/ModuleList.cpp @@ -66,16 +66,15 @@ namespace { -PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"enable-external-lookup", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, + {}, "Control the use of external tools or libraries to locate symbol files. " "On macOS, Spotlight is used to locate a matching .dSYM bundle based on " "the UUID of the executable."}, {"clang-modules-cache-path", OptionValue::eTypeFileSpec, true, 0, nullptr, - nullptr, - "The path to the clang modules cache directory (-fmodules-cache-path)."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + {}, + "The path to the clang modules cache directory (-fmodules-cache-path)."}}; enum { ePropertyEnableExternalLookup, ePropertyClangModulesCachePath }; Index: source/Host/common/NativeBreakpointList.cpp =================================================================== --- source/Host/common/NativeBreakpointList.cpp +++ source/Host/common/NativeBreakpointList.cpp @@ -210,20 +210,31 @@ Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const { + auto data = llvm::makeMutableArrayRef(static_cast(buf), size); for (const auto &map : m_breakpoints) { - lldb::addr_t bp_addr = map.first; - // Breapoint not in range, ignore - if (bp_addr < addr || addr + size <= bp_addr) - continue; const auto &bp_sp = map.second; // Not software breakpoint, ignore if (!bp_sp->IsSoftwareBreakpoint()) continue; auto software_bp_sp = std::static_pointer_cast(bp_sp); - auto opcode_addr = static_cast(buf) + bp_addr - addr; - auto saved_opcodes = software_bp_sp->m_saved_opcodes; + + lldb::addr_t bp_addr = map.first; auto opcode_size = software_bp_sp->m_opcode_size; - ::memcpy(opcode_addr, saved_opcodes, opcode_size); + + // Breapoint not in range, ignore + if (bp_addr + opcode_size < addr || addr + size <= bp_addr) + continue; + + auto saved_opcodes = + llvm::makeArrayRef(software_bp_sp->m_saved_opcodes, opcode_size); + if (bp_addr < addr) { + saved_opcodes = saved_opcodes.drop_front(addr - bp_addr); + bp_addr = addr; + } + auto bp_data = data.drop_front(bp_addr - addr); + std::copy_n(saved_opcodes.begin(), + std::min(saved_opcodes.size(), bp_data.size()), + bp_data.begin()); } return Status(); } Index: source/Interpreter/CommandInterpreter.cpp =================================================================== --- source/Interpreter/CommandInterpreter.cpp +++ source/Interpreter/CommandInterpreter.cpp @@ -76,22 +76,20 @@ static const char *k_white_space = " \t\v"; -static PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "If true, regular expression alias commands will show the " + {}, "If true, regular expression alias commands will show the " "expanded command that will be executed. This can be used to " "debug new regular expression alias commands."}, - {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, {}, "If true, LLDB will prompt you before quitting if there are any live " "processes being debugged. If false, LLDB will quit without asking in any " "case."}, {"stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, - nullptr, nullptr, "If true, LLDB will stop running a 'command source' " - "script upon encountering an error."}, - {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, - "If true, blank lines will be printed between between REPL submissions."}, - {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; + nullptr, {}, "If true, LLDB will stop running a 'command source' " + "script upon encountering an error."}, + {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, {}, + "If true, blank lines will be printed between between REPL submissions."}}; enum { ePropertyExpandRegexAliases = 0, Index: source/Interpreter/OptionArgParser.cpp =================================================================== --- source/Interpreter/OptionArgParser.cpp +++ source/Interpreter/OptionArgParser.cpp @@ -46,10 +46,10 @@ } int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, - OptionEnumValueElement *enum_values, + const OptionEnumValues &enum_values, int32_t fail_value, Status &error) { error.Clear(); - if (!enum_values) { + if (enum_values.empty()) { error.SetErrorString("invalid enumeration argument"); return fail_value; } @@ -59,16 +59,18 @@ return fail_value; } - for (int i = 0; enum_values[i].string_value != nullptr; i++) { - llvm::StringRef this_enum(enum_values[i].string_value); + for (const auto &enum_value : enum_values) { + llvm::StringRef this_enum(enum_value.string_value); if (this_enum.startswith(s)) - return enum_values[i].value; + return enum_value.value; } StreamString strm; strm.PutCString("invalid enumeration value, valid values are: "); - for (int i = 0; enum_values[i].string_value != nullptr; i++) { - strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value); + bool is_first = true; + for (const auto &enum_value : enum_values) { + strm.Printf("%s\"%s\"", + is_first ? is_first = false,"" : ", ", enum_value.string_value); } error.SetErrorString(strm.GetString()); return fail_value; Index: source/Interpreter/OptionGroupArchitecture.cpp =================================================================== --- source/Interpreter/OptionGroupArchitecture.cpp +++ source/Interpreter/OptionGroupArchitecture.cpp @@ -18,9 +18,9 @@ OptionGroupArchitecture::~OptionGroupArchitecture() {} -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "arch", 'a', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeArchitecture, + nullptr, {}, 0, eArgTypeArchitecture, "Specify the architecture for the target."}, }; Index: source/Interpreter/OptionGroupBoolean.cpp =================================================================== --- source/Interpreter/OptionGroupBoolean.cpp +++ source/Interpreter/OptionGroupBoolean.cpp @@ -32,7 +32,7 @@ m_option_definition.option_has_arg = no_argument_toggle_default ? OptionParser::eNoArgument : OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; + m_option_definition.enum_values = {}; m_option_definition.completion_type = 0; m_option_definition.argument_type = eArgTypeBoolean; m_option_definition.usage_text = usage_text; Index: source/Interpreter/OptionGroupFile.cpp =================================================================== --- source/Interpreter/OptionGroupFile.cpp +++ source/Interpreter/OptionGroupFile.cpp @@ -30,7 +30,7 @@ m_option_definition.short_option = short_option; m_option_definition.validator = nullptr; m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; + m_option_definition.enum_values = {}; m_option_definition.completion_type = completion_type; m_option_definition.argument_type = argument_type; m_option_definition.usage_text = usage_text; @@ -61,7 +61,7 @@ m_option_definition.short_option = short_option; m_option_definition.validator = nullptr; m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; + m_option_definition.enum_values = {}; m_option_definition.completion_type = completion_type; m_option_definition.argument_type = argument_type; m_option_definition.usage_text = usage_text; Index: source/Interpreter/OptionGroupFormat.cpp =================================================================== --- source/Interpreter/OptionGroupFormat.cpp +++ source/Interpreter/OptionGroupFormat.cpp @@ -27,18 +27,18 @@ OptionGroupFormat::~OptionGroupFormat() {} -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFormat, + nullptr, {}, 0, eArgTypeFormat, "Specify a format to be used for display."}, {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeGDBFormat, + nullptr, {}, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."}, {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeByteSize, + nullptr, {}, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."}, {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeCount, + nullptr, {}, 0, eArgTypeCount, "The number of total items to display."}, }; Index: source/Interpreter/OptionGroupOutputFile.cpp =================================================================== --- source/Interpreter/OptionGroupOutputFile.cpp +++ source/Interpreter/OptionGroupOutputFile.cpp @@ -25,12 +25,12 @@ static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd' -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "outfile", 'o', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, + nullptr, {}, 0, eArgTypeFilename, "Specify a path for capturing command output."}, {LLDB_OPT_SET_1, false, "append-outfile", SHORT_OPTION_APND, - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to the file specified with '--outfile '."}, }; Index: source/Interpreter/OptionGroupPlatform.cpp =================================================================== --- source/Interpreter/OptionGroupPlatform.cpp +++ source/Interpreter/OptionGroupPlatform.cpp @@ -65,21 +65,21 @@ m_os_version = llvm::VersionTuple(); } -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to " - "use for this target, creating the " - "platform if necessary."}, + nullptr, {}, 0, eArgTypePlatform, "Specify name of the platform to " + "use for this target, creating the " + "platform if necessary."}, {LLDB_OPT_SET_ALL, false, "version", 'v', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting."}, {LLDB_OPT_SET_ALL, false, "build", 'b', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Specify the initial SDK build number."}, {LLDB_OPT_SET_ALL, false, "sysroot", 'S', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory " - "that contains a root of all " - "remote system files."}}; + nullptr, {}, 0, eArgTypeFilename, "Specify the SDK root directory " + "that contains a root of all " + "remote system files."}}; llvm::ArrayRef OptionGroupPlatform::GetDefinitions() { llvm::ArrayRef result(g_option_table); Index: source/Interpreter/OptionGroupString.cpp =================================================================== --- source/Interpreter/OptionGroupString.cpp +++ source/Interpreter/OptionGroupString.cpp @@ -31,7 +31,7 @@ m_option_definition.short_option = short_option; m_option_definition.validator = nullptr; m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; + m_option_definition.enum_values = {}; m_option_definition.completion_type = completion_type; m_option_definition.argument_type = argument_type; m_option_definition.usage_text = usage_text; Index: source/Interpreter/OptionGroupUInt64.cpp =================================================================== --- source/Interpreter/OptionGroupUInt64.cpp +++ source/Interpreter/OptionGroupUInt64.cpp @@ -31,7 +31,7 @@ m_option_definition.short_option = short_option; m_option_definition.validator = nullptr; m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; + m_option_definition.enum_values = {}; m_option_definition.completion_type = completion_type; m_option_definition.argument_type = argument_type; m_option_definition.usage_text = usage_text; Index: source/Interpreter/OptionGroupUUID.cpp =================================================================== --- source/Interpreter/OptionGroupUUID.cpp +++ source/Interpreter/OptionGroupUUID.cpp @@ -22,9 +22,9 @@ OptionGroupUUID::~OptionGroupUUID() {} -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."}, + nullptr, {}, 0, eArgTypeNone, "A module UUID value."}, }; llvm::ArrayRef OptionGroupUUID::GetDefinitions() { Index: source/Interpreter/OptionGroupValueObjectDisplay.cpp =================================================================== --- source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -28,46 +28,44 @@ OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {} -static OptionDefinition g_option_table[] = { +static const OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "dynamic-type", 'd', - OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0, + OptionParser::eRequiredArgument, nullptr, GetDynamicValueTypes(), 0, eArgTypeNone, "Show the object as its full dynamic type, not its static " "type, if available."}, {LLDB_OPT_SET_1, false, "synthetic-type", 'S', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."}, {LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when " - "dumping aggregate types (default is " - "infinity)."}, + nullptr, {}, 0, eArgTypeCount, "Set the max recurse depth when dumping " + "aggregate types (default is infinity)."}, {LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, "Display results in a flat format that uses " - "expression paths for each variable or member."}, + {}, 0, eArgTypeNone, "Display results in a flat format that uses " + "expression paths for each variable or member."}, {LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, "Show variable location information."}, + {}, 0, eArgTypeNone, "Show variable location information."}, {LLDB_OPT_SET_1, false, "object-description", 'O', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print as an Objective-C object."}, {LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be " - "traversed when dumping values " - "(default is zero)."}, + nullptr, {}, 0, eArgTypeCount, "The number of pointers to be traversed " + "when dumping values (default is zero)."}, {LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Show variable types when dumping values."}, {LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', - OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, + OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is " "1)."}, {LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, + nullptr, {}, 0, eArgTypeNone, "Don't use formatting options."}, {LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."}, {LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."}, + nullptr, {}, 0, eArgTypeBoolean, "Show results of type validators."}, {LLDB_OPT_SET_1, false, "element-count", 'Z', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Treat the result of the expression as if its type is an array of this " "many values."}}; @@ -86,8 +84,8 @@ switch (short_option) { case 'd': { int32_t result; - result = OptionArgParser::ToOptionEnum(option_arg, g_dynamic_value_types, 2, - error); + result = OptionArgParser::ToOptionEnum(option_arg, GetDynamicValueTypes(), + 2, error); if (error.Success()) use_dynamic = (lldb::DynamicValueType)result; } break; Index: source/Interpreter/OptionGroupVariable.cpp =================================================================== --- source/Interpreter/OptionGroupVariable.cpp +++ source/Interpreter/OptionGroupVariable.cpp @@ -24,31 +24,31 @@ // if you add any options here, remember to update the counters in // OptionGroupVariable::GetNumDefinitions() -static OptionDefinition g_variable_options[] = { +static constexpr OptionDefinition g_variable_options[] = { {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Omit function arguments."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Omit local variables."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show the current frame source file global and static variables."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration", 'c', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show variable declaration information (source file and line where the " "variable was declared)."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeRegularExpression, "The argument for name lookups are regular expressions."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."}, {LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeName, + nullptr, {}, 0, eArgTypeName, "Specify the summary that the variable output should use."}, {LLDB_OPT_SET_2, false, "summary-string", 'z', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Specify a summary string to use to format the variable output."}, }; Index: source/Interpreter/OptionGroupWatchpoint.cpp =================================================================== --- source/Interpreter/OptionGroupWatchpoint.cpp +++ source/Interpreter/OptionGroupWatchpoint.cpp @@ -20,33 +20,31 @@ using namespace lldb; using namespace lldb_private; -static OptionEnumValueElement g_watch_type[] = { +static constexpr OptionEnumValueElement g_watch_type[] = { {OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"}, {OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"}, {OptionGroupWatchpoint::eWatchReadWrite, "read_write", - "Watch for read/write"}, - {0, nullptr, nullptr}}; + "Watch for read/write"} }; -static OptionEnumValueElement g_watch_size[] = { +static constexpr OptionEnumValueElement g_watch_size[] = { {1, "1", "Watch for byte size of 1"}, {2, "2", "Watch for byte size of 2"}, {4, "4", "Watch for byte size of 4"}, - {8, "8", "Watch for byte size of 8"}, - {0, nullptr, nullptr}}; + {8, "8", "Watch for byte size of 8"} }; -static OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, - nullptr, g_watch_type, 0, eArgTypeWatchType, + nullptr, OptionEnumValues(g_watch_type), 0, eArgTypeWatchType, "Specify the type of watching to perform."}, {LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, - nullptr, g_watch_size, 0, eArgTypeByteSize, + nullptr, OptionEnumValues(g_watch_size), 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}}; bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) { - for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i) { - if (g_watch_size[i].value == 0) + for (const auto& size : g_watch_size) { + if (0 == size.value) break; - if (watch_size == g_watch_size[i].value) + if (watch_size == size.value) return true; } return false; Index: source/Interpreter/OptionValueEnumeration.cpp =================================================================== --- source/Interpreter/OptionValueEnumeration.cpp +++ source/Interpreter/OptionValueEnumeration.cpp @@ -19,7 +19,7 @@ using namespace lldb_private; OptionValueEnumeration::OptionValueEnumeration( - const OptionEnumValueElement *enumerators, enum_type value) + const OptionEnumValues &enumerators, enum_type value) : OptionValue(), m_current_value(value), m_default_value(value), m_enumerations() { SetEnumerations(enumerators); @@ -91,18 +91,16 @@ } void OptionValueEnumeration::SetEnumerations( - const OptionEnumValueElement *enumerators) { + const OptionEnumValues &enumerators) { m_enumerations.Clear(); - if (enumerators) { - for (size_t i = 0; enumerators[i].string_value != nullptr; ++i) { - ConstString const_enumerator_name(enumerators[i].string_value); - EnumeratorInfo enumerator_info = {enumerators[i].value, - enumerators[i].usage}; - m_enumerations.Append(const_enumerator_name, - enumerator_info); - } - m_enumerations.Sort(); + + for (const auto &enumerator : enumerators) { + ConstString const_enumerator_name(enumerator.string_value); + EnumeratorInfo enumerator_info = {enumerator.value, enumerator.usage}; + m_enumerations.Append(const_enumerator_name, enumerator_info); } + + m_enumerations.Sort(); } lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const { Index: source/Interpreter/OptionValueProperties.cpp =================================================================== --- source/Interpreter/OptionValueProperties.cpp +++ source/Interpreter/OptionValueProperties.cpp @@ -53,9 +53,9 @@ return m_properties.size(); } -void OptionValueProperties::Initialize(const PropertyDefinition *defs) { - for (size_t i = 0; defs[i].name; ++i) { - Property property(defs[i]); +void OptionValueProperties::Initialize(const PropertyDefinitions &defs) { + for (const auto &definition : defs) { + Property property(definition); assert(property.IsValid()); m_name_to_index.Append(ConstString(property.GetName()), m_properties.size()); property.GetValue()->SetParent(shared_from_this()); Index: source/Interpreter/Options.cpp =================================================================== --- source/Interpreter/Options.cpp +++ source/Interpreter/Options.cpp @@ -601,15 +601,17 @@ if (opt_defs[i].usage_text) OutputFormattedUsageText(strm, opt_defs[i], screen_width); - if (opt_defs[i].enum_values != nullptr) { + if (!opt_defs[i].enum_values.empty()) { strm.Indent(); strm.Printf("Values: "); - for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; - k++) { - if (k == 0) - strm.Printf("%s", opt_defs[i].enum_values[k].string_value); + bool is_first = true; + for (const auto &enum_value : opt_defs[i].enum_values) { + if (is_first) { + strm.Printf("%s", enum_value.string_value); + is_first = false; + } else - strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); + strm.Printf(" | %s", enum_value.string_value); } strm.EOL(); } @@ -770,17 +772,18 @@ // See if this is an enumeration type option, and if so complete it here: - OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values; - if (enum_values != nullptr) { + const auto &enum_values = opt_defs[opt_defs_index].enum_values; + if (!enum_values.empty()) { bool return_value = false; std::string match_string( request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos), request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos) + request.GetCursorCharPosition()); - for (int i = 0; enum_values[i].string_value != nullptr; i++) { - if (strstr(enum_values[i].string_value, match_string.c_str()) == - enum_values[i].string_value) { - request.AddCompletion(enum_values[i].string_value); + + for (const auto &enum_value : enum_values) { + if (strstr(enum_value.string_value, match_string.c_str()) == + enum_value.string_value) { + request.AddCompletion(enum_value.string_value); return_value = true; } } Index: source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp =================================================================== --- source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -58,7 +58,7 @@ // range looking for a kernel }; -OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = { +static constexpr OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = { {eKASLRScanNone, "none", "Do not read memory looking for a Darwin kernel when attaching."}, {eKASLRScanLowgloAddresses, "basic", "Check for the Darwin kernel's load " @@ -68,17 +68,15 @@ "the Darwin kernel's load address."}, {eKASLRScanExhaustiveScan, "exhaustive-scan", "Scan through the entire potential address range of Darwin kernel (only " - "on 32-bit targets)."}, - {0, NULL, NULL}}; + "on 32-bit targets)."}}; -static PropertyDefinition g_properties[] = { - {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, NULL, +static constexpr PropertyDefinition g_properties[] = { + {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, {}, "Automatically loads kext images when attaching to a kernel."}, {"scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, NULL, - g_kaslr_kernel_scan_enum_values, "Control how many reads lldb will make " - "while searching for a Darwin kernel on " - "attach."}, - {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; + OptionEnumValues(g_kaslr_kernel_scan_enum_values), + "Control how many reads lldb will make while searching for a Darwin " + "kernel on attach."}}; enum { ePropertyLoadKexts, ePropertyScanType }; Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -177,8 +177,8 @@ lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) override; - llvm::Optional GetLanguageForExpr( - DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); + void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx); bool SetupPersistentState(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); bool PrepareForParsing(DiagnosticManager &diagnostic_manager, @@ -201,6 +201,9 @@ lldb::TargetSP m_target_sp; }; + /// The language type of the current expression. + lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown; + /// The absolute character position in the transformed source code where the /// user code (as typed by the user) starts. If the variable is empty, then we /// were not able to calculate this position. Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -376,9 +376,9 @@ } } -llvm::Optional ClangUserExpression::GetLanguageForExpr( +void ClangUserExpression::UpdateLanguageForExpr( DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { - lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown; + m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; std::string prefix = m_expr_prefix; @@ -390,17 +390,17 @@ m_expr_text.c_str())); if (m_in_cplusplus_method) - lang_type = lldb::eLanguageTypeC_plus_plus; + m_expr_lang = lldb::eLanguageTypeC_plus_plus; else if (m_in_objectivec_method) - lang_type = lldb::eLanguageTypeObjC; + m_expr_lang = lldb::eLanguageTypeObjC; else - lang_type = lldb::eLanguageTypeC; + m_expr_lang = lldb::eLanguageTypeC; - if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method, - exe_ctx)) { + if (!source_code->GetText(m_transformed_text, m_expr_lang, + m_in_static_method, exe_ctx)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); - return llvm::Optional(); + return; } // Find and store the start position of the original code inside the @@ -408,12 +408,11 @@ std::size_t original_start; std::size_t original_end; bool found_bounds = source_code->GetOriginalBodyBounds( - m_transformed_text, lang_type, original_start, original_end); + m_transformed_text, m_expr_lang, original_start, original_end); if (found_bounds) { m_user_expression_start_pos = original_start; } } - return lang_type; } bool ClangUserExpression::PrepareForParsing( @@ -437,6 +436,8 @@ ApplyObjcCastHack(m_expr_text); SetupDeclVendor(exe_ctx, m_target); + + UpdateLanguageForExpr(diagnostic_manager, exe_ctx); return true; } @@ -450,11 +451,6 @@ if (!PrepareForParsing(diagnostic_manager, exe_ctx)) return false; - lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown; - if (auto new_lang = GetLanguageForExpr(diagnostic_manager, exe_ctx)) { - lang_type = new_lang.getValue(); - } - if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); @@ -514,7 +510,7 @@ const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); if (ExpressionSourceCode::GetOriginalBodyBounds( - fixed_expression, lang_type, fixed_start, fixed_end)) + fixed_expression, m_expr_lang, fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); } @@ -655,8 +651,6 @@ if (!PrepareForParsing(diagnostic_manager, exe_ctx)) return false; - GetLanguageForExpr(diagnostic_manager, exe_ctx); - if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); Index: source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp =================================================================== --- source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -59,10 +59,9 @@ namespace { -PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"enable-jit-breakpoint", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, "Enable breakpoint on __jit_debug_register_code."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + {}, "Enable breakpoint on __jit_debug_register_code."}}; enum { ePropertyEnableJITBreakpoint }; Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -475,9 +475,9 @@ return NULL; } -static OptionDefinition g_objc_classtable_dump_options[] = { +static constexpr OptionDefinition g_objc_classtable_dump_options[] = { {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Print ivar and method information in detail"}}; class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed { Index: source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp =================================================================== --- source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -4171,13 +4171,13 @@ } }; -static OptionDefinition g_renderscript_reduction_bp_set_options[] = { +static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = { {LLDB_OPT_SET_1, false, "function-role", 't', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Break on a comma separated set of reduction kernel types " "(accumulator,outcoverter,combiner,initializer"}, {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeValue, + nullptr, {}, 0, eArgTypeValue, "Set a breakpoint on a single invocation of the kernel with specified " "coordinate.\n" "Coordinate takes the form 'x[,y][,z] where x,y,z are positive " @@ -4330,9 +4330,9 @@ CommandOptions m_options; }; -static OptionDefinition g_renderscript_kernel_bp_set_options[] = { +static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = { {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeValue, + nullptr, {}, 0, eArgTypeValue, "Set a breakpoint on a single invocation of the kernel with specified " "coordinate.\n" "Coordinate takes the form 'x[,y][,z] where x,y,z are positive " @@ -4602,9 +4602,9 @@ } }; -static OptionDefinition g_renderscript_runtime_alloc_dump_options[] = { +static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = { {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, + nullptr, {}, 0, eArgTypeFilename, "Print results to specified file instead of command line."}}; class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword { @@ -4738,9 +4738,9 @@ CommandOptions m_options; }; -static OptionDefinition g_renderscript_runtime_alloc_list_options[] = { +static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = { {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr, - nullptr, 0, eArgTypeIndex, + {}, 0, eArgTypeIndex, "Only show details of a single allocation with specified id."}}; class CommandObjectRenderScriptRuntimeAllocationList Index: source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp =================================================================== --- source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp +++ source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp @@ -46,10 +46,9 @@ namespace { -static PropertyDefinition g_properties[] = { - {"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, - "Specify whether goroutines should be treated as threads."}, - {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; +static constexpr PropertyDefinition g_properties[] = { + {"enable", OptionValue::eTypeBoolean, true, true, nullptr, {}, + "Specify whether goroutines should be treated as threads."}}; enum { ePropertyEnableGoroutines, Index: source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp =================================================================== --- source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -186,14 +186,13 @@ /// Code to handle the PlatformDarwinKernel settings //------------------------------------------------------------------ -static PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"search-locally-for-kexts", OptionValue::eTypeBoolean, true, true, NULL, - NULL, "Automatically search for kexts on the local system when doing " + {}, "Automatically search for kexts on the local system when doing " "kernel debugging."}, - {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, + {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, {}, "Directories/KDKs to search for kexts in when starting a kernel debug " - "session."}, - {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; + "session."}}; enum { ePropertySearchForKexts = 0, ePropertyKextDirectories }; Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -335,7 +335,7 @@ GetTarget().SetArchitecture(module_arch); // Initialize the target module list - GetTarget().SetExecutableModule(exe_module_sp, true); + GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsYes); SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); @@ -519,7 +519,7 @@ executable_search_paths.GetSize() ? &executable_search_paths : NULL); if (!error.Success()) return; - target->SetExecutableModule(exe_module_sp, true); + target->SetExecutableModule(exe_module_sp, eLoadDependentsYes); } } } Index: source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp =================================================================== --- source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -55,10 +55,9 @@ namespace { -static PropertyDefinition g_properties[] = { - {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, NULL, - "Specify the default packet timeout in seconds."}, - {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; +static constexpr PropertyDefinition g_properties[] = { + {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {}, + "Specify the default packet timeout in seconds."}}; enum { ePropertyPacketTimeout }; Index: source/Plugins/Process/Utility/UnwindLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/UnwindLLDB.cpp +++ source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -130,6 +130,8 @@ RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB( m_thread, prev_frame->reg_ctx_lldb_sp, cursor_sp->sctx, cur_idx, *this)); + uint64_t max_stack_depth = m_thread.GetMaxBacktraceDepth(); + // We want to detect an unwind that cycles erroneously and stop backtracing. // Don't want this maximum unwind limit to be too low -- if you have a // backtrace with an "infinitely recursing" bug, it will crash when the stack @@ -138,7 +140,7 @@ // unwind at 10,000 or something. Realistically anything over around 200,000 // is going to blow out the stack space. If we're still unwinding at that // point, we're probably never going to finish. - if (cur_idx > 300000) { + if (cur_idx >= max_stack_depth) { if (log) log->Printf("%*sFrame %d unwound too many frames, assuming unwind has " "gone astray, stopping.", Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -110,12 +110,11 @@ namespace { -static PropertyDefinition g_properties[] = { - {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL, +static constexpr PropertyDefinition g_properties[] = { + {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, {}, "Specify the default packet timeout in seconds."}, - {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL, - "The file that provides the description for remote target registers."}, - {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; + {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, {}, + "The file that provides the description for remote target registers."}}; enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; Index: source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp =================================================================== --- source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -112,14 +112,14 @@ /// Code to handle the StructuredDataDarwinLog settings //------------------------------------------------------------------ -static PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { { "enable-on-startup", // name OptionValue::eTypeBoolean, // type true, // global false, // default uint value nullptr, // default cstring value - nullptr, // enum values + {}, // enum values "Enable Darwin os_log collection when debugged process is launched " "or attached." // description }, @@ -129,13 +129,11 @@ true, // global 0, // default uint value "", // default cstring value - nullptr, // enum values + {}, // enum values "Specify the options to 'plugin structured-data darwin-log enable' " "that should be applied when automatically enabling logging on " "startup/attach." // description - }, - // Last entry sentinel. - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + }}; enum { ePropertyEnableOnStartup = 0, ePropertyAutoEnableOptions = 1 }; @@ -402,23 +400,23 @@ /// This resets the logging with whatever settings are currently set. // ------------------------------------------------------------------------- -static OptionDefinition g_enable_option_table[] = { +static constexpr OptionDefinition g_enable_option_table[] = { // Source stream include/exclude options (the first-level filter). This one // should be made as small as possible as everything that goes through here // must be processed by the process monitor. {LLDB_OPT_SET_ALL, false, "any-process", 'a', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Specifies log messages from other related processes should be " "included."}, {LLDB_OPT_SET_ALL, false, "debug", 'd', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, + {}, 0, eArgTypeNone, "Specifies debug-level log messages should be included. Specifying" " --debug implies --info."}, {LLDB_OPT_SET_ALL, false, "info", 'i', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, + {}, 0, eArgTypeNone, "Specifies info-level log messages should be included."}, {LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgRawInput, + nullptr, {}, 0, eArgRawInput, // There doesn't appear to be a great way for me to have these multi-line, // formatted tables in help. This looks mostly right but there are extra // linefeeds added at seemingly random spots, and indentation isn't @@ -452,52 +450,52 @@ "Prefer character classes like [[:digit:]] to \\d and the like, as " "getting the backslashes escaped through properly is error-prone."}, {LLDB_OPT_SET_ALL, false, "live-stream", 'l', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether logging events are live-streamed or buffered. " "True indicates live streaming, false indicates buffered. The " "default is true (live streaming). Live streaming will deliver " "log messages with less delay, but buffered capture mode has less " "of an observer effect."}, {LLDB_OPT_SET_ALL, false, "no-match-accepts", 'n', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether a log message that doesn't match any filter rule " "is accepted or rejected, where true indicates accept. The " "default is true."}, {LLDB_OPT_SET_ALL, false, "echo-to-stderr", 'e', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether os_log()/NSLog() messages are echoed to the " "target program's stderr. When DarwinLog is enabled, we shut off " "the mirroring of os_log()/NSLog() to the program's stderr. " "Setting this flag to true will restore the stderr mirroring." "The default is false."}, {LLDB_OPT_SET_ALL, false, "broadcast-events", 'b', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify if the plugin should broadcast events. Broadcasting " "log events is a requirement for displaying the log entries in " "LLDB command-line. It is also required if LLDB clients want to " "process log events. The default is true."}, // Message formatting options {LLDB_OPT_SET_ALL, false, "timestamp-relative", 'r', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include timestamp in the message header when printing a log " "message. The timestamp is relative to the first displayed " "message."}, {LLDB_OPT_SET_ALL, false, "subsystem", 's', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Include the subsystem in the the message header when displaying " "a log message."}, {LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, - "Include the category in the message header when displaying " + nullptr, {}, 0, eArgTypeNone, + "Include the category in the the message header when displaying " "a log message."}, {LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Include the activity parent-child chain in the message header " "when displaying a log message. The activity hierarchy is " "displayed as {grandparent-activity}:" "{parent-activity}:{activity}[:...]."}, {LLDB_OPT_SET_ALL, false, "all-fields", 'A', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Shortcut to specify that all header fields should be displayed."}}; class EnableOptions : public Options { Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -111,17 +111,14 @@ namespace { -PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr, - nullptr, + {}, "If the DW_AT_comp_dir matches any of these paths the symbolic " "links will be resolved at DWARF parse time."}, - {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, - nullptr, + {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {}, "Ignore indexes present in the object files and always index DWARF " - "manually."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}, -}; + "manually."}}; enum { ePropertySymLinkPaths, Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -331,6 +331,26 @@ return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; } +static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) { + switch (pdb_cc) { + case llvm::codeview::CallingConvention::NearC: + return clang::CC_C; + case llvm::codeview::CallingConvention::NearStdCall: + return clang::CC_X86StdCall; + case llvm::codeview::CallingConvention::NearFast: + return clang::CC_X86FastCall; + case llvm::codeview::CallingConvention::ThisCall: + return clang::CC_X86ThisCall; + case llvm::codeview::CallingConvention::NearVector: + return clang::CC_X86VectorCall; + case llvm::codeview::CallingConvention::NearPascal: + return clang::CC_X86Pascal; + default: + assert(false && "Unknown calling convention"); + return clang::CC_C; + } +} + PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {} PDBASTParser::~PDBASTParser() {} @@ -603,9 +623,10 @@ type_quals |= clang::Qualifiers::Const; if (func_sig->isVolatileType()) type_quals |= clang::Qualifiers::Volatile; + auto cc = TranslateCallingConvention(func_sig->getCallingConvention()); CompilerType func_sig_ast_type = m_ast.CreateFunctionType(return_ast_type, arg_list.data(), - arg_list.size(), is_variadic, type_quals); + arg_list.size(), is_variadic, type_quals, cc); GetDeclarationForSymbol(type, decl); return std::make_shared( Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -2058,7 +2058,8 @@ CompilerType ClangASTContext::CreateFunctionType( ASTContext *ast, const CompilerType &result_type, const CompilerType *args, - unsigned num_args, bool is_variadic, unsigned type_quals) { + unsigned num_args, bool is_variadic, unsigned type_quals, + clang::CallingConv cc) { if (ast == nullptr) return CompilerType(); // invalid AST @@ -2086,6 +2087,7 @@ // TODO: Detect calling convention in DWARF? FunctionProtoType::ExtProtoInfo proto_info; + proto_info.ExtInfo = cc; proto_info.Variadic = is_variadic; proto_info.ExceptionSpec = EST_None; proto_info.TypeQuals = type_quals; Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -67,12 +67,11 @@ namespace { -PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"use-module-cache", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, "Use module cache."}, + {}, "Use module cache."}, {"module-cache-directory", OptionValue::eTypeFileSpec, true, 0, nullptr, - nullptr, "Root directory for cached modules."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + {}, "Root directory for cached modules."}}; enum { ePropertyUseModuleCache, ePropertyModuleCacheDirectory }; @@ -1397,32 +1396,32 @@ return m_local_cache_directory.c_str(); } -static OptionDefinition g_rsync_option_table[] = { +static constexpr OptionDefinition g_rsync_option_table[] = { {LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, "Enable rsync."}, + {}, 0, eArgTypeNone, "Enable rsync."}, {LLDB_OPT_SET_ALL, false, "rsync-opts", 'R', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName, "Platform-specific options required for rsync to work."}, {LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName, "Platform-specific rsync prefix put before the remote path."}, {LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i', - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Do not automatically fill in the remote hostname when composing the " "rsync command."}, }; -static OptionDefinition g_ssh_option_table[] = { +static constexpr OptionDefinition g_ssh_option_table[] = { {LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, "Enable SSH."}, + {}, 0, eArgTypeNone, "Enable SSH."}, {LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeCommandName, + nullptr, {}, 0, eArgTypeCommandName, "Platform-specific options required for SSH to work."}, }; -static OptionDefinition g_caching_option_table[] = { +static constexpr OptionDefinition g_caching_option_table[] = { {LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePath, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath, "Path in which to store local copies of files."}, }; Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -116,39 +116,38 @@ } }; -static PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"disable-memory-cache", OptionValue::eTypeBoolean, false, - DISABLE_MEM_CACHE_DEFAULT, nullptr, nullptr, + DISABLE_MEM_CACHE_DEFAULT, nullptr, {}, "Disable reading and caching of memory in fixed-size units."}, {"extra-startup-command", OptionValue::eTypeArray, false, - OptionValue::eTypeString, nullptr, nullptr, + OptionValue::eTypeString, nullptr, {}, "A list containing extra commands understood by the particular process " "plugin used. " "For instance, to turn on debugserver logging set this to " "\"QSetLogging:bitmask=LOG_DEFAULT;\""}, {"ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true, - nullptr, nullptr, + nullptr, {}, "If true, breakpoints will be ignored during expression evaluation."}, {"unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, - nullptr, nullptr, "If true, errors in expression evaluation will unwind " - "the stack back to the state before the call."}, + nullptr, {}, "If true, errors in expression evaluation will unwind " + "the stack back to the state before the call."}, {"python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, nullptr, - nullptr, "A path to a python OS plug-in module file that contains a " - "OperatingSystemPlugIn class."}, + {}, "A path to a python OS plug-in module file that contains a " + "OperatingSystemPlugIn class."}, {"stop-on-sharedlibrary-events", OptionValue::eTypeBoolean, true, false, - nullptr, nullptr, + nullptr, {}, "If true, stop when a shared library is loaded or unloaded."}, {"detach-keeps-stopped", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "If true, detach will attempt to keep the process stopped."}, + {}, "If true, detach will attempt to keep the process stopped."}, {"memory-cache-line-size", OptionValue::eTypeUInt64, false, 512, nullptr, - nullptr, "The memory cache line size"}, + {}, "The memory cache line size"}, {"optimization-warnings", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "If true, warn when stopped in code that is optimized where " - "stepping and variable availability may not behave as expected."}, + {}, "If true, warn when stopped in code that is optimized where " + "stepping and variable availability may not behave as expected."}, {"stop-on-exec", OptionValue::eTypeBoolean, true, true, - nullptr, nullptr, - "If true, stop when a shared library is loaded or unloaded."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + nullptr, {}, + "If true, stop when a shared library is loaded or unloaded."}}; enum { ePropertyDisableMemCache, @@ -533,52 +532,52 @@ return error; } -static OptionDefinition g_process_launch_options[] = { +static constexpr OptionDefinition g_process_launch_options[] = { {LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, - nullptr, nullptr, 0, eArgTypeNone, + nullptr, {}, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, {LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set whether to disable address space layout randomization when launching " "a process."}, {LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypePlugin, + nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, {LLDB_OPT_SET_ALL, false, "working-dir", 'w', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeDirectoryName, "Set the current working directory to when running the inferior."}, {LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeArchitecture, + nullptr, {}, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."}, {LLDB_OPT_SET_ALL, false, "environment", 'v', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment " "NAME=VALUE). Can be specified multiple times for subsequent environment " "entries."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "shell", 'c', - OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeFilename, + OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."}, {LLDB_OPT_SET_1, false, "stdin", 'i', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, + nullptr, {}, 0, eArgTypeFilename, "Redirect stdin for the process to ."}, {LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, + nullptr, {}, 0, eArgTypeFilename, "Redirect stdout for the process to ."}, {LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument, - nullptr, nullptr, 0, eArgTypeFilename, + nullptr, {}, 0, eArgTypeFilename, "Redirect stderr for the process to ."}, {LLDB_OPT_SET_2, false, "tty", 't', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, + {}, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."}, {LLDB_OPT_SET_3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, - nullptr, 0, eArgTypeNone, + {}, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, {LLDB_OPT_SET_4, false, "shell-expand-args", 'X', - OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set whether to shell expand arguments to the process when launching."}, }; Index: source/Target/Target.cpp =================================================================== --- source/Target/Target.cpp +++ source/Target/Target.cpp @@ -1446,20 +1446,20 @@ FileSpecList dependent_files; ObjectFile *executable_objfile = executable_sp->GetObjectFile(); - bool load_dependens; + bool load_dependents = true; switch (load_dependent_files) { case eLoadDependentsDefault: - load_dependens = executable_sp->IsExecutable(); + load_dependents = executable_sp->IsExecutable(); break; case eLoadDependentsYes: - load_dependens = true; + load_dependents = true; break; case eLoadDependentsNo: - load_dependens = false; + load_dependents = false; break; } - if (executable_objfile && load_dependens) { + if (executable_objfile && load_dependents) { executable_objfile->GetDependentModules(dependent_files); for (uint32_t i = 0; i < dependent_files.GetSize(); i++) { FileSpec dependent_file_spec( @@ -3125,16 +3125,19 @@ // class TargetProperties //-------------------------------------------------------------- -OptionEnumValueElement lldb_private::g_dynamic_value_types[] = { +static constexpr OptionEnumValueElement g_dynamic_value_types[] = { {eNoDynamicValues, "no-dynamic-values", "Don't calculate the dynamic type of values"}, {eDynamicCanRunTarget, "run-target", "Calculate the dynamic type of values " "even if you have to run the target."}, {eDynamicDontRunTarget, "no-run-target", - "Calculate the dynamic type of values, but don't run the target."}, - {0, nullptr, nullptr}}; + "Calculate the dynamic type of values, but don't run the target."} }; -static OptionEnumValueElement g_inline_breakpoint_enums[] = { +OptionEnumValues lldb_private::GetDynamicValueTypes() { + return OptionEnumValues(g_dynamic_value_types); +} + +static constexpr OptionEnumValueElement g_inline_breakpoint_enums[] = { {eInlineBreakpointsNever, "never", "Never look for inline breakpoint " "locations (fastest). This setting " "should only be used if you know that " @@ -3145,8 +3148,7 @@ "files (default)."}, {eInlineBreakpointsAlways, "always", "Always look for inline breakpoint locations when setting file and line " - "breakpoints (slower but most accurate)."}, - {0, nullptr, nullptr}}; + "breakpoints (slower but most accurate)."} }; typedef enum x86DisassemblyFlavor { eX86DisFlavorDefault, @@ -3154,36 +3156,33 @@ eX86DisFlavorATT } x86DisassemblyFlavor; -static OptionEnumValueElement g_x86_dis_flavor_value_types[] = { +static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = { {eX86DisFlavorDefault, "default", "Disassembler default (currently att)."}, {eX86DisFlavorIntel, "intel", "Intel disassembler flavor."}, - {eX86DisFlavorATT, "att", "AT&T disassembler flavor."}, - {0, nullptr, nullptr}}; + {eX86DisFlavorATT, "att", "AT&T disassembler flavor."} }; -static OptionEnumValueElement g_hex_immediate_style_values[] = { +static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = { {Disassembler::eHexStyleC, "c", "C-style (0xffff)."}, - {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."}, - {0, nullptr, nullptr}}; + {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."} }; -static OptionEnumValueElement g_load_script_from_sym_file_values[] = { +static constexpr OptionEnumValueElement g_load_script_from_sym_file_values[] = { {eLoadScriptFromSymFileTrue, "true", "Load debug scripts inside symbol files"}, {eLoadScriptFromSymFileFalse, "false", "Do not load debug scripts inside symbol files."}, {eLoadScriptFromSymFileWarn, "warn", - "Warn about debug scripts inside symbol files but do not load them."}, - {0, nullptr, nullptr}}; + "Warn about debug scripts inside symbol files but do not load them."} }; -static OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = { +static constexpr +OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = { {eLoadCWDlldbinitTrue, "true", "Load .lldbinit files from current directory"}, {eLoadCWDlldbinitFalse, "false", "Do not load .lldbinit files from current directory"}, {eLoadCWDlldbinitWarn, "warn", - "Warn about loading .lldbinit files from current directory"}, - {0, nullptr, nullptr}}; + "Warn about loading .lldbinit files from current directory"} }; -static OptionEnumValueElement g_memory_module_load_level_values[] = { +static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = { {eMemoryModuleLoadLevelMinimal, "minimal", "Load minimal information when loading modules from memory. Currently " "this setting loads sections only."}, @@ -3192,28 +3191,27 @@ "this setting loads sections and function bounds."}, {eMemoryModuleLoadLevelComplete, "complete", "Load complete information when loading modules from memory. Currently " - "this setting loads sections and all symbols."}, - {0, nullptr, nullptr}}; + "this setting loads sections and all symbols."} }; -static PropertyDefinition g_properties[] = { - {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, nullptr, +static constexpr PropertyDefinition g_properties[] = { + {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, {}, "Default architecture to choose, when there's a choice."}, {"move-to-nearest-code", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Move breakpoints to nearest code."}, + {}, "Move breakpoints to nearest code."}, {"language", OptionValue::eTypeLanguage, false, eLanguageTypeUnknown, - nullptr, nullptr, + nullptr, {}, "The language to use when interpreting expressions entered in commands."}, - {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr, + {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, "Path to a file containing expressions to be prepended to all " "expressions."}, {"prefer-dynamic-value", OptionValue::eTypeEnum, false, - eDynamicDontRunTarget, nullptr, g_dynamic_value_types, + eDynamicDontRunTarget, nullptr, OptionEnumValues(g_dynamic_value_types), "Should printed values be shown as their dynamic value."}, {"enable-synthetic-value", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Should synthetic values be used by default whenever available."}, - {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + {}, "Should synthetic values be used by default whenever available."}, + {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, {}, "Skip function prologues when setting breakpoints by name."}, - {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, nullptr, + {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, {}, "Source path remappings are used to track the change of location between " "a source file when built, and " "where it exists on the current system. It consists of an array of " @@ -3225,66 +3223,67 @@ "Each element of the array is checked in order and the first one that " "results in a match wins."}, {"exec-search-paths", OptionValue::eTypeFileSpecList, false, 0, nullptr, - nullptr, "Executable search paths to use when locating executable files " - "whose paths don't match the local file system."}, + {}, "Executable search paths to use when locating executable files " + "whose paths don't match the local file system."}, {"debug-file-search-paths", OptionValue::eTypeFileSpecList, false, 0, - nullptr, nullptr, + nullptr, {}, "List of directories to be searched when locating debug symbol files."}, {"clang-module-search-paths", OptionValue::eTypeFileSpecList, false, 0, - nullptr, nullptr, + nullptr, {}, "List of directories to be searched when locating modules for Clang."}, {"auto-import-clang-modules", OptionValue::eTypeBoolean, false, true, - nullptr, nullptr, + nullptr, {}, "Automatically load Clang modules referred to by the program."}, {"auto-apply-fixits", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Automatically apply fix-it hints to expressions."}, + {}, "Automatically apply fix-it hints to expressions."}, {"notify-about-fixits", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Print the fixed expression text."}, + {}, "Print the fixed expression text."}, {"save-jit-objects", OptionValue::eTypeBoolean, false, false, nullptr, - nullptr, "Save intermediate object files generated by the LLVM JIT"}, + {}, "Save intermediate object files generated by the LLVM JIT"}, {"max-children-count", OptionValue::eTypeSInt64, false, 256, nullptr, - nullptr, "Maximum number of children to expand in any level of depth."}, + {}, "Maximum number of children to expand in any level of depth."}, {"max-string-summary-length", OptionValue::eTypeSInt64, false, 1024, - nullptr, nullptr, + nullptr, {}, "Maximum number of characters to show when using %s in summary strings."}, {"max-memory-read-size", OptionValue::eTypeSInt64, false, 1024, nullptr, - nullptr, "Maximum number of bytes that 'memory read' will fetch before " - "--force must be specified."}, + {}, "Maximum number of bytes that 'memory read' will fetch before " + "--force must be specified."}, {"breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean, false, - true, nullptr, nullptr, "Consult the platform module avoid list when " - "setting non-module specific breakpoints."}, - {"arg0", OptionValue::eTypeString, false, 0, nullptr, nullptr, + true, nullptr, {}, "Consult the platform module avoid list when " + "setting non-module specific breakpoints."}, + {"arg0", OptionValue::eTypeString, false, 0, nullptr, {}, "The first argument passed to the program in the argument array which can " "be different from the executable itself."}, - {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, nullptr, + {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, {}, "A list containing all the arguments to be passed to the executable when " "it is run. Note that this does NOT include the argv[0] which is in " "target.arg0."}, {"env-vars", OptionValue::eTypeDictionary, false, OptionValue::eTypeString, - nullptr, nullptr, "A list of all the environment variables to be passed " - "to the executable's environment, and their values."}, - {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + nullptr, {}, "A list of all the environment variables to be passed " + "to the executable's environment, and their values."}, + {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, {}, "Inherit the environment from the process that is running LLDB."}, - {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr, + {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, "The file/path to be used by the executable program for reading its " "standard input."}, - {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr, + {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, "The file/path to be used by the executable program for writing its " "standard output."}, - {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr, + {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, "The file/path to be used by the executable program for writing its " "standard error."}, {"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "debugserver will detach (rather than killing) a process if it " + {}, "debugserver will detach (rather than killing) a process if it " "loses connection with lldb."}, - {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, {}, "Enable loading of symbol tables before they are needed."}, - {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, {}, "Disable Address Space Layout Randomization (ASLR)"}, - {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr, + {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, {}, "Disable stdin/stdout for process (e.g. for a GUI application)"}, {"inline-breakpoint-strategy", OptionValue::eTypeEnum, false, - eInlineBreakpointsAlways, nullptr, g_inline_breakpoint_enums, + eInlineBreakpointsAlways, nullptr, + OptionEnumValues(g_inline_breakpoint_enums), "The strategy to use when settings breakpoints by file and line. " "Breakpoint locations can end up being inlined by the compiler, so that a " "compile unit 'a.c' might contain an inlined function from another source " @@ -3304,25 +3303,29 @@ // FIXME: This is the wrong way to do per-architecture settings, but we // don't have a general per architecture settings system in place yet. {"x86-disassembly-flavor", OptionValue::eTypeEnum, false, - eX86DisFlavorDefault, nullptr, g_x86_dis_flavor_value_types, + eX86DisFlavorDefault, nullptr, + OptionEnumValues(g_x86_dis_flavor_value_types), "The default disassembly flavor to use for x86 or x86-64 targets."}, {"use-hex-immediates", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Show immediates in disassembly as hexadecimal."}, + {}, "Show immediates in disassembly as hexadecimal."}, {"hex-immediate-style", OptionValue::eTypeEnum, false, - Disassembler::eHexStyleC, nullptr, g_hex_immediate_style_values, + Disassembler::eHexStyleC, nullptr, + OptionEnumValues(g_hex_immediate_style_values), "Which style to use for printing hexadecimal disassembly values."}, {"use-fast-stepping", OptionValue::eTypeBoolean, false, true, nullptr, - nullptr, "Use a fast stepping algorithm based on running from branch to " - "branch rather than instruction single-stepping."}, + {}, "Use a fast stepping algorithm based on running from branch to " + "branch rather than instruction single-stepping."}, {"load-script-from-symbol-file", OptionValue::eTypeEnum, false, - eLoadScriptFromSymFileWarn, nullptr, g_load_script_from_sym_file_values, + eLoadScriptFromSymFileWarn, nullptr, + OptionEnumValues(g_load_script_from_sym_file_values), "Allow LLDB to load scripting resources embedded in symbol files when " "available."}, {"load-cwd-lldbinit", OptionValue::eTypeEnum, false, eLoadCWDlldbinitWarn, - nullptr, g_load_current_working_dir_lldbinit_values, + nullptr, OptionEnumValues(g_load_current_working_dir_lldbinit_values), "Allow LLDB to .lldbinit files from the current directory automatically."}, {"memory-module-load-level", OptionValue::eTypeEnum, false, - eMemoryModuleLoadLevelComplete, nullptr, g_memory_module_load_level_values, + eMemoryModuleLoadLevelComplete, nullptr, + OptionEnumValues(g_memory_module_load_level_values), "Loading modules from memory can be slow as reading the symbol tables and " "other data can take a long time depending on your connection to the " "debug target. " @@ -3338,20 +3341,18 @@ "symbols, but should rarely be used as stack frames in these memory " "regions will be inaccurate and not provide any context (fastest). "}, {"display-expression-in-crashlogs", OptionValue::eTypeBoolean, false, false, - nullptr, nullptr, "Expressions that crash will show up in crash logs if " - "the host system supports executable specific crash log " - "strings and this setting is set to true."}, + nullptr, {}, "Expressions that crash will show up in crash logs if " + "the host system supports executable specific crash log " + "strings and this setting is set to true."}, {"trap-handler-names", OptionValue::eTypeArray, true, - OptionValue::eTypeString, nullptr, nullptr, + OptionValue::eTypeString, nullptr, {}, "A list of trap handler function names, e.g. a common Unix user process " "one is _sigtramp."}, {"display-runtime-support-values", OptionValue::eTypeBoolean, false, false, - nullptr, nullptr, "If true, LLDB will show variables that are meant to " - "support the operation of a language's runtime " - "support."}, - {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, nullptr, - "Disable lock-step debugging, instead control threads independently."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + nullptr, {}, "If true, LLDB will show variables that are meant to " + "support the operation of a language's runtime support."}, + {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, {}, + "Disable lock-step debugging, instead control threads independently."}}; enum { ePropertyDefaultArch, @@ -3473,16 +3474,15 @@ //---------------------------------------------------------------------- // TargetProperties //---------------------------------------------------------------------- -static PropertyDefinition g_experimental_properties[]{ +static constexpr PropertyDefinition g_experimental_properties[]{ {"inject-local-vars", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, + {}, "If true, inject local variables explicitly into the expression text. " "This will fix symbol resolution when there are name collisions between " "ivars and local variables. " "But it can make expressions run much more slowly."}, {"use-modern-type-lookup", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "If true, use Clang's modern type lookup infrastructure."}, - {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; + {}, "If true, use Clang's modern type lookup infrastructure."}}; enum { ePropertyInjectLocalVars = 0, ePropertyUseModernTypeLookup }; Index: source/Target/Thread.cpp =================================================================== --- source/Target/Thread.cpp +++ source/Target/Thread.cpp @@ -64,30 +64,31 @@ return *g_settings_sp_ptr; } -static PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr, - nullptr, + {}, "If true, step-in will not stop in functions with no debug information."}, {"step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "If true, when step-in/step-out/step-over leave the current " - "frame, they will continue to step out till they come to a " - "function with " - "debug information. Passing a frame argument to step-out will " - "override this option."}, - {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", nullptr, + {}, "If true, when step-in/step-out/step-over leave the current frame, " + "they will continue to step out till they come to a function with " + "debug information. Passing a frame argument to step-out will " + "override this option."}, + {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", {}, "A regular expression defining functions step-in won't stop in."}, {"step-avoid-libraries", OptionValue::eTypeFileSpecList, true, 0, nullptr, - nullptr, "A list of libraries that source stepping won't stop in."}, - {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr, + {}, "A list of libraries that source stepping won't stop in."}, + {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, {}, "If true, this thread will single-step and log execution."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; + {"max-backtrace-depth", OptionValue::eTypeUInt64, false, 300000, nullptr, + {}, "Maximum number of frames to backtrace."}}; enum { ePropertyStepInAvoidsNoDebug, ePropertyStepOutAvoidsNoDebug, ePropertyStepAvoidRegex, ePropertyStepAvoidLibraries, - ePropertyEnableThreadTrace + ePropertyEnableThreadTrace, + ePropertyMaxBacktraceDepth }; class ThreadOptionValueProperties : public OptionValueProperties { @@ -165,6 +166,12 @@ nullptr, idx, g_properties[idx].default_uint_value != 0); } +uint64_t ThreadProperties::GetMaxBacktraceDepth() const { + const uint32_t idx = ePropertyMaxBacktraceDepth; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + //------------------------------------------------------------------ // Thread Event Data //------------------------------------------------------------------ Index: tools/lldb-vscode/VSCode.cpp =================================================================== --- tools/lldb-vscode/VSCode.cpp +++ tools/lldb-vscode/VSCode.cpp @@ -14,6 +14,11 @@ #include "VSCode.h" #include "LLDBUtils.h" +#if defined(_WIN32) +#include +#include +#endif + using namespace lldb_vscode; namespace { @@ -39,6 +44,10 @@ focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false), stop_at_entry(false) { const char *log_file_path = getenv("LLDBVSCODE_LOG"); +#if defined(_WIN32) + assert(_setmode(fileno(stdout), _O_BINARY)); + assert(_setmode(fileno(stdin), _O_BINARY)); +#endif if (log_file_path) log.reset(new std::ofstream(log_file_path)); } Index: unittests/Host/CMakeLists.txt =================================================================== --- unittests/Host/CMakeLists.txt +++ unittests/Host/CMakeLists.txt @@ -3,6 +3,7 @@ HostInfoTest.cpp HostTest.cpp MainLoopTest.cpp + NativeProcessProtocolTest.cpp SocketAddressTest.cpp SocketTest.cpp SymbolsTest.cpp @@ -22,4 +23,5 @@ lldbCore lldbHost lldbUtilityHelpers + LLVMTestingSupport ) Index: unittests/Host/NativeProcessProtocolTest.cpp =================================================================== --- /dev/null +++ unittests/Host/NativeProcessProtocolTest.cpp @@ -0,0 +1,221 @@ +//===-- NativeProcessProtocolTest.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "llvm/Testing/Support/Error.h" +#include "gmock/gmock.h" + +using namespace lldb_private; +using namespace lldb; +using namespace testing; + +namespace { +class MockDelegate : public NativeProcessProtocol::NativeDelegate { +public: + MOCK_METHOD1(InitializeDelegate, void(NativeProcessProtocol *Process)); + MOCK_METHOD2(ProcessStateChanged, + void(NativeProcessProtocol *Process, StateType State)); + MOCK_METHOD1(DidExec, void(NativeProcessProtocol *Process)); +}; + +class MockProcess : public NativeProcessProtocol { +public: + MockProcess(NativeDelegate &Delegate, const ArchSpec &Arch, + lldb::pid_t Pid = 1) + : NativeProcessProtocol(Pid, -1, Delegate), Arch(Arch) {} + + MOCK_METHOD1(Resume, Status(const ResumeActionList &ResumeActions)); + MOCK_METHOD0(Halt, Status()); + MOCK_METHOD0(Detach, Status()); + MOCK_METHOD1(Signal, Status(int Signo)); + MOCK_METHOD0(Kill, Status()); + MOCK_METHOD3(AllocateMemory, + Status(size_t Size, uint32_t Permissions, addr_t &Addr)); + MOCK_METHOD1(DeallocateMemory, Status(addr_t Addr)); + MOCK_METHOD0(GetSharedLibraryInfoAddress, addr_t()); + MOCK_METHOD0(UpdateThreads, size_t()); + MOCK_CONST_METHOD0(GetAuxvData, + llvm::ErrorOr>()); + MOCK_METHOD2(GetLoadedModuleFileSpec, + Status(const char *ModulePath, FileSpec &Spec)); + MOCK_METHOD2(GetFileLoadAddress, + Status(const llvm::StringRef &FileName, addr_t &Addr)); + + const ArchSpec &GetArchitecture() const override { return Arch; } + Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size, + bool Hardware) override { + if (Hardware) + return SetHardwareBreakpoint(Addr, Size); + else + return SetSoftwareBreakpoint(Addr, Size); + } + + // Redirect base class Read/Write Memory methods to functions whose signatures + // are more mock-friendly. + Status ReadMemory(addr_t Addr, void *Buf, size_t Size, + size_t &BytesRead) override; + Status WriteMemory(addr_t Addr, const void *Buf, size_t Size, + size_t &BytesWritten) override; + + MOCK_METHOD2(ReadMemory, + llvm::Expected>(addr_t Addr, size_t Size)); + MOCK_METHOD2(WriteMemory, + llvm::Expected(addr_t Addr, + llvm::ArrayRef Data)); + + using NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode; + llvm::Expected> ReadMemoryWithoutTrap(addr_t Addr, + size_t Size); + +private: + ArchSpec Arch; +}; + +class FakeMemory { +public: + FakeMemory(llvm::ArrayRef Data) : Data(Data) {} + llvm::Expected> Read(addr_t Addr, size_t Size); + llvm::Expected Write(addr_t Addr, llvm::ArrayRef Chunk); + +private: + std::vector Data; +}; +} // namespace + +Status MockProcess::ReadMemory(addr_t Addr, void *Buf, size_t Size, + size_t &BytesRead) { + auto ExpectedMemory = ReadMemory(Addr, Size); + if (!ExpectedMemory) { + BytesRead = 0; + return Status(ExpectedMemory.takeError()); + } + BytesRead = ExpectedMemory->size(); + assert(BytesRead <= Size); + std::memcpy(Buf, ExpectedMemory->data(), BytesRead); + return Status(); +} + +Status MockProcess::WriteMemory(addr_t Addr, const void *Buf, size_t Size, + size_t &BytesWritten) { + auto ExpectedBytes = WriteMemory( + Addr, llvm::makeArrayRef(static_cast(Buf), Size)); + if (!ExpectedBytes) { + BytesWritten = 0; + return Status(ExpectedBytes.takeError()); + } + BytesWritten = *ExpectedBytes; + return Status(); +} + +llvm::Expected> +MockProcess::ReadMemoryWithoutTrap(addr_t Addr, size_t Size) { + std::vector Data(Size, 0); + size_t BytesRead; + Status ST = NativeProcessProtocol::ReadMemoryWithoutTrap( + Addr, Data.data(), Data.size(), BytesRead); + if (ST.Fail()) + return ST.ToError(); + Data.resize(BytesRead); + return std::move(Data); +} + +llvm::Expected> FakeMemory::Read(addr_t Addr, + size_t Size) { + if (Addr >= Data.size()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Address out of range."); + Size = std::min(Size, Data.size() - (size_t)Addr); + return std::vector(&Data[Addr], &Data[Addr + Size]); +} + +llvm::Expected FakeMemory::Write(addr_t Addr, + llvm::ArrayRef Chunk) { + if (Addr >= Data.size()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Address out of range."); + size_t Size = std::min(Chunk.size(), Data.size() - (size_t)Addr); + std::copy_n(Chunk.begin(), Size, &Data[Addr]); + return Size; +} + +TEST(NativeProcessProtocolTest, SetBreakpoint) { + NiceMock DummyDelegate; + MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); + auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); + InSequence S; + EXPECT_CALL(Process, ReadMemory(0x47, 1)) + .WillOnce(Return(ByMove(std::vector{0xbb}))); + EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1))); + EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap))); + EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), + llvm::Succeeded()); +} + +TEST(NativeProcessProtocolTest, SetBreakpointFailRead) { + NiceMock DummyDelegate; + MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); + EXPECT_CALL(Process, ReadMemory(0x47, 1)) + .WillOnce(Return(ByMove( + llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); + EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), + llvm::Failed()); +} + +TEST(NativeProcessProtocolTest, SetBreakpointFailWrite) { + NiceMock DummyDelegate; + MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); + auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); + InSequence S; + EXPECT_CALL(Process, ReadMemory(0x47, 1)) + .WillOnce(Return(ByMove(std::vector{0xbb}))); + EXPECT_CALL(Process, WriteMemory(0x47, Trap)) + .WillOnce(Return(ByMove( + llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); + EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), + llvm::Failed()); +} + +TEST(NativeProcessProtocolTest, SetBreakpointFailVerify) { + NiceMock DummyDelegate; + MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); + auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); + InSequence S; + EXPECT_CALL(Process, ReadMemory(0x47, 1)) + .WillOnce(Return(ByMove(std::vector{0xbb}))); + EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1))); + EXPECT_CALL(Process, ReadMemory(0x47, 1)) + .WillOnce(Return(ByMove( + llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); + EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), + llvm::Failed()); +} + +TEST(NativeProcessProtocolTest, ReadMemoryWithoutTrap) { + NiceMock DummyDelegate; + MockProcess Process(DummyDelegate, ArchSpec("aarch64-pc-linux")); + FakeMemory M{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; + EXPECT_CALL(Process, ReadMemory(_, _)) + .WillRepeatedly(Invoke(&M, &FakeMemory::Read)); + EXPECT_CALL(Process, WriteMemory(_, _)) + .WillRepeatedly(Invoke(&M, &FakeMemory::Write)); + + EXPECT_THAT_ERROR(Process.SetBreakpoint(0x4, 0, false).ToError(), + llvm::Succeeded()); + EXPECT_THAT_EXPECTED( + Process.ReadMemoryWithoutTrap(0, 10), + llvm::HasValue(std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(0, 6), + llvm::HasValue(std::vector{0, 1, 2, 3, 4, 5})); + EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 4), + llvm::HasValue(std::vector{6, 7, 8, 9})); + EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 2), + llvm::HasValue(std::vector{6, 7})); + EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(4, 2), + llvm::HasValue(std::vector{4, 5})); +}