This adds support for using const static integral data members as described by C++11 [class.static.data]p3
to LLDB's expression evaluator.
So far LLDB treated these data members are normal static variables. They already work as intended when they are declared in the class definition and then defined in a namespace scope. However, if they are declared and initialised in the class definition but never defined in a namespace scope, all LLDB expressions that use them will fail to link when LLDB can't find the respective symbol for the variable.
The reason for this is that the data members which are only declared in the class are not emitted into any object file so LLDB can never resolve them. Expressions that use these variables are expected to directly use their constant value if possible. Clang can do this for us during codegen, but it requires that we add the constant value to the VarDecl we generate for these data members.
This patch implements this by:
- parsing the constant values from the debug info and adding it to variable declarations we encounter.
- ensuring that LLDB doesn't implicitly try to take the address of expressions that might be an lvalue that points to such a special data member.
The second change is caused by LLDB's way of storing lvalues in the expression parser. When LLDB parses an expression, it tries to keep the result around via two mechanisms:
- For lvalues, LLDB generates a static pointer variable and stores the address of the last expression in it: T *$__lldb_expr_result_ptr = &LastExpression
- For everything else, LLDB generates a static variable of the same type as the last expression and then direct initialises that variable: T $__lldb_expr_result(LastExpression)
If we try to print a special const static data member via something like expr Class::Member, then LLDB will try to take the address of this expression as it's an lvalue. This means LLDB will try to take the address of the variable which causes that Clang can't replace the use with the constant value. There isn't any good way to detect this case (as there a lot of different expressions that could yield an lvalue that points to such a data member), so this patch also changes that we only use the first way of capturing the result if the last expression does not have a type that could potentially indicate it's coming from such a special data member.
This change shouldn't break most workflows for users. The only observable side effect I could find is that the implicit persistent result variables for const int's now have their own memory address:
Before this change:
(lldb) p i (const int) $0 = 123 (lldb) p &$0 (const int *) $1 = 0x00007ffeefbff8e8 (lldb) p &i (const int *) $2 = 0x00007ffeefbff8e8
After this change we capture i by value so it has its own value.
(lldb) p i (const int) $0 = 123 (lldb) p &$0 (const int *) $1 = 0x0000000100155320 (lldb) p &i (const int *) $2 = 0x00007ffeefbff8e8
Should we assert that this is an lvalue?