Michi
Michi

Reputation: 1484

Xcode LLDB throws Parse error when printing out property

I'm facing big issues when trying to print out Objective C properties in many situations when I'm almost certainly sure it SHOULD work.

Consider the following setup:

Case setup

The view controller's property has strictly set class (Card *), but still, LLDB outputs an parsing error where subproperty cannot be found on object of type id.

Having an object property defined on a view controller (see points 5 & 6):

  1. stop at breakpoint inside the controller code (f.e. in -viewDidAppear: method)
  2. try to print out the property itself with po _card (points 1 & 2)
  3. try to print out its subproperty with po _card.offlineURL (points 3 & 4)
  4. an LLDB parsing error occurs

Printing out via [_card offlineURL] prints out proper object description as LLDB sends a message to Card object with no class check.

Definition of object property on the controller declares non-id class, though (point 5).

I'm expecting LLDB to print out the property object's subproperty description, NSString containing URL string in this case, but this annoying LLDB error occurs instead.

This is just a single example from many. Sometimes it affects direct property printout, numbers printing etc. These issues are way more frequent since integration of Swift began, being worse with every new version of Xcode since 6.2, including the latest 7.2.

This happens in my Objective C project in many situations, though sometimes it works fine in different cases.

Do you know about any work-arounds or fixes for this issue? I've already filed a report on Apple Bug Reporter, but this will certainly take time for Apple to even notice.

Upvotes: 1

Views: 2040

Answers (1)

Jim Ingham
Jim Ingham

Reputation: 27110

The most likely problem given the info in your question is that we don't actually have debug information for _card.

The lldb command:

(lldb) image lookup -t Card

will tell you whether lldb had debug information for Card available to it. If this doesn't find anything, then maybe some part of your project isn't getting built with debug info. If the command does find some correct definition of Card, then it must be that the debug info for the _card ivar is not getting hooked up to this type correctly.

If there is a definition of Card, then the workaround:

(lldb) po ((Card *) _card).offLineURL

is available.

For future reference, there are two other bits of behavior that are probably complicating your attempt to figure out what is going on here:

1) (w.r.t. picture 3) The Xcode IDE uses its built-in indexer for auto completion in the debug window as well as the Source Code editor. But the debugger runs off debug information, since we need to be able to debug things that aren't built in Xcode. So the fact that auto-completion can find a name in an expression doesn't tell you anything about what lldb will do.

2) (w.r.t. picture 2) po force-casts the expression you are trying to "po" to an ObjC object (i.e. "id") and then calls its description method. The description method of an ObjC object that doesn't override description prints the type name and the address. So lldb didn't need to know the type of the _card ivar to get the output you saw. We only start to need types when the expression is more complex and involves accesses to ivars or properties of an ObjC object in the expression.

Note also, by default if you do:

(lldb) print _card

lldb will evaluate the expression "_card", find it resolves to a pointer of at least type id, then follow that pointer's isa pointer into the ObjC runtime to figure out what the dynamic type is. So it is likely to print Card * in this case.

But the expression parser hasn't yet been taught to resolve the dynamic type of sub-expressions within the expression parser in mid-parse. That would actually be quite a trick... So if it doesn't know the full type of _card, then:

(lldb) print _card.offlineURL

isn't going to work, since id does indeed not have a property of that name.

You can work around this by doing:

(lldb) print _card
$0 = (Card *) 0x12345678

Then:

(lldb) print $0.offlineURL

since the result variable captures the full dynamic type information, that will also be available in subsequent expressions.

Upvotes: 1

Related Questions