Skip to content

Commit 46b8527

Browse files
authored
Merge pull request #6727 from bulbazord/5.9-watchpoint-expression-language
Cherry-pick "[lldb] Add support for specifying language when setting watchpoint by expression"
2 parents 749dca4 + 1800e66 commit 46b8527

File tree

9 files changed

+95
-8
lines changed

9 files changed

+95
-8
lines changed

lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class OptionGroupWatchpoint : public OptionGroup {
4343
WatchType watch_type;
4444
uint32_t watch_size;
4545
bool watch_type_specified;
46+
lldb::LanguageType language_type;
4647

4748
private:
4849
OptionGroupWatchpoint(const OptionGroupWatchpoint &) = delete;

lldb/include/lldb/Target/Language.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ class Language : public PluginInterface {
281281
static void PrintAllLanguages(Stream &s, const char *prefix,
282282
const char *suffix);
283283

284+
/// Prints to the specified stream 's' each language type that the
285+
/// current target supports for expression evaluation.
286+
///
287+
/// \param[out] s Stream to which the language types are written.
288+
/// \param[in] prefix String that is prepended to the language type.
289+
/// \param[in] suffix String that is appended to the language type.
290+
static void PrintSupportedLanguagesForExpressions(Stream &s,
291+
llvm::StringRef prefix,
292+
llvm::StringRef suffix);
293+
284294
// return false from callback to stop iterating
285295
static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback);
286296

lldb/source/Commands/CommandObjectExpression.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,15 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
4747
switch (short_option) {
4848
case 'l':
4949
language = Language::GetLanguageTypeFromString(option_arg);
50-
if (language == eLanguageTypeUnknown)
51-
error.SetErrorStringWithFormat(
52-
"unknown language type: '%s' for expression",
53-
option_arg.str().c_str());
50+
if (language == eLanguageTypeUnknown) {
51+
StreamString sstr;
52+
sstr.Printf("unknown language type: '%s' for expression. "
53+
"List of supported languages:\n",
54+
option_arg.str().c_str());
55+
56+
Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n");
57+
error.SetErrorString(sstr.GetString());
58+
}
5459
break;
5560

5661
case 'a': {

lldb/source/Commands/CommandObjectWatchpoint.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,7 @@ corresponding to the byte size of the data type.");
835835
m_arguments.push_back(arg);
836836

837837
// Absorb the '-w' and '-s' options into our option group.
838-
m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
839-
LLDB_OPT_SET_1);
838+
m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1);
840839
m_option_group.Finalize();
841840
}
842841

@@ -990,6 +989,7 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
990989
: CommandObjectRaw(
991990
interpreter, "watchpoint set expression",
992991
"Set a watchpoint on an address by supplying an expression. "
992+
"Use the '-l' option to specify the language of the expression. "
993993
"Use the '-w' option to specify the type of watchpoint and "
994994
"the '-s' option to specify the byte size to watch for. "
995995
"If no '-w' option is specified, it defaults to write. "
@@ -1083,6 +1083,8 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
10831083
options.SetKeepInMemory(false);
10841084
options.SetTryAllThreads(true);
10851085
options.SetTimeout(llvm::None);
1086+
if (m_option_watchpoint.language_type != eLanguageTypeUnknown)
1087+
options.SetLanguage(m_option_watchpoint.language_type);
10861088

10871089
ExpressionResults expr_result =
10881090
target->EvaluateExpression(expr, frame, valobj_sp, options);

lldb/source/Interpreter/OptionGroupWatchpoint.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "lldb/Host/OptionParser.h"
1212
#include "lldb/Interpreter/OptionArgParser.h"
13+
#include "lldb/Target/Language.h"
1314
#include "lldb/lldb-enumerations.h"
1415

1516
using namespace lldb;
@@ -62,7 +63,17 @@ static constexpr OptionDefinition g_option_table[] = {
6263
"Specify the type of watching to perform."},
6364
{LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument,
6465
nullptr, OptionEnumValues(g_watch_size), 0, eArgTypeByteSize,
65-
"Number of bytes to use to watch a region."}};
66+
"Number of bytes to use to watch a region."},
67+
{LLDB_OPT_SET_2,
68+
false,
69+
"language",
70+
'l',
71+
OptionParser::eRequiredArgument,
72+
nullptr,
73+
{},
74+
0,
75+
eArgTypeLanguage,
76+
"Language of expression to run"}};
6677

