Skip to content

Commit 30f4901

Browse files
committed
[lldb][Breakpoint] Fix setting breakpoints on templates by basename
This patch fixes a regression with setting breakpoints on template functions by name. E.g.,: ``` $ cat main.cpp template<typename T> struct Foo { template<typename U> void func() {} }; int main() { Foo<int> f; f.func<double>(); } (lldb) br se -n func ``` This has regressed since `3339000e0bda696c2e29173d15958c0a4978a143` where we started using the `CPlusPlusNameParser` for getting the basename of the function symbol and match it exactly against the name in the breakpoint command. The parser will include template parameters in the basename, so the exact match will always fail **Testing** * Added API tests * Added unit-tests Differential Revision: https://reviews.llvm.org/D135921 (cherry picked from commit d4a55ad)
1 parent ed4feed commit 30f4901

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
@@ -143,7 +143,12 @@ TEST(CPlusPlusLanguage, ContainsPath) {
143143
CPlusPlusLanguage::MethodName reference_3(ConstString("int func01()"));
144144
CPlusPlusLanguage::MethodName
145145
reference_4(ConstString("bar::baz::operator bool()"));
146-
146+
CPlusPlusLanguage::MethodName reference_5(
147+
ConstString("bar::baz::operator bool<int, Type<double>>()"));
148+
CPlusPlusLanguage::MethodName reference_6(ConstString(
149+
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
150+
151+
EXPECT_TRUE(reference_1.ContainsPath(""));
147152
EXPECT_TRUE(reference_1.ContainsPath("func01"));
148153
EXPECT_TRUE(reference_1.ContainsPath("bar::func01"));
149154
EXPECT_TRUE(reference_1.ContainsPath("foo::bar::func01"));
@@ -153,17 +158,35 @@ TEST(CPlusPlusLanguage, ContainsPath) {
153158
EXPECT_FALSE(reference_1.ContainsPath("::foo::baz::func01"));
154159
EXPECT_FALSE(reference_1.ContainsPath("foo::bar::baz::func01"));
155160

161+
EXPECT_TRUE(reference_2.ContainsPath(""));
156162
EXPECT_TRUE(reference_2.ContainsPath("foofoo::bar::func01"));
157163
EXPECT_FALSE(reference_2.ContainsPath("foo::bar::func01"));
158164

165+
EXPECT_TRUE(reference_3.ContainsPath(""));
159166
EXPECT_TRUE(reference_3.ContainsPath("func01"));
160167
EXPECT_FALSE(reference_3.ContainsPath("func"));
161168
EXPECT_FALSE(reference_3.ContainsPath("bar::func01"));
162169

170+
EXPECT_TRUE(reference_4.ContainsPath(""));
171+
EXPECT_TRUE(reference_4.ContainsPath("operator"));
163172
EXPECT_TRUE(reference_4.ContainsPath("operator bool"));
164173
EXPECT_TRUE(reference_4.ContainsPath("baz::operator bool"));
165174
EXPECT_TRUE(reference_4.ContainsPath("bar::baz::operator bool"));
166175
EXPECT_FALSE(reference_4.ContainsPath("az::operator bool"));
176+
177+
EXPECT_TRUE(reference_5.ContainsPath(""));
178+
EXPECT_TRUE(reference_5.ContainsPath("operator"));
179+
EXPECT_TRUE(reference_5.ContainsPath("operator bool"));
180+
EXPECT_TRUE(reference_5.ContainsPath("operator bool<int, Type<double>>"));
181+
EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, double>"));
182+
EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, Type<int>>"));
183+
184+
EXPECT_TRUE(reference_6.ContainsPath(""));
185+
EXPECT_TRUE(reference_6.ContainsPath("operator"));
186+
EXPECT_TRUE(reference_6.ContainsPath("operator<<"));
187+
EXPECT_TRUE(reference_6.ContainsPath(
188+
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
189+
EXPECT_FALSE(reference_6.ContainsPath("operator<<<Type<double>>"));
167190
}
168191

169192
TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) {

0 commit comments

Comments
 (0)