Skip to content

Commit 99679a1

Browse files
authored
Merge pull request #5459 from Michael137/bugfix/break-on-templates-by-basename-to-20220421
[cherry-pick][stable/20220421] [lldb][Breakpoint] Fix setting breakpoints on templates by basename
2 parents 149f529 + 30f4901 commit 99679a1

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,21 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
268268
return res;
269269
}
270270

271+
llvm::StringRef
272+
CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
273+
llvm::StringRef basename = GetBasename();
274+
size_t arg_start, arg_end;
275+
llvm::StringRef parens("<>", 2);
276+
if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end))
277+
return basename.substr(0, arg_start);
278+
279+
return basename;
280+
}
281+
271282
bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
272283
if (!m_parsed)
273284
Parse();
285+
274286
// If we can't parse the incoming name, then just check that it contains path.
275287
if (m_parse_error)
276288
return m_full.GetStringRef().contains(path);
@@ -285,8 +297,23 @@ bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
285297
if (!success)
286298
return m_full.GetStringRef().contains(path);
287299

288-
if (identifier != GetBasename())
300+
// Basename may include template arguments.
301+
// E.g.,
302+
// GetBaseName(): func<int>
303+
// identifier : func
304+
//
305+
// ...but we still want to account for identifiers with template parameter
306+
// lists, e.g., when users set breakpoints on template specializations.
307+
//
308+
// E.g.,
309+
// GetBaseName(): func<uint32_t>
310+
// identifier : func<int32_t*>
311+
//
312+
// Try to match the basename with or without template parameters.
313+
if (GetBasename() != identifier &&
314+
GetBasenameNoTemplateParameters() != identifier)
289315
return false;
316+
290317
// Incoming path only had an identifier, so we match.
291318
if (context.empty())
292319
return true;

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ class CPlusPlusLanguage : public Language {
5858

5959
bool ContainsPath(llvm::StringRef path);
6060

61+
private:
62+
/// Returns the Basename of this method without a template parameter
63+
/// list, if any.
64+
///
65+
// Examples:
66+
//
67+
// +--------------------------------+---------+
68+
// | MethodName | Returns |
69+
// +--------------------------------+---------+
70+
// | void func() | func |
71+
// | void func<int>() | func |
72+
// | void func<std::vector<int>>() | func |
73+
// +--------------------------------+---------+
74+
llvm::StringRef GetBasenameNoTemplateParameters();
75+
6176
protected:
6277
void Parse();
6378
bool TrySimplifiedParse();

lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,12 @@ TEST(CPlusPlusLanguage, ContainsPath) {
228228
CPlusPlusLanguage::MethodName reference_3(ConstString("int func01()"));
229229
CPlusPlusLanguage::MethodName
230230
reference_4(ConstString("bar::baz::operator bool()"));
231-
231+
CPlusPlusLanguage::MethodName reference_5(
232+
ConstString("bar::baz::operator bool<int, Type<double>>()"));
233+
CPlusPlusLanguage::MethodName reference_6(ConstString(
234+
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
235+
236+
EXPECT_TRUE(reference_1.ContainsPath(""));
232237
EXPECT_TRUE(reference_1.ContainsPath("func01"));
233238
EXPECT_TRUE(reference_1.ContainsPath("bar::func01"));
234239
EXPECT_TRUE(reference_1.ContainsPath("foo::bar::func01"));
@@ -238,17 +243,35 @@ TEST(CPlusPlusLanguage, ContainsPath) {
238243
EXPECT_FALSE(reference_1.ContainsPath("::foo::baz::func01"));
239244
EXPECT_FALSE(reference_1.ContainsPath("foo::bar::baz::func01"));
240245

246+
EXPECT_TRUE(reference_2.ContainsPath(""));
241247
EXPECT_TRUE(reference_2.ContainsPath("foofoo::bar::func01"));
242248
EXPECT_FALSE(reference_2.ContainsPath("foo::bar::func01"));
243249

250+
EXPECT_TRUE(reference_3.ContainsPath(""));
244251
EXPECT_TRUE(reference_3.ContainsPath("func01"));
245252
EXPECT_FALSE(reference_3.ContainsPath("func"));
246253
EXPECT_FALSE(reference_3.ContainsPath("bar::func01"));
247254

255+
EXPECT_TRUE(reference_4.ContainsPath(""));
256+
EXPECT_TRUE(reference_4.ContainsPath("operator"));
248257
EXPECT_TRUE(reference_4.ContainsPath("operator bool"));
249258
EXPECT_TRUE(reference_4.ContainsPath("baz::operator bool"));
250259
EXPECT_TRUE(reference_4.ContainsPath("bar::baz::operator bool"));
251260
EXPECT_FALSE(reference_4.ContainsPath("az::operator bool"));
261+
262+
EXPECT_TRUE(reference_5.ContainsPath(""));
263+
EXPECT_TRUE(reference_5.ContainsPath("operator"));
264+
EXPECT_TRUE(reference_5.ContainsPath("operator bool"));
265+
EXPECT_TRUE(reference_5.ContainsPath("operator bool<int, Type<double>>"));
266+
EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, double>"));
267+
EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, Type<int>>"));
268+
269+
EXPECT_TRUE(reference_6.ContainsPath(""));
270+
EXPECT_TRUE(reference_6.ContainsPath("operator"));
271+
EXPECT_TRUE(reference_6.ContainsPath("operator<<"));
272+
EXPECT_TRUE(reference_6.ContainsPath(
273+
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
274+
EXPECT_FALSE(reference_6.ContainsPath("operator<<<Type<double>>"));
252275
}
253276

254277
TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) {

0 commit comments

Comments
 (0)