This is an archive of the discontinued LLVM Phabricator instance.

Make SBValue::GetNonSyntheticValue return really that.
AbandonedPublic

Authored by sivachandra on Jun 19 2015, 3:59 PM.

Details

Summary

Before this change it was only returning itself instead of the real
non-synthetic value.

Diff Detail

Event Timeline

sivachandra retitled this revision from to Make SBValue::GetNonSyntheticValue return really that..
sivachandra updated this object.
sivachandra edited the test plan for this revision. (Show Details)
sivachandra added a reviewer: clayborg.
sivachandra added a subscriber: Unknown Object (MLST).
clayborg requested changes to this revision.Jun 22 2015, 10:32 AM
clayborg edited edge metadata.

So the root shared pointer is always the original untouched value object (non-dynamic and non-synthetic). The ValueImpl sets booleans that allow it to say if it needs to get the dynamic or synthetic values from the untouched root shared pointer. These booleans for dynamic and synthetic are set by current "settings" values. The old SBValue::GetNonSyntheticValue() should be doing the right thing without the need for any changes: it creates a new SBValue that has a untouched root value object and a ValueImpl that says "never fetch the synthetic value" -- the false in the statement below:

ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(),m_opaque_sp->GetUseDynamic(),false));

So I don't think any change is needed. Were you seeing otherwise?

This revision now requires changes to proceed.Jun 22 2015, 10:32 AM

I checked in some code that clears up the ValueImpl::GetSP() a bit so it is easier to read. See:

% svn commit source/API/SBValue.cpp
Sending        source/API/SBValue.cpp
Transmitting file data .
Committed revision 240299.

I have a case where in the ValueObject backing the SBValue (via the ValueImpl) is itself a synthetic value. I hoped to get the non-synthetic version by calling SBValue::GetNonSyntheticValue. Before the proposed change, it was only returning the SBValue made from the backing ValueObject (which was synthetic) and hence was in a way returning itself.

Should this case not happen at all? I am hitting this under the following scenario for a type:

  1. It has synthetic children (implemented via a Python script)
  2. It has a summary (also via a Python script). The summary implementation wants the non-synthetic version (as it wants to call methods like GetChildMemberWithName etc.), but gets the synthetic version because a synthetic children provider is registered.

I will need to check with Enrico Granata when he gets back as I think if what you are saying is true we are going to have more problems. If you can make a failing snippet of code and the python needed to make it fail, please attach it to a comment in here. Enrico is out until Wednesday so it might be a few days.

The following is a small repro case I am using.

C++ source (class.cc):

 1 class CCC
 2 {
 3 public:
 4   int a, b, c;
 5 };
 6 
 7 int
 8 main ()
 9 {
10   CCC obj = { 111, 222, 333 };
11   return 0;
12 }

Python (ccc.py):

 1 import lldb
 2 
 3 def ccc_summary(sbvalue, internal_dict):
 4     sbvalue = sbvalue.GetNonSyntheticValue()
 5     return ("%s, %s, %s" %
 6             (str(sbvalue.GetChildMemberWithName("a")),
 7              str(sbvalue.GetChildMemberWithName("b")),
 8              str(sbvalue.GetChildMemberWithName("c"))))
 9 
10 
11 class CCCSynthProvider(object):
12     def __init__(self, sbvalue, internal_dict):
13         self._sbvalue = sbvalue
14 
15     def num_children(self):
16         return 3
17 
18     def get_child_index(self, name):
19         raise RuntimeError("I don't want to be called!")
20 
21     def get_child_at_index(self, index):
22         if index == 0:
23             return self._sbvalue.GetChildMemberWithName("a")
24         if index == 1:
25             return self._sbvalue.GetChildMemberWithName("b")
26         if index == 2:
27             return self._sbvalue.GetChildMemberWithName("c")
28 
29 
30 cat = lldb.debugger.CreateCategory("my_cat")
31 cat.AddTypeSynthetic(
32     lldb.SBTypeNameSpecifier("CCC"),
33     lldb.SBTypeSynthetic.CreateWithClassName("ccc.CCCSynthProvider",
34                                              lldb.eTypeOptionCascade))
35 cat.AddTypeSummary(
36     lldb.SBTypeNameSpecifier("CCC"),
37     lldb.SBTypeSummary.CreateWithFunctionName("ccc.ccc_summary",
38                                               lldb.eTypeOptionCascade))
39 cat.SetEnabled(True)

Without the proposed change, this is what happens:

(lldb) script import ccc
(lldb) b class.cc :11
Breakpoint 1: where = a.out`main + 25 at class.cc:11, address = 0x0000000000400506
(lldb) r
Process 31046 launched: '/usr/local/google/home/sivachandra/LAB/lldb_scripting/a.out' (x86_64)
Process 31046 stopped
* thread #1: tid = 31046, 0x0000000000400506 a.out`main + 25 at class.cc:11, name = 'a.out', stop reason = breakpoint 1.1
    frame #0: 0x0000000000400506 a.out`main + 25 at class.cc:11
   8   	main ()
   9   	{
   10  	  CCC obj = { 111, 222, 333 };
-> 11  	  return 0;
   12  	}
(lldb) p obj
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
Traceback (most recent call last):
  File "./ccc.py", line 19, in get_child_index
    raise RuntimeError("I don't want to be called!")
RuntimeError: I don't want to be called!
(CCC) $0 = No value, No value, No value {
  a = 111
  b = 222
  c = 333
}

After the proposed change:

(lldb) script import ccc
(lldb) b class.cc :11
Breakpoint 1: where = a.out`main + 25 at class.cc:11, address = 0x0000000000400506
(lldb) r
Process 31412 launched: '/usr/local/google/home/sivachandra/LAB/lldb_scripting/a.out' (x86_64)
Process 31412 stopped
* thread #1: tid = 31412, 0x0000000000400506 a.out`main + 25 at class.cc:11, name = 'a.out', stop reason = breakpoint 1.1
    frame #0: 0x0000000000400506 a.out`main + 25 at class.cc:11
   8   	main ()
   9   	{
   10  	  CCC obj = { 111, 222, 333 };
-> 11  	  return 0;
   12  	}
(lldb) p obj
(CCC) $0 = (int) a = 111, (int) b = 222, (int) c = 333 {
  a = 111
  b = 222
  c = 333
}

For the record, I put a patch which solves the problem I describe here in a different way: http://reviews.llvm.org/D10624

With my understanding of the code base, I am inclined to think that both solutions should be present (though only one of them is sufficient to solve the problem I am hitting).

Thanks for the examples. I will have Enrico look into this when he gets back tomorrow.

sivachandra abandoned this revision.Jun 24 2015, 6:09 PM