6778
bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) {
6879
for (const auto& size : g_watch_size) {
@@ -81,6 +92,18 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
8192
Status error;
8293
const int short_option = g_option_table[option_idx].short_option;
8394
switch (short_option) {
95+
case 'l': {
96+
language_type = Language::GetLanguageTypeFromString(option_arg);
97+
if (language_type == eLanguageTypeUnknown) {
98+
StreamString sstr;
99+
sstr.Printf("Unknown language type: '%s' for expression. List of "
100+
"supported languages:\n",
101+
option_arg.str().c_str());
102+
Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n");
103+
error.SetErrorString(sstr.GetString());
104+
}
105+
break;
106+
}
84107
case 'w': {
85108
WatchType tmp_watch_type;
86109
tmp_watch_type = (WatchType)OptionArgParser::ToOptionEnum(
@@ -108,6 +131,7 @@ void OptionGroupWatchpoint::OptionParsingStarting(
108131
watch_type_specified = false;
109132
watch_type = eWatchInvalid;
110133
watch_size = 0;
134+
language_type = eLanguageTypeUnknown;
111135
}
112136

113137
llvm::ArrayRef<OptionDefinition> OptionGroupWatchpoint::GetDefinitions() {

lldb/source/Target/Language.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ const char *Language::GetNameForLanguageType(LanguageType language) {
236236
return language_names[eLanguageTypeUnknown].name;
237237
}
238238

239+
void Language::PrintSupportedLanguagesForExpressions(Stream &s,
240+
llvm::StringRef prefix,
241+
llvm::StringRef suffix) {
242+
auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions();
243+
for (size_t idx = 0; idx < num_languages; ++idx) {
244+
auto const &lang = language_names[idx];
245+
if (supported[lang.type])
246+
s << prefix << lang.name << suffix;
247+
}
248+
}
249+
239250
void Language::PrintAllLanguages(Stream &s, const char *prefix,
240251
const char *suffix) {
241252
for (uint32_t i = 1; i < num_languages; i++) {

lldb/test/API/commands/expression/invalid-args/TestInvalidArgsExpression.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ class InvalidArgsExpressionTestCase(TestBase):
77
@no_debug_info_test
88
def test_invalid_lang(self):
99
self.expect("expression -l foo --", error=True,
10-
substrs=["error: unknown language type: 'foo' for expression"])
10+
substrs=["error: unknown language type: 'foo' for expression",
11+
"List of supported languages:",
12+
"c++", "c++11", "c++14"])
1113

1214
@no_debug_info_test
1315
def test_invalid_all_thread(self):
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# UNSUPPORTED: system-windows
2+
# RUN: %clangxx_host %p/Inputs/languages.cpp -g -o %t.out
3+
# RUN: %lldb -b -o 'settings set interpreter.stop-command-source-on-error false' -s %s %t.out 2>&1 | FileCheck %s
4+
5+
settings show interpreter.stop-command-source-on-error
6+
# CHECK: interpreter.stop-command-source-on-error (boolean) = false
7+
8+
b main
9+
run
10+
# CHECK: stopped
11+
# CHECK-NEXT: stop reason = breakpoint
12+
13+
watchpoint set expression -- &g_foo
14+
# CHECK: Watchpoint created:
15+
16+
watchpoint set expression -l c++ -- &g_bar
17+
# CHECK: Watchpoint created:
18+
19+
watchpoint set expression -l fake -- &g_baz
20+
# CHECK: Unknown language type: 'fake' for expression. List of supported languages:
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <cstdint>
2+
#include <iostream>
3+
4+
uint64_t g_foo = 5;
5+
uint64_t g_bar = 6;
6+
uint64_t g_baz = 7;
7+
8+
int main() {
9+
int val = 8;
10+
printf("Hello world! %d\n", val);
11+
return 0;
12+
}

0 commit comments

Comments
 (0)