Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 320277

Summary: Cannot view variables of base class in derived class
Product: [Tools] CDT Reporter: Axel Mueller <aegges>
Component: cdt-debug-dsf-gdbAssignee: Marc Khouzam <marc.khouzam>
Status: RESOLVED FIXED QA Contact: Marc Khouzam <marc.khouzam>
Severity: normal    
Priority: P3 CC: marc.khouzam, pawel.1.piech, rstanzel
Version: 7.0   
Target Milestone: 8.0.1   
Hardware: PC   
OS: All   
Whiteboard:
Attachments:
Description Flags
modify output of var-info-path-expression
none
modify output of var-info-path-expression beware of variables that are named after their type
none
Test for GDB's behavior
none
JUnit test for this bug
marc.khouzam: iplog-
More JUnit tests
marc.khouzam: iplog-
modify output of var-info-path-expression beware of variables that are named after their type
none
Minor updates to Axel's last patch
marc.khouzam: iplog-
Update to Marc's patch. Remember if we used the workaround to create are own var-info-expression
none
Fix to JUnit tests
marc.khouzam: iplog-
Remember if we used the workaround to create are own var-info-expression
none
Remember if we used the workaround to create are own var-info-expression
none
Fix based on "Remember if we used the workaround to create are own var-info-expression"
marc.khouzam: iplog-
Updated latest fix to easily turn off
marc.khouzam: iplog-
To check if GDB actually has this bug we call -data-evaluate-expression with the return value of -var-info-path-expression
marc.khouzam: iplog+
Updated Axel's fix that uses -data-evaluate-expression (master)
marc.khouzam: iplog-
Updated Axel's fix that uses -data-evaluate-expression (8_0) marc.khouzam: iplog-

Description Axel Mueller CLA 2010-07-19 11:09:11 EDT
Build Identifier: Version: Helios Release (3.6.0) Build id: 20100527-0614, CDT 7.0

Build the following code and put a breakpoint at the printf command. Then try to inspect this->testbase.aiVal in the variables view.
You will get this:
(((*(testbase*) this)).aiVal)[0]	Error: Unable to create variable object	


Reproducible: Always

Steps to Reproduce:
#include <cstdio>

class testbase {
public:
    testbase(){ aiVal[0] = 1; };
protected:
    int aiVal[5];
};

class test : public testbase {
public:
  test()
  {
    printf("%d", aiVal[0]); 
  }
};


int main(void)
{
    test t;
    return 0;
}

BTW, when you debug the same code with the CDI debug framework you can inspect the variables flawlessly.

This bug might be in relation to #308678
Comment 1 Axel Mueller CLA 2010-08-15 18:15:05 EDT
Created attachment 176645 [details]
modify output of var-info-path-expression

I have changed the bug title to reflect better the problem. It is not possible to show the value of a base class member because the expression returned by gdb via var-info-path-expression is wrong.

var-info-path-expression returns 
(*(testbase*) this)
but for data-evaluate-expression we need
(*(struct testbase*) this)

This was fixed for CDI in bug #304010

My patch will also cover bug #308678 which describes a similar problem with base classes in a namespace.
Comment 2 Axel Mueller CLA 2010-09-08 03:49:13 EDT
Marc,

could you have a look at my patch? I would like to see this included in the fall release. 
Hopefully, it is okay that I added your name to this bug.
Comment 3 Marc Khouzam CLA 2010-09-08 13:01:28 EDT
(In reply to comment #2)
> Marc,
> 
> could you have a look at my patch? I would like to see this included in the
> fall release. 
> Hopefully, it is okay that I added your name to this bug.

As you know by now, a little reminder like this is a good way to get things moving :-)

I had a look at the patch and I was bothered by the technique of using baseClassName.equals(child.getType()) to know if we are dealing with a base class.  I wondered if the name of a variable could be the same as its type.

So I added the line
  testbase testbase;
as a member of the test class.  Things compiled.
Then this member triggered the code of the patch by mistake and I got

Failed to execute MI command:
-data-evaluate-expression "(struct testbase)var2.public"

We'd need some other way to know we are dealing with such a case

Also, two minor comments:
1- I don't think you need to call setData() with the new childFullExpression.
2- The new code should probably be in an else case of 
   if (childFullExpression.length() == 0) { 

I was also thinking that it may be safer to use the result of var-info-path-expression and insert the 'struct' in there instead of creating a 'hard-coded' new full expression ourselves; I haven't quite figured out when this case happens, so maybe that would be unnecessary though.
Comment 4 Axel Mueller CLA 2010-09-08 17:09:26 EDT
(In reply to comment #3)
> As you know by now, a little reminder like this is a good way to get things
> moving :-)
I am learning :)

> I had a look at the patch and I was bothered by the technique of using
> baseClassName.equals(child.getType()) to know if we are dealing with a base
> class.  
Yeah, that looks weird. To be honest, I got this idea from the CDI code in org.eclipse.cdt.debug.mi.core.cdi.model.Variable

> I wondered if the name of a variable could be the same as its type.
> 
> So I added the line
>   testbase testbase;
> as a member of the test class.  Things compiled.
> Then this member triggered the code of the patch by mistake and I got
> 
> Failed to execute MI command:
> -data-evaluate-expression "(struct testbase)var2.public"
> 
> We'd need some other way to know we are dealing with such a case
Patch to follow.

> 
> Also, two minor comments:
> 1- I don't think you need to call setData() with the new childFullExpression.
This is necessary when you have a second level derived class. 
e.g.
class testbase {
    float fBase;
};

class test1 : public testbase {
    float f1;
};

class test2 : public test1 {
public:
  test2()
  {
    printf("%d", aiVal[0]);
  }
};

