@@ -15,6 +15,8 @@ def setUp(self):
1515
1616 self .main_source = "main.cpp"
1717 self .main_source_spec = lldb .SBFileSpec (self .main_source )
18+ self .main_source_diag_path = os .path .join ("diagnostics" , "main.cpp" )
19+ self .header_source_diag_path = os .path .join ("diagnostics" , "lib.h" )
1820
1921 def test_source_and_caret_printing (self ):
2022 """Test that the source and caret positions LLDB prints are correct"""
@@ -113,9 +115,6 @@ def test_source_and_caret_printing(self):
113115 value .GetError ().GetCString (),
114116 )
115117
116- # Declarations from the debug information currently have no debug information. It's not clear what
117- # we should do in this case, but we should at least not print anything that's wrong.
118- # In the future our declarations should have valid source locations.
119118 value = frame .EvaluateExpression ("struct FooBar { double x };" , top_level_opts )
120119 self .assertFalse (value .GetError ().Success ())
121120 self .assertIn (
@@ -140,10 +139,13 @@ def test_source_and_caret_printing(self):
140139 """
141140 1 | foo(1, 2)
142141 | ^~~
143- note: candidate function not viable: requires single argument 'x', but 2 arguments were provided
144142""" ,
145143 value .GetError ().GetCString (),
146144 )
145+ self .assertIn (
146+ "candidate function not viable: requires single argument 'x', but 2 arguments were provided" ,
147+ value .GetError ().GetCString (),
148+ )
147149
148150 # Redefine something that we defined in a user-expression. We should use the previous expression file name
149151 # for the original decl.
@@ -260,3 +262,116 @@ def check_error(diags):
260262 self .assertEqual (err_ty .GetIntegerValue (), lldb .eErrorTypeExpression )
261263 diags = data .GetValueForKey ("errors" ).GetItemAtIndex (0 )
262264 check_error (diags )
265+
266+ def test_source_locations_from_debug_information (self ):
267+ """Test that the source locations from debug information are correct"""
268+ self .build ()
269+
270+ (_ , _ , thread , _ ) = lldbutil .run_to_source_breakpoint (
271+ self , "// Break here" , self .main_source_spec
272+ )
273+
274+ frame = thread .GetFrameAtIndex (0 )
275+
276+ # Test source locations of functions
277+ value = frame .EvaluateExpression ("foo(1, 2)" )
278+ self .assertFalse (value .GetError ().Success ())
279+ error_msg = value .GetError ().GetCString ()
280+ self .assertIn (
281+ """:1:1: no matching function for call to 'foo'
282+ 1 | foo(1, 2)
283+ | ^~~
284+ """ ,
285+ error_msg ,
286+ )
287+
288+ self .assertIn (
289+ """
290+ 1 | void foo() {}
291+ | ^
292+ """ ,
293+ error_msg ,
294+ )
295+
296+ self .assertIn (
297+ """
298+ 2 | void foo(char, char const *x) {}
299+ | ^
300+ """ ,
301+ error_msg ,
302+ )
303+
304+ self .assertIn (
305+ """
306+ 3 | void foo(int x) {}
307+ | ^
308+ """ ,
309+ error_msg ,
310+ )
311+
312+ self .assertIn (f"{ self .header_source_diag_path } :" , error_msg )
313+ self .assertIn (f"{ self .main_source_diag_path } :" , error_msg )
314+
315+ top_level_opts = lldb .SBExpressionOptions ()
316+ top_level_opts .SetTopLevel (True )
317+
318+ # Test source locations of records
319+ value = frame .EvaluateExpression ("struct FooBar { double x; };" , top_level_opts )
320+ self .assertFalse (value .GetError ().Success ())
321+ error_msg = value .GetError ().GetCString ()
322+ self .assertIn (
323+ """:1:8: redefinition of 'FooBar'
324+ 1 | struct FooBar { double x; };
325+ """ ,
326+ error_msg ,
327+ )
328+ self .assertIn (
329+ """previous definition is here
330+ 5 | struct FooBar {
331+ | ^
332+ """ ,
333+ error_msg ,
334+ )
335+ self .assertIn (f"{ self .main_source_diag_path } :" , error_msg )
336+
337+ # Test source locations of enums
338+ value = frame .EvaluateExpression ("enum class EnumInSource {};" , top_level_opts )
339+ self .assertFalse (value .GetError ().Success ())
340+ error_msg = value .GetError ().GetCString ()
341+ self .assertIn (
342+ """previous declaration is here
343+ 9 | enum class EnumInSource { A, B, C };
344+ | ^
345+ """ ,
346+ error_msg ,
347+ )
348+ self .assertIn (f"{ self .main_source_diag_path } :" , error_msg )
349+
350+ @skipIf (
351+ debug_info = no_match ("dsym" ),
352+ bugnumber = "Template function decl can only be found via dsym" ,
353+ )
354+ def test_source_locations_from_debug_information_template_func (self ):
355+ """Test that the source locations from debug information are correct
356+ for template functions"""
357+ self .build ()
358+
359+ (_ , _ , thread , _ ) = lldbutil .run_to_source_breakpoint (
360+ self , "// Break here" , self .main_source_spec
361+ )
362+
363+ frame = thread .GetFrameAtIndex (0 )
364+
365+ # Test source locations of template functions
366+ value = frame .EvaluateExpression ("templateFunc<int>(1)" )
367+ self .assertFalse (value .GetError ().Success ())
368+ error_msg = value .GetError ().GetCString ()
369+ self .assertIn (
370+ """11:1: non-template declaration found by name lookup
371+ 11 | template <typename T> void templateFunc() {}
372+ | ^
373+ """ ,
374+ error_msg ,
375+ )
376+
377+ self .assertIn (f"{ self .main_source_diag_path } :" , error_msg )
0 commit comments