Display of reference parameters

Hi all,
Consider this code:


void foo(int& x)
{
++x;
// Breakpoint
}

Reference parameter x is shown like this:


(lldb) frame variable
(int &) x = 0x00007fff5fbff5e8 (&x = 33)

Should this perhaps be improved? (I find the “&x = 33” a little confusing)
Some ideas:
A. (int &) x = 0x00007fff5fbff5e8 (*x = 33)
B. (int &) x = 33 (&x = 0x00007fff5fbff5e8)

Cheers,
Johan

The main issue is what do you want to see when things go wrong? It is nice to see what the reference value is. How about:

(int &) x @ 0x00007fff5fbff5e8 = 33

The main issue is we want people to know what is wrong when things go bad:

void foo(int& x)
{
    ++x;
}
int main()
{
  int *int_ptr = nullptr;
  foo(*int_ptr);
  return 0;
}

(lldb)
Process 60095 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100000f78 a.out`foo(x=0x0000000000000000) at main.cpp:3
   1 void foo(int& x)
   2 {
-> 3 ++x;
   4 }
   5 int main()
   6 {
   7 int *int_ptr = nullptr;
(lldb) fr var
(int &) x = 0x0000000000000000

This shows that the reference is clearly bad and is why we currently show the reference value. The current method of display tries to display the truth. If we cover up the reference then when we display things and things work correctly, then we would end up showing it one way, and then how would be display things if they are not correct.

If we add case C where we show "@ <address> = <value>":

Current when reference is valid:

(lldb) frame variable
(int &) x = 0x00007fff5fbff5e8 (&x = 33)
A. (int &) x = 0x00007fff5fbff5e8 (*x = 33)
B. (int &) x = 33 (&x = 0x00007fff5fbff5e8)
C. (int &) x @ 0x00007fff5fbff5e8 = 33

When reference is invalid:

(lldb) frame variable
(int &) x = 0x0000000000000000
A. (int &) x = 0x0000000000000000 (*x = <error>)
B. (int &) x = <reference is invalid> (&x = 0x0000000000000000)
C. (int &) x @ 0x0000000000000000 = <reference is invalid>

It would be a good idea to see what other debuggers do and make sure we use what makes the most sense to people. Also we need to think about what gets shown for references to simple structs/unions/classes (like "struct Point { int x,y; };" and also structs/unions/classes that are have many children as all of those cases differ.

I wouldn't be against switching to "(<type>) <name> @ <ref-addr> = <value>" way of displaying things.

Anyone else want to chime in?

Greg Clayton

Since the address is mostly only interesting "when it goes bad" which should be infrequent, we want to have the value be the easiest thing to pick out. It's a little harder to tell in isolation, what you're really going to see is something like:

A:

(int) y = 33
(int) z = 33
(int &) x = 0x00007fff5fbff5e8 (*x = 33)
(int) a = 33
(int) b = 33

B:

(int) y = 33
(int) z = 33
(int &) x = 33 (&x = 0x00007fff5fbff5e8)
(int) a = 33
(int) b = 33

C:

(int) y = 33
(int) z = 33
(int &) x @ 0x00007fff5fbff5e8 = 33
(int) a = 33
(int) x = 33

I think of these B is the easiest to scan for values. It's easiest not to be distracted by the appended value in that case. A simple (one line) struct would be similar. Not quite as sure what we should do for structures. I'm not sure how to do A nicely. I think B would be okay if you did it like:

(int) y = 33
(int) z = 33
(Array) my_array = {
  size = 10
  head = 0x00007fff5fbff770
} (&my_array = 0x00007fff5fbff5e8)
(int) a = 33
(int) x = 33

But I think C looks nicer in this case:

(int) y = 33
(int) z = 33
(Array) my_array @ 0x00007fff5fbff5e8 = {
  size = 10
  head = 0x00007fff5fbff770
}
(int) a = 33
(int) x = 33

Jim