> 2- The new code should probably be in an else case of 
>    if (childFullExpression.length() == 0) { 
> 
> I was also thinking that it may be safer to use the result of
> var-info-path-expression and insert the 'struct' in there instead of creating a
> 'hard-coded' new full expression ourselves;
Comment 5 Axel Mueller CLA 2010-09-08 17:13:27 EDT
Created attachment 178451 [details]
modify output of var-info-path-expression beware of variables that are named after their type

I modified the patch so variables that name is identical to their type (see comment #3) are excluded from the modification.
Comment 6 Marc Khouzam CLA 2010-09-08 21:05:40 EDT
Created attachment 178470 [details]
Test for GDB's behavior

GDB's bahavior is a little more complicated that it seems.
The attached file is meant to be run directly in GDB command-line and gives a test that allows to cause the problem or not.

It seems that have a constructor or not affects the syntax error.  So, it seems that it is not -var-info-path-expression that has the problem but GDB's variable printing.  Understanding GDB's behavior should help us figure out how to work around it the best way.

I'm going to follow-up with the gdb mailing list after doing a little more debugging.
Comment 7 Axel Mueller CLA 2010-09-09 05:52:51 EDT
(In reply to comment #6)
> Created an attachment (id=178470) [details]
> Test for GDB's behavior
> 
> GDB's bahavior is a little more complicated that it seems.
> The attached file is meant to be run directly in GDB command-line and gives a
> test that allows to cause the problem or not.
> 
> It seems that have a constructor or not affects the syntax error.  So, it seems
> that it is not -var-info-path-expression that has the problem but GDB's
> variable printing.  Understanding GDB's behavior should help us figure out how
> to work around it the best way.
> 
> I'm going to follow-up with the gdb mailing list after doing a little more
> debugging.
-var-info-path-expression does work as expected
from http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html
"For example, suppose C is a C++ class, derived from class Base, and that the Base class has a member called m_size. Assume a variable c is has the type of C and a variable object C was created for variable c. Then, we'll get this output:

     (gdb) -var-info-path-expression C.Base.public.m_size
     ^done,path_expr=((Base)c).m_size)
"

I assume the existence of the constructor in your example influences the vtable. But you may be right that gdb has a printing problem. But should we wait for gdb to fix this or have a workaround in Eclipse?
Comment 8 Marc Khouzam CLA 2010-09-09 06:15:56 EDT
(In reply to comment #7)
 
> I assume the existence of the constructor in your example influences the
> vtable. But you may be right that gdb has a printing problem. But should we
> wait for gdb to fix this or have a workaround in Eclipse?

We'll need a workaround ourselves.  But if we understand what GDB is doing, we can make sure our workaround is complete.  Also, I'd like to get this fixed in GDB.  And finally, we'll need to make sure our workaround does not break things, if/when GDB is fixed.
Comment 9 Axel Mueller CLA 2010-09-09 07:13:02 EDT
(In reply to comment #8)
> (In reply to comment #7)
> 
> > I assume the existence of the constructor in your example influences the
> > vtable. But you may be right that gdb has a printing problem. But should we
> > wait for gdb to fix this or have a workaround in Eclipse?
> 
> We'll need a workaround ourselves.  But if we understand what GDB is doing, we
> can make sure our workaround is complete.  Also, I'd like to get this fixed in
> GDB.  And finally, we'll need to make sure our workaround does not break
> things, if/when GDB is fixed.
Well, that is what I basically meant in my last comment.
Comment 10 Marc Khouzam CLA 2010-09-09 08:34:58 EDT
Created attachment 178509 [details]
JUnit test for this bug

This JUnit test reproduces the bug so we can make sure it is properly fixed.

I committed the test to HEAD.
Comment 12 Marc Khouzam CLA 2010-09-09 11:31:35 EDT
There is already a GDB bug that seems to be the same as what we see here: http://sourceware.org/bugzilla/show_bug.cgi?id=11912

The explanation is that the GDB parser treats the base class name in the expression as its constructor's name instead.  In the example below, in the expression:
((*(testbase*) this)).aiVal)[0]

testbase is mistaken to be the constructor by GDB.

The suggested workaround was to add the keyword 'class' (same as 'struct'), as we are proposing to do in DSF-GDB.
Comment 13 Marc Khouzam CLA 2010-09-09 15:50:43 EDT
(In reply to comment #5)
> Created an attachment (id=178451) [details]
> modify output of var-info-path-expression beware of variables that are named
> after their type
> 
> I modified the patch so variables that name is identical to their type (see
> comment #3) are excluded from the modification.

I still feel un-easy about this solution.
The trick to exclude variables that have the same name as their type does not feel very safe (fullExp != gdbName) relies on our handling of private/public/protected and on their existence.  

What about C programs that don't use those?  I wasn't able to find a counter example, but it seems risky.  I guess we could check for C++ like CDI does.

Also, nested children logic (if (parent != null)) does not quite work.
I added 'int *a;' in testbase and I'm getting errors.  This is because the parent of an expression can be the public/private/protected element, so we would need to go another parent up.

Also for the nested children logic, I'm not convinced that if we have a child, we can always access it using parent.child.  Couldn't there be other cases like ->?
Comment 14 Marc Khouzam CLA 2010-09-09 16:35:33 EDT
Created attachment 178566 [details]
More JUnit tests

Here are more JUnit tests for this bug, which go into more details.  They will help get our solution working.

Committed to HEAD.
Comment 16 Axel Mueller CLA 2010-09-09 18:04:04 EDT
(In reply to comment #13)

> I still feel un-easy about this solution.
> The trick to exclude variables that have the same name as their type does not
> feel very safe (fullExp != gdbName) relies on our handling of
> private/public/protected and on their existence. 
It is a little bit voodoo. But as long as you don't provide a counter case I would say it is safe to use :)
 
> What about C programs that don't use those?  I wasn't able to find a counter
> example, but it seems risky.  I guess we could check for C++ like CDI does.
I as thinking about this, too. But I didn't find any example that could cause problems and I don't know how to check for C++.

> Also, nested children logic (if (parent != null)) does not quite work.
> I added 'int *a;' in testbase and I'm getting errors.  This is because the
> parent of an expression can be the public/private/protected element, so we
> would need to go another parent up.
Hmm, I don't get any errors when adding "int *a" to testbase. However, I am testing the example from comment #0 manually and not your unit test. Both unit tests fail with a time out (the rest of the MIExpressionTests do work).
java.lang.Exception: Timed out waiting for ServiceEvent: org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent
	at org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor.waitForEvent(ServiceEventWaitor.java:87)
	at org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.resumeUntilStopped(SyncUtil.java:317)
	at org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.resumeUntilStopped(SyncUtil.java:326)
	at org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.runToLocation(SyncUtil.java:381)
	at org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.runToLocation(SyncUtil.java:373)
	at org.eclipse.cdt.tests.dsf.gdb.tests.MIExpressionsTest.testBaseChildrenBug(MIExpressionsTest.java:419)


> Also for the nested children logic, I'm not convinced that if we have a child,
> we can always access it using parent.child.  Couldn't there be other cases like
> ->?
I have to think about this. We could check parent.isPointer() and then use -> ?
Comment 17 Marc Khouzam CLA 2010-09-09 19:37:40 EDT
(In reply to comment #16)
> (In reply to comment #13)
> 
> > I still feel un-easy about this solution.
> > The trick to exclude variables that have the same name as their type does not
> > feel very safe (fullExp != gdbName) relies on our handling of
> > private/public/protected and on their existence. 
> It is a little bit voodoo. But as long as you don't provide a counter case I
> would say it is safe to use :)

I might have to accept that one as I don't see another option at this time.

> > What about C programs that don't use those?  I wasn't able to find a counter
> > example, but it seems risky.  I guess we could check for C++ like CDI does.
> I as thinking about this, too. But I didn't find any example that could cause
> problems and I don't know how to check for C++.

To check for C++ we need to start using -var-info-expression.
But I would be ok with delaying this until we find a example that shows we need it.

> > Also, nested children logic (if (parent != null)) does not quite work.
> > I added 'int *a;' in testbase and I'm getting errors.  This is because the
> > parent of an expression can be the public/private/protected element, so we
> > would need to go another parent up.
> Hmm, I don't get any errors when adding "int *a" to testbase. However, I am
> testing the example from comment #0 manually and not your unit test. 

I was able to see this manually by opening down to *a and the selecting it.

> Both unit
> tests fail with a time out (the rest of the MIExpressionTests do work).

Did you update the entire test.dsf.gdb plugin?  You also need the changes from ExpressionTestApp.cc.

> > Also for the nested children logic, I'm not convinced that if we have a child,
> > we can always access it using parent.child.  Couldn't there be other cases like
> > ->?
> I have to think about this. We could check parent.isPointer() and then use -> ?

I'd have to think about it too...
Comment 18 Marc Khouzam CLA 2010-09-09 19:40:00 EDT
(In reply to comment #4)

> > Also, two minor comments:
> > 1- I don't think you need to call setData() with the new childFullExpression.
> This is necessary when you have a second level derived class. 
> e.g.
> class testbase {
>     float fBase;
> };
> 
> class test1 : public testbase {
>     float f1;
> };
> 
> class test2 : public test1 {
> public:
>   test2()
>   {
>     printf("%d", aiVal[0]);
>   }
> };
> 

I agree that you need to set the full expression of the child to be the new one we created, but the setData() call is something else, which will make getData() change.  But since we don't use getData() anymore, there is no need, as far as I can see.
Comment 19 Axel Mueller CLA 2010-09-20 17:37:27 EDT
(In reply to comment #17)
> > > Also, nested children logic (if (parent != null)) does not quite work.
> > > I added 'int *a;' in testbase and I'm getting errors.  This is because the
> > > parent of an expression can be the public/private/protected element, so we
> > > would need to go another parent up.
> > Hmm, I don't get any errors when adding "int *a" to testbase. However, I am
> > testing the example from comment #0 manually and not your unit test. 
> 
> I was able to see this manually by opening down to *a and the selecting it.
OK, I was able now to partly reproduce this. I used the code from the unit test:

class Base {
public:
  int nested;
  int* pNested;
};
class BaseTest: public Base {
public:
  BaseTest() {}
  void test() {
    nested = 8;
    return;
  }
  Base Base; // make sure we don't get confused by the same name
};

int main(void)
{  
    BaseTest b;   
    b.test();
    return 0;
}
I had to open in Variables View b.Base (the second one!) and select pNested and then dig further. But in my case it only fails because pNested=0x0 ! (Cannot access memory 0x0). If I add the line
  b.Base.pNested = (int*)malloc(1);

I can inspect the variable then w/o any problems. 
Or did you see another error?

> 
> > Both unit
> > tests fail with a time out (the rest of the MIExpressionTests do work).
> 
> Did you update the entire test.dsf.gdb plugin?  You also need the changes from
> ExpressionTestApp.cc.
I have all updates. But both tests fail here in this line:
MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("BaseTest::test");
Is it possible to get the gdb traces in the Junit test? I am using gdb 7.1 (x86_64).
Comment 20 Axel Mueller CLA 2011-04-05 17:40:07 EDT
Created attachment 192600 [details]
modify output of var-info-path-expression beware of variables that are named after their type

I updated the patch to the current HEAD version and fixed a bug. The Junit test does now succeed.
Comment 21 Axel Mueller CLA 2011-04-26 15:55:36 EDT
> I updated the patch to the current HEAD version and fixed a bug. The Junit test
> does now succeed.
Marc, what do you think about it? 


> I had a look at the patch and I was bothered by the technique of using
> baseClassName.equals(child.getType()) to know if we are dealing with a base
> class.
I have noticed that QtCreator uses a similar approach
"isBaseClass = field.name == stripClassTag(str(field.type))"
see http://qt.gitorious.org/qt-creator/qt-creator/blobs/master/share/qtcreator/gdbmacros/dumper.py
Comment 22 Marc Khouzam CLA 2011-04-27 13:34:58 EDT
(In reply to comment #21)
> > I updated the patch to the current HEAD version and fixed a bug. The Junit test
> > does now succeed.
> Marc, what do you think about it? 

Sorry for the delay.  I've started looking at it but go pulled away again.  But I'm hopeful for this week.
Comment 23 Marc Khouzam CLA 2011-04-29 16:00:48 EDT
Created attachment 194406 [details]
Minor updates to Axel's last patch

I cleaned-up the patch a little by renaming variables and adding more comments.  I also fixed a JUnit that was failing with the changes.

However, I still don't feel this patch is safe.  The problem is in the fact that once we start creating our own expression to add 'struct', we have to keep looking for it and having a special case for all children.  I'm talking about the case:

} else if ( parent != null ) {

This else clause will be hit for every single child expression which does not have the same name as type, which is pretty much every child.  In that majority of cases, we start looking for the inserted 'struct' in different potential places, and then building our own expressions instead of using the output of var-info-path-expression.

I think the risk is too big for the benefit.

CDI was able to fix it easily because it builds the expression itself, and stores it.  In our case, because we rely on GDB's var-info-path-expression, we rely on GDB to give us the proper expression for the parent and for any of the children.

To fix this more safely, I think we would need a new member in our MIVariableObject class to remember if we can trust var-info-path-expression for this hierarchy of varObjects.  Once we detect that a varObj is having the problem and that we insert the 'struct', we should mark it in a way, so that when we deal with any of its children, or children of children, etc, we no longer use var-info-path-expression.

If we do that, once GDB is fixed, we should no longer ignore var-info-path-expression, which means we'll have to version MIVariableManager.  I'm not convinced this problem is worth all the effort.

I think we should fix GDB instead and live with the bug for older versions.  I posted a fix at http://sourceware.org/ml/gdb-patches/2010-09/msg00204.html, but I haven't pushed further.  With a little effort, I could probably get it in for 7.2.1 and for 7.3.

What do you think?
Comment 24 Axel Mueller CLA 2011-05-02 04:42:48 EDT
(In reply to comment #23)
> To fix this more safely, I think we would need a new member in our
> MIVariableObject class to remember if we can trust var-info-path-expression for
> this hierarchy of varObjects.  Once we detect that a varObj is having the
> problem and that we insert the 'struct', we should mark it in a way, so that
> when we deal with any of its children, or children of children, etc, we no
> longer use var-info-path-expression.
> 
> If we do that, once GDB is fixed, we should no longer ignore
> var-info-path-expression, which means we'll have to version MIVariableManager. 
> I'm not convinced this problem is worth all the effort.
> 
> I think we should fix GDB instead and live with the bug for older versions.  I
> posted a fix at http://sourceware.org/ml/gdb-patches/2010-09/msg00204.html, but
> I haven't pushed further.  With a little effort, I could probably get it in for
> 7.2.1 and for 7.3.
> 
> What do you think?
I see the problem with the special case for the children. Of course, a gdb patch would be preferable. However, not everyone can update its gdb (I am using gdb 7.2 at the moment, so updating to 7.2.1 should be no problem for me. But others might be using some older version , e.g. RHEL6 ships gdb 7.0).
Do you think the changes with respect to MIVariableObject might be doable for the Indigo release in June?
Comment 25 Marc Khouzam CLA 2011-05-02 10:04:05 EDT
(In reply to comment #24)

> I see the problem with the special case for the children. Of course, a gdb
> patch would be preferable. However, not everyone can update its gdb (I am using
> gdb 7.2 at the moment, so updating to 7.2.1 should be no problem for me. But
> others might be using some older version , e.g. RHEL6 ships gdb 7.0).
> Do you think the changes with respect to MIVariableObject might be doable for
> the Indigo release in June?

If we limit the change to children of the buggy-case, I'd be ok with submitting it in the next two weeks.  Is that enough time for you?
Comment 26 Axel Mueller CLA 2011-05-02 12:53:52 EDT
(In reply to comment #25)
> If we limit the change to children of the buggy-case, I'd be ok with submitting
> it in the next two weeks.  Is that enough time for you?
OK. Hopefully, I will have a new patch within this week.
Comment 27 Axel Mueller CLA 2011-05-03 15:40:37 EDT
Created attachment 194636 [details]
Update to Marc's patch. Remember if we used the workaround to create are own var-info-expression

>To fix this more safely, I think we would need a new member in our >MIVariableObject class to remember if we can trust var-info-path-expression for >this hierarchy of varObjects. Once we detect that a varObj is having the problem >and that we insert the 'struct', we should mark it in a way, so that< when we >deal with any of its children, or children of children, etc, we no< longer use >var-info-path-expression.
I added a new boolean to MIVariableObject to remember if we used the 'struct' workaround. That way we will only check the children of this varObject.

>If we do that, once GDB is fixed, we should no longer ignore
>var-info-path-expression, which means we'll have to version MIVariableManager. 
How would you do this?
Comment 28 Marc Khouzam CLA 2011-05-03 15:47:49 EDT
(In reply to comment #27)
> >If we do that, once GDB is fixed, we should no longer ignore
> >var-info-path-expression, which means we'll have to version MIVariableManager. 
> How would you do this?

I'm not sure what is easier, but we have a couple of options:
1- wait for GDB to be fixed to know which version has the fix and version MIVariableManager (seems complicated, maintenance wise)
2-before inserting the 'struct' keyword, we can verify if var-info-path-expression already has the 'struct' or 'class' keyword.  This is a hack to me.  GDB could fix the problem in another way and we would not know.
3- the very first time (and only then) we are about to insert the 'struct' keyword, we first send a command to GDB using -data-evaluate-expression with the result of -var-info-path-expression.  If the command fails, we know we have to apply our fix; else we know we can trust GDB.

I think #3 is easier to code but is more obscure.  It would need some clear comments.  It has the advantage that once GDB fixes the problem, we would already be ready for it.  I suggest trying that approach and seeing how it looks.
Comment 29 Axel Mueller CLA 2011-05-03 16:15:26 EDT
(In reply to comment #28)
> I'm not sure what is easier, but we have a couple of options:
> 1- wait for GDB to be fixed to know which version has the fix and version
> MIVariableManager (seems complicated, maintenance wise)
> 2-before inserting the 'struct' keyword, we can verify if
> var-info-path-expression already has the 'struct' or 'class' keyword.  This is
> a hack to me.  GDB could fix the problem in another way and we would not know.
> 3- the very first time (and only then) we are about to insert the 'struct'
> keyword, we first send a command to GDB using -data-evaluate-expression with
> the result of -var-info-path-expression.  If the command fails, we know we have
> to apply our fix; else we know we can trust GDB.
> 
> I think #3 is easier to code but is more obscure.  It would need some clear
> comments.  It has the advantage that once GDB fixes the problem, we would
> already be ready for it.  I suggest trying that approach and seeing how it
> looks.
I would also favor option #3. Interestingly, this is the way QtCreator handles this gdb bug.
Could you give me some hints how to implement it?
Comment 30 Marc Khouzam CLA 2011-05-03 16:34:03 EDT
> I would also favor option #3. Interestingly, this is the way QtCreator handles
> this gdb bug.
> Could you give me some hints how to implement it?

Try this:
create an expressionDMC using the result from -var-info-path-expression
then 
fCommandControl.queueCommand(
  fCommandFactory.createMIDataEvaluateExpression(expressionDMC),
  new DataRequestMonitor<MIDataEvaluateExpressionInfo>(getExecutor(), rm) {
	@Override
	protected void handleError() {
// GDB bug
        }
  });
Comment 31 Axel Mueller CLA 2011-05-04 16:41:08 EDT
(In reply to comment #30)
> > I would also favor option #3. Interestingly, this is the way QtCreator handles
> > this gdb bug.
> > Could you give me some hints how to implement it?
> 
> Try this:
> create an expressionDMC using the result from -var-info-path-expression
Dumb question: How do I create an expressionDMC?
Comment 32 Marc Khouzam CLA 2011-05-05 10:07:47 EDT
(In reply to comment #31)
> (In reply to comment #30)
> > > I would also favor option #3. Interestingly, this is the way QtCreator handles
> > > this gdb bug.
> > > Could you give me some hints how to implement it?
> > 
> > Try this:
> > create an expressionDMC using the result from -var-info-path-expression
> Dumb question: How do I create an expressionDMC?

I knew I should have mentioned that, but I was rushed, sorry.


IExpressionDMContext exprDmc= expressions.createExpression(parentDmc, exprStr);

The parentDmc can be a frame, a thread or a memory dmc, as shown in MIExpressions.createExpression(IDMContext, ExpressionInfo)
Comment 33 Axel Mueller CLA 2011-05-05 17:11:18 EDT
(In reply to comment #32)
> > Dumb question: How do I create an expressionDMC?
> 
> I knew I should have mentioned that, but I was rushed, sorry.
> 
> IExpressionDMContext exprDmc= expressions.createExpression(parentDmc, exprStr);
> 
> The parentDmc can be a frame, a thread or a memory dmc, as shown in
> MIExpressions.createExpression(IDMContext, ExpressionInfo)
I still don't get it. I tried the following:
			        							
IExpressionDMContext expressionDMC = null;
IFrameDMContext frameDmc = DMContexts.getAncestorOfType(getRootToUpdate().getControlDMContext(), IFrameDMContext.class);
			        						    
if (frameDmc != null) {
expressionDMC= new MIExpressionDMC( getSession().getId(), new ExpressionInfo( childFullExpression, childFullExpression), frameDmc);
} 

However, frameDmc is always null. I think this DMC thing is beyond my Eclipse/Java knowledge.
Comment 34 Marc Khouzam CLA 2011-05-06 11:49:58 EDT
(In reply to comment #33)
> IExpressionDMContext expressionDMC = null;
> IFrameDMContext frameDmc =
> DMContexts.getAncestorOfType(getRootToUpdate().getControlDMContext(),
> IFrameDMContext.class);

The controlDMContext never has a frame as a parent, so it makes sense it is null.

We need to choose a thread for which to create the expression.  However, that particular variable object is only valid for a particular thread, and I'm not sure we store that anywhere.  I'll try to have a look this afternoon to see if we can do anything.
Comment 35 Axel Mueller CLA 2011-05-11 03:12:22 EDT
(In reply to comment #34)
> We need to choose a thread for which to create the expression.  However, that
> particular variable object is only valid for a particular thread, and I'm not
> sure we store that anywhere.  I'll try to have a look this afternoon to see if
> we can do anything.
Anything I can do on this?
Comment 36 Marc Khouzam CLA 2011-05-11 06:32:47 EDT
(In reply to comment #35)
> (In reply to comment #34)
> > We need to choose a thread for which to create the expression.  However, that
> > particular variable object is only valid for a particular thread, and I'm not
> > sure we store that anywhere.  I'll try to have a look this afternoon to see if
> > we can do anything.
> Anything I can do on this?

Sorry, I'll work on it this morning.
Comment 37 Marc Khouzam CLA 2011-05-11 06:53:17 EDT
(In reply to comment #27)
> Created attachment 194636 [details]
> Update to Marc's patch. Remember if we used the workaround to create are own
> var-info-expression
> 
> >To fix this more safely, I think we would need a new member in our >MIVariableObject class to remember if we can trust var-info-path-expression for >this hierarchy of varObjects. Once we detect that a varObj is having the problem >and that we insert the 'struct', we should mark it in a way, so that< when we >deal with any of its children, or children of children, etc, we no< longer use >var-info-path-expression.
> I added a new boolean to MIVariableObject to remember if we used the 'struct'
> workaround. That way we will only check the children of this varObject.

Great. Can you name it with a lower-case letter first? Also, remove the @since tag since it is not public.

I'm guessing you set the hasCastToBaseClassWorkaround flag at the top because we need to include the fakeChild case in there too, right?  Can you put a comment to say that?  My first reaction was to push down that code to the new else clause below, which I think would have been wrong.

Can you explain to me this part:

if (getParent().getExpression().contains("(" + CAST_PREFIX)){ //$NON-NLS-1$	// children of base class used in derived class
  childFullExpression = "(" + getParent().getExpression() + ")." + child.getExp(); //$NON-NLS-1$ //$NON-NLS-2$
} else if (parentExpression.contains("(" + CAST_PREFIX)){ //$NON-NLS-1$  // dereferenced pointer of base class in derived class
  childFullExpression = "*" + parentExpression; //$NON-NLS-1$		        								}

Do we need to check for the presence of CAST_PREFIX now that we have checked for  
hasCastToBaseClassWorkaround?

Can you give and example for the if case and one for the else case?  I don't understand what we are doing here.

Thanks

> >If we do that, once GDB is fixed, we should no longer ignore
> >var-info-path-expression, which means we'll have to version MIVariableManager. 
> How would you do this?

I'll commit the above patch, once you make the changes, and we can deal with this part separately.
Comment 38 Marc Khouzam CLA 2011-05-11 07:00:40 EDT
Created attachment 195322 [details]
Fix to JUnit tests

Fix for JUnit tests to match the new output
Comment 39 Axel Mueller CLA 2011-05-11 16:40:06 EDT
(In reply to comment #37)
> Great. Can you name it with a lower-case letter first? Also, remove the @since
> tag since it is not public.
No problem.

> I'm guessing you set the hasCastToBaseClassWorkaround flag at the top because
> we need to include the fakeChild case in there too, right?  Can you put a
> comment to say that?  My first reaction was to push down that code to the new
> else clause below, which I think would have been wrong.
The check for the must indeed stay on top in case of fake children like var1.public. Otherwise the flag would not be inherited to all children.

 
> Can you explain to me this part:
> 
> if (getParent().getExpression().contains("(" + CAST_PREFIX)){ //$NON-NLS-1$   
> // children of base class used in derived class
>   childFullExpression = "(" + getParent().getExpression() + ")." +
> child.getExp(); //$NON-NLS-1$ //$NON-NLS-2$
> } else if (parentExpression.contains("(" + CAST_PREFIX)){ //$NON-NLS-1$  //
> dereferenced pointer of base class in derived class
>   childFullExpression = "*" + parentExpression; //$NON-NLS-1$                  
>                              }
> 
> Do we need to check for the presence of CAST_PREFIX now that we have checked
> for  
> hasCastToBaseClassWorkaround?
> 
> Can you give and example for the if case and one for the else case?  I don't
> understand what we are doing here.
It is a bit complicated. You should have a look at the Junit C++ code for better understanding. But I will try to explain it.
- We must check for the CAST_PREFIX because the parent can be a fake variable, e.g. var1.public
- The parent will be "(Base*)this" when we try to inspect a base class variable in the derived class (if clause). In this case the parent expression will have the CAST_PREFIX and we must construct the correct child expression.
- When we inspect a variable of the derived class the parent will be "this" (w/o the cast to the base class!). However, the parent still has the hasCastToBaseClassWorkaround flag. But in this case we should not modify the child expression.
- I changed the else clause to make it more understandable
} else if (isPointer()){
This test is necessary when the base class has a pointer variable which must be dereferenced  ((struct Base*)(this)).pNested
Comment 40 Axel Mueller CLA 2011-05-11 16:42:52 EDT
Created attachment 195429 [details]
Remember if we used the workaround to create are own var-info-expression

Update for last patch (see my last comment for details).
Comment 41 Marc Khouzam CLA 2011-05-12 11:01:58 EDT
Looking at
  if (child.getExp().equals(child.getType()) && parentExpression != getGdbName()) {
  [snip]
  hasCastToBaseClassWorkaround = true;
}

it seems we are setting the new flag for the parent instead of the child.  I believe this will cause the workaround to be triggered for all grandchildren of this expression, although it may be only one of its children that needs it, so a subset of its grandchildren.  I think I need an example to explain.

Say you have:

parent  (hasWorkaround==false) 
  currentVarObj   (hasWorkaround==false)
    child1   <---- this one needs the workaround
      grandchild1
    child2
      grandchild2

when we notice child1 needs the workaround, the code will bring us to the following state:

parent  (hasWorkaround==false) 
  currentVarObj   (hasWorkaround==true)  <-- changed instead of child1
    child1   
      grandchild1
    child2
      grandchild2

That means that when we examine grandchild2 and do
  if (getParent() != null && getParent().hasCastToBaseClassWorkaround) {
    hasCastToBaseClassWorkaround = true;
  }
getparent() will look at currentVarObj and will think that grandchild2 needs the workaround.

But maybe I'm mis-reading things...  I haven't confirmed by testing.

It also hit me that the clean way to do this change is to improve and use buildChildExpression() instead of calling var-info-path-expression.  Currently, we will call var-info-path-expression, and then ignore its result completely.  I'll modify the patch in those lines and post the result to see what you think.
Comment 42 Marc Khouzam CLA 2011-05-12 16:39:31 EDT
I got pulled to a customer issue.  But we can try this for the next build.
Comment 43 Axel Mueller CLA 2011-05-12 16:58:32 EDT
(In reply to comment #41)
> Looking at
>   if (child.getExp().equals(child.getType()) && parentExpression !=
> getGdbName()) {
>   [snip]
>   hasCastToBaseClassWorkaround = true;
> }
> 
> it seems we are setting the new flag for the parent instead of the child.  I
> believe this will cause the workaround to be triggered for all grandchildren of
> this expression, although it may be only one of its children that needs it, so
> a subset of its grandchildren.  I think I need an example to explain.
>....
I thought about your objection and did some tests. 
parent "this"
  child "Base" (here we need the CAST_PREFIX to get (struct Base*)(this)
    grandchild "var1.Base.public"   => check still needed
  child2 "childOfBaseTest"  => check no longer needed

So your suggestion would indeed prevent some useless checks.
I did not find a way to flag the child directly (it is of type MIVar) so I added a second boolean (not really nice).
if (getParent() != null) {
  if (getParent().childWillNeedCastToBaseClassWorkaround){
    hasCastToBaseClassWorkaround = true;
    childWillNeedCastToBaseClassWorkaround = false;
  } else if (getParent().hasCastToBaseClassWorkaround){
           hasCastToBaseClassWorkaround = true;
         }
Comment 44 Axel Mueller CLA 2011-05-15 07:47:12 EDT
Created attachment 195660 [details]
Remember if we used the workaround to create are own var-info-expression

Here is the patch according to my last comment.
Comment 45 Marc Khouzam CLA 2011-05-16 06:09:07 EDT
Let's continue and finish this bug.  However, I'm worried about the risk about putting it for Indigo since we are so late.

I prefer to plan it for Indigo's first maintenance release (CDT 8.0.1)
Comment 46 Axel Mueller CLA 2011-05-16 08:50:08 EDT
(In reply to comment #45)
> Let's continue and finish this bug.  However, I'm worried about the risk about
> putting it for Indigo since we are so late.
> 
> I prefer to plan it for Indigo's first maintenance release (CDT 8.0.1)
As a user who his plagued with this (gdb) bug I would prefer the Indigo release :-)
But it is up to you. You know the DSF code much better and have the commit rights (and the responsibility).
Comment 47 Marc Khouzam CLA 2011-05-16 09:06:00 EDT
(In reply to comment #46)
> (In reply to comment #45)
> > Let's continue and finish this bug.  However, I'm worried about the risk about
> > putting it for Indigo since we are so late.
> > 
> > I prefer to plan it for Indigo's first maintenance release (CDT 8.0.1)
> As a user who his plagued with this (gdb) bug I would prefer the Indigo release
> :-)
> But it is up to you. You know the DSF code much better and have the commit
> rights (and the responsibility).

I understand, but MIVariableManager is pretty complex and I would prefer to have such a fix soak a little, just in case.

Thanks for understanding.
Comment 48 Axel Mueller CLA 2011-05-16 15:34:23 EDT
(In reply to comment #45)
> Let's continue and finish this bug.  However, I'm worried about the risk about
> putting it for Indigo since we are so late.
What about committing the patch right after the Indigo release? So the Indigo release would be safe and I could use a nightly build from the 8.0 branch. If I would encounter any problems we would have enough time until the maintenance release.
Comment 49 Marc Khouzam CLA 2011-05-16 16:13:45 EDT
(In reply to comment #48)
> (In reply to comment #45)
> > Let's continue and finish this bug.  However, I'm worried about the risk about
> > putting it for Indigo since we are so late.
> What about committing the patch right after the Indigo release? So the Indigo
> release would be safe and I could use a nightly build from the 8.0 branch. If I
> would encounter any problems we would have enough time until the maintenance
> release.

Absolutely.  As soon as the branch is open.
Comment 50 Axel Mueller CLA 2011-08-03 02:51:56 EDT
(In reply to comment #49)
> > What about committing the patch right after the Indigo release? So the Indigo
> > release would be safe and I could use a nightly build from the 8.0 branch. If I
> > would encounter any problems we would have enough time until the maintenance
> > release.
> 
> Absolutely.  As soon as the branch is open.
Marc, can you commit the patch?
Comment 51 Marc Khouzam CLA 2011-08-03 08:51:21 EDT
(In reply to comment #50)
> (In reply to comment #49)
> > > What about committing the patch right after the Indigo release? So the Indigo
> > > release would be safe and I could use a nightly build from the 8.0 branch. If I
> > > would encounter any problems we would have enough time until the maintenance
> > > release.
> > 
> > Absolutely.  As soon as the branch is open.
> Marc, can you commit the patch?

I'll have a look again this week.
Comment 52 Marc Khouzam CLA 2011-08-03 15:41:26 EDT
Created attachment 200851 [details]
Fix based on "Remember if we used the workaround to create are own var-info-expression"

I modified the proposed patch into something that I felt was a bit cleaner:
1- I moved the logic that played with the childExpression to before we call -var-info-path-expression.  That way, we don't need to make that call to GDB if we won't be using it.
2- I used a local class ChildFullExpressionInfo, to allow us to know if the workaround was used for the child (instead of a new global childWillNeedCastToBaseClassWorkaround)
3- to know if a variable has the same name as its type, instead of doing "parentExpression != getGdbName()", which uses an internal implementation detail (that we use the GdbName as an expression, I used "!isAccessQualifier(getExpressionInfo().getRelExpr())"
4- I had to enhance buildChildExpression() because it was being used in more cases, now that we have to build our own expression for every descendant of a derived class.
5- I added buildDerivedChildExpression() to do the special casting.

The MIExpresions JUnit tests pass for GDB 6.6 to 7.3.
And what pleased me even more is that with GDB 6.6, more tests pass than before because we can handle derived classes ourselves (6.6 does not have the command -var-info-path-expression).

Axel, can you try this patch, look it over too and tell me what you think?
Comment 53 Marc Khouzam CLA 2011-08-04 10:41:07 EDT
I'm still not happy with this fix.
We are affecting too many expressions for a small set that has the problem.

With the latest patch, every expression that is a derived class or a descent of it, will require us to build the full expression ourselves instead of using -var-info-path-expression.  Descendants of derived expressions can take any format allowed by C/C++, so we are effectively bypassing GDB for all derived classes.

On the other hand, from what I can see, the problem seems to only happens for derived classes that:
1- the parent or child class has a constructor
AND
2- we are currently within the child class when looking at the content (going through 'this').  If we look at the content of the derived class when not in it (not using 'this'), the problem does not happen.

The problem is that, in MIVariableManager, we don't cover all possibilities when creating the full expression ourselves.  Our MIVariableManager.buildExpression method is very rudimentary compared to how GDB does it in -var-info-path-expression; in fact, GDB has one method for C code (171 lines) and a different one for C++ code (108 lines).  I doubt that our 23 lines of buildExpression() is covering everything.

So, we have three options:

1- fix GDB (we just missed the release of 7.3, so it may take some months).  I'll follow-up on http://sourceware.org/ml/gdb-patches/2010-09/msg00204.html

2- find a way to limit the impact to only the broken cases and their children (at least only when going through 'this')

3- try to code an exhaustive buildExpression() method, like GDB does.
Comment 54 Axel Mueller CLA 2011-08-04 17:16:23 EDT
(In reply to comment #52)
> I modified the proposed patch into something that I felt was a bit cleaner:
> Axel, can you try this patch, look it over too and tell me what you think?
Sorry, for my late answer, However, I am still struggling with EGit (e.g. Quick diff shows no change after applying your patch). 
I had a look at your patch and have no objections.
Comment 55 Axel Mueller CLA 2011-08-04 17:38:00 EDT
(In reply to comment #53)
> I'm still not happy with this fix.
> We are affecting too many expressions for a small set that has the problem.
> 
> With the latest patch, every expression that is a derived class or a descent of
> it, will require us to build the full expression ourselves instead of using
> -var-info-path-expression.  Descendants of derived expressions can take any
> format allowed by C/C++, so we are effectively bypassing GDB for all derived
> classes.
> 
> On the other hand, from what I can see, the problem seems to only happens for
> derived classes that:
> 1- the parent or child class has a constructor
> AND
> 2- we are currently within the child class when looking at the content (going
> through 'this').  If we look at the content of the derived class when not in it
> (not using 'this'), the problem does not happen.
> 
> The problem is that, in MIVariableManager, we don't cover all possibilities
> when creating the full expression ourselves.  Our
> MIVariableManager.buildExpression method is very rudimentary compared to how
> GDB does it in -var-info-path-expression; in fact, GDB has one method for C
> code (171 lines) and a different one for C++ code (108 lines).  I doubt that
> our 23 lines of buildExpression() is covering everything.
> 
> So, we have three options:
> 
> 1- fix GDB (we just missed the release of 7.3, so it may take some months). 
> I'll follow-up on http://sourceware.org/ml/gdb-patches/2010-09/msg00204.html
> 
> 2- find a way to limit the impact to only the broken cases and their children
> (at least only when going through 'this')
> 
> 3- try to code an exhaustive buildExpression() method, like GDB does.
Did not have we the same discussion some months ago? :) 
My answer from comment #24 still holds. I would prefer to fix this bug in Eclipse and do not want to wait for a gdb bugfix. I don't know how long this will take (there was no clear response to your submitted patch and the GDB bugzilla entry is very old) and updating GDB is not always an option. However, an exhaustive rebuild of the GDB code to build the expression is beyond our scope. Thus, I recommend option #2. Let's see if I find something to limit the scope. I will let you know.
Comment 56 Marc Khouzam CLA 2011-08-05 09:58:33 EDT
(In reply to comment #55)

> Did not have we the same discussion some months ago? :) 
> My answer from comment #24 still holds. I would prefer to fix this bug in
> Eclipse and do not want to wait for a gdb bugfix. I don't know how long this
> will take (there was no clear response to your submitted patch and the GDB
> bugzilla entry is very old) and updating GDB is not always an option. 

I agree that upgrading GDB is not good for everyone (and since we missed 7.3 it may be a while).
But it is still worth fixing in GDB so I've posted a follow-up to my GDB fix: 
http://sourceware.org/ml/gdb-patches/2011-08/msg00108.html

> an exhaustive rebuild of the GDB code to build the expression is beyond our
> scope. Thus, I recommend option #2. Let's see if I find something to limit the
> scope. I will let you know.

Thanks, that would be my preferred solution as well.
Comment 57 Marc Khouzam CLA 2011-08-05 10:18:53 EDT
Created attachment 200983 [details]
Updated latest fix to easily turn off

This patch is identical to the previous one, except that it add a protected method MIVariableManager.needFixForGDBBug320277().  This will allow to easily override this special behavior for GDBs that don't have the bug.

But we still need to reduce the impact of this fix to only failed cases.

Axel, FYI, I'll be on vacation for the next two weeks.
Comment 58 CDT Genie CLA 2011-08-05 17:23:02 EDT
*** cdt git genie on behalf of Marc Khouzam ***

    Bug 320277: Cannot view variables of base class in derived class

[*] http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=f0f38554230a5ef1c6e19ee1d10e664fb2585a4c
Comment 59 Marc Khouzam CLA 2011-08-12 09:41:35 EDT
(In reply to comment #57)
 
> But we still need to reduce the impact of this fix to only failed cases.

Still on vacation but I had a thought.  The best way to do this fix safely is to only trigger the workaround once GDB fails.  I haven't look into if it is feasible or not, but here is the idea.  Use the current algorithm of MIVariableManager (no fix), but look for a GDB failure.  Once GDB fails, trigger the workaround.  It may be that the failure happens for a child of the expression we have to change, but I believe we can go back up the hierarchy and fix the problem at the parent, and mark that hierarchy as needing the fix.
Comment 60 Axel Mueller CLA 2011-08-12 17:54:05 EDT
(In reply to comment #59)
> Still on vacation but I had a thought.  The best way to do this fix safely is
> to only trigger the workaround once GDB fails.
Well, you had this idea before (see comment #28 option 3). And again I do not know how to get the parentDMC (see my answer #33). Any advice?
Comment 61 Axel Mueller CLA 2011-08-18 17:50:40 EDT
(In reply to comment #60)
> Well, you had this idea before (see comment #28 option 3). And again I do not
> know how to get the parentDMC (see my answer #33). Any advice?
OK. I finally managed to get this working as described in comment #28 . As soon as it is working properly I will submit a new patch.
Comment 62 Marc Khouzam CLA 2011-08-22 14:19:34 EDT
(In reply to comment #61)
> (In reply to comment #60)
> > Well, you had this idea before (see comment #28 option 3). And again I do not
> > know how to get the parentDMC (see my answer #33). Any advice?
> OK. I finally managed to get this working as described in comment #28 . As soon
> as it is working properly I will submit a new patch.

From comment #28:

> 3- the very first time (and only then) we are about to insert the 'struct'
> keyword, we first send a command to GDB using -data-evaluate-expression with
> the result of -var-info-path-expression.  If the command fails, we know we have
> to apply our fix; else we know we can trust GDB.

Now that I understand that it is not very easy to figure out in which case we should add the 'struct' keyword and when we don't need to, I think we should always go to GDB and see if we get an error.  Once we get an error, we then know all children will need the workaround, but any varObj not part of such a hierarchy should still go through GDB first.

My original thought in comment 28 was to have a single on/off flag for the entire MIVariableManager, but that is too broad.
Comment 63 Axel Mueller CLA 2011-08-25 18:34:28 EDT
Created attachment 202188 [details]
To check if GDB actually has this bug we call -data-evaluate-expression with the return value of -var-info-path-expression

If a derived class is cast to its base class we check if GDB actually has this bug by calling -data-evaluate-expression with the return value of -var-info-path-expression. If -data-evaluate-expression fails we know GDB is buggy and we will build the expression ourselves. This check is done only once. For the children we check the value of hasCastToBaseClassWorkaround.
Comment 64 Marc Khouzam CLA 2011-08-26 08:55:47 EDT
(In reply to comment #56)

> I agree that upgrading GDB is not good for everyone (and since we missed 7.3 it
> may be a while).
> But it is still worth fixing in GDB so I've posted a follow-up to my GDB fix: 
> http://sourceware.org/ml/gdb-patches/2011-08/msg00108.html

I committed the fix for GDB this morning:
http://sourceware.org/ml/gdb-patches/2011-08/msg00489.html

The other good news is that a GDB 7.3.1 should be released very soon and will contain that fix.  From August 19:
http://sourceware.org/ml/gdb-patches/2011-08/msg00372.html

"So, the plan, now, is to make a 7.3.1 release ASAP, particularly
since we now have the fix for the NetBSD build failure...."
Comment 65 Axel Mueller CLA 2011-08-29 03:28:59 EDT
(In reply to comment #64)
> I committed the fix for GDB this morning:
> http://sourceware.org/ml/gdb-patches/2011-08/msg00489.html
> 
> The other good news is that a GDB 7.3.1 should be released very soon and will
> contain that fix.  From August 19:
> http://sourceware.org/ml/gdb-patches/2011-08/msg00372.html
> 
> "So, the plan, now, is to make a 7.3.1 release ASAP, particularly
> since we now have the fix for the NetBSD build failure...."
That's cool. But I am still using gdb 7.2. So I need the Eclipse workaround :)
Did you have a look at my latest patch?
Comment 66 Marc Khouzam CLA 2011-08-29 15:31:11 EDT
(In reply to comment #65)

> That's cool. But I am still using gdb 7.2. So I need the Eclipse workaround :)
> Did you have a look at my latest patch?

I had a look and it seems pretty good.  Thanks for posting it.
I'll properly try it out review it sometime this week.
Comment 67 Axel Mueller CLA 2011-09-06 14:30:53 EDT
(In reply to comment #66)
> I had a look and it seems pretty good.  Thanks for posting it.
> I'll properly try it out review it sometime this week.
Any chance to get this into the SR1 update release?
Comment 68 Marc Khouzam CLA 2011-09-06 22:46:15 EDT
(In reply to comment #63)
> Created attachment 202188 [details]
> To check if GDB actually has this bug we call -data-evaluate-expression with
> the return value of -var-info-path-expression
> 
> If a derived class is cast to its base class we check if GDB actually has this
> bug by calling -data-evaluate-expression with the return value of
> -var-info-path-expression. If -data-evaluate-expression fails we know GDB is
> buggy and we will build the expression ourselves. This check is done only once.
> For the children we check the value of hasCastToBaseClassWorkaround.

I finally reviewed the patch in detail.  I like the solution.  I have cleaned it up a bit and will post a new version that I am planning on committing once I get to the office.

Here are some comments on the original patch.  I made the corresponding changes already, in the patch I will post.

1- We don't have a clear rule to know for which expressions GDB will fail, which is why we actually try -data-evaluate-expression and see if the expression fails or not.  This is not only to know if GDB has the bug, but to know if the current expression is affected.  So, since we don't know for sure when an expression should fail or now, we cannot know if needFixForGDBBug320277() should be true or false.  Therefore, I removed setNeedFixForGDBBug320277() and the variable needFixForGDBBug320277; instead we'll just have the protected method needFixForGDBBug320277() which can be overridden for GDB versions that we know don't need the fix.

2- cleaned up some missing done() calls and one extra one.

3- Although I liked the check to fStatus.getCode() == 10004 and the error message, we still need to do something for any other error.  So, I made it more general and if we have any error, we build the expression ourselves.

There is one more thing I want to try, which is to merge buildDerivedChildExpression() and buildChildExpression(), to see if it can be used for GDB <  6.7 which didn't have the -var-info-path-expression command.  But I'll do that as a separate patch.

Thanks Axel!
Once I post the patch, I hope you can confirm it works as you would expect.
Comment 69 Marc Khouzam CLA 2011-09-07 09:47:58 EDT
BTW, GDB 7.3.1, which has this bug fixed, has been released
Comment 70 Marc Khouzam CLA 2011-09-07 09:50:45 EDT
Created attachment 202899 [details]
Updated Axel's fix that uses -data-evaluate-expression (master)

Here is the patch for master.  I'll have to modify slightly for 8_0 because I cannot add APIs.

Axel, how does it look?

I'll commit to master now.
Comment 71 Marc Khouzam CLA 2011-09-07 09:51:58 EDT
Oh wait, Axel, you need to confirm in this bug that you wrote this code by yourself (my changes are ok), and that you have to right to contribute to eclipse.
Comment 72 Marc Khouzam CLA 2011-09-07 10:18:08 EDT
Created attachment 202902 [details]
Updated Axel's fix that uses -data-evaluate-expression (8_0)

This is the cdt_8_0 fix which updates the plugin version but also makes the needFixForGDBBug320277() method private, because we cannot add a new API.

Once I get Axel's confirmation he can contribute his patch to eclipse, I'll commit to 8_0
Comment 73 Axel Mueller CLA 2011-09-07 10:30:37 EDT
(In reply to comment #71)
> Oh wait, Axel, you need to confirm in this bug that you wrote this code by
> yourself (my changes are ok), and that you have to right to contribute to
> eclipse.
I wrote all the code by myself and I have the right to contribute it (it is private work).
Comment 74 Marc Khouzam CLA 2011-09-07 10:35:41 EDT
(In reply to comment #73)
> (In reply to comment #71)
> > Oh wait, Axel, you need to confirm in this bug that you wrote this code by
> > yourself (my changes are ok), and that you have to right to contribute to
> > eclipse.
> I wrote all the code by myself and I have the right to contribute it (it is
> private work).


I committed the patches to master and cdt_8_0.

Thanks Axel for not giving up :-)
Comment 75 Axel Mueller CLA 2011-09-07 10:39:06 EDT
(In reply to comment #70)
> Here is the patch for master.  I'll have to modify slightly for 8_0 because I
> cannot add APIs.
> 
> Axel, how does it look?
I just had a short look at the patch and it looks good (I guess I will have no time before the weekend to test the patch).

>3- Although I liked the check to fStatus.getCode() == 10004 and the error
>message, we still need to do something for any other error.  So, I made it more
>general and if we have any error, we build the expression ourselves.
I added this check so we are sure that GDB has this specific bug. So we need to test GDB only once per session and not for every possible base class. That's why I introduced the needFixForGDBBug320277 variable.
Comment 76 Axel Mueller CLA 2011-09-07 10:41:18 EDT
(In reply to comment #74)
> I committed the patches to master and cdt_8_0.
> 
> Thanks Axel for not giving up :-)
Thanks for your support.

BTW, you can also close bug #308678 . This patch should resolve that problem, too.
Comment 77 Marc Khouzam CLA 2011-09-07 10:41:41 EDT
(In reply to comment #75)

> >3- Although I liked the check to fStatus.getCode() == 10004 and the error
> >message, we still need to do something for any other error.  So, I made it more
> >general and if we have any error, we build the expression ourselves.
> I added this check so we are sure that GDB has this specific bug. So we need to
> test GDB only once per session and not for every possible base class. That's
> why I introduced the needFixForGDBBug320277 variable.

The problem is that if the call to -data-evaluate-expression works for one expression, it does not mean that GDB does not have the bug.  For example, when we are not dealing with 'this' the problem does not occur.  So, I don't think it was right to disable the fix if things worked once.  
Makes sense?
Comment 78 Axel Mueller CLA 2011-09-07 10:50:14 EDT
(In reply to comment #77)
> The problem is that if the call to -data-evaluate-expression works for one
> expression, it does not mean that GDB does not have the bug.  For example, when
> we are not dealing with 'this' the problem does not occur.  So, I don't think
> it was right to disable the fix if things worked once.  
> Makes sense?
OK, I didn't think about this case.
Comment 79 CDT Genie CLA 2011-09-07 11:23:03 EDT
*** cdt git genie on behalf of Axel Mueller ***

    Bug 320277: Cannot view variables of base class in derived class

[*] http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=e44884f7ea63d5edcda8cd165de5ac23b741e226
Comment 80 CDT Genie CLA 2011-09-07 11:23:06 EDT
*** cdt git genie on behalf of Axel Mueller ***

    Bug 320277: Cannot view variables of base class in derived class

[*] http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=84fa9f1b4912b6a7a9adf2cdf226ea54e430f81e