News:

The new Release 25.03 is out! You can download binaries for Windows and many major Linux distros here .

Main Menu

Find declaration/implementation of fails on obects in containers

Started by logzero, May 21, 2012, 09:08:53 PM

Previous topic - Next topic

logzero

Hi

Not sure if this is a bug, maybe a feature? ;)

Running codeblocks nightly builds on windows. The issue has been there as long as I can remember(2 years?) but too infrequent/random to care until now.

The find function will fail as soon as the object accessed is in a container.

#include <list>

class bar
{
void foo() {}
};

int main()
{
std::list<bar> foobar;
foobar.insert(bar());
foobar.begin().foo(); // fails to find declaration/implementation

bar bar1;
bar1.foo(); // works fine

   return 0;
}



zabzonk

#1
That code won't remotely compile. Was it so hard to try compiling it before posting here? This will:

#include <list>

struct bar {
void foo() {}
};

int main() {
std::list< bar> foobar;
foobar.push_back(bar());
foobar.begin()->foo();
bar bar1;
bar1.foo();
}


You are right that trying to find the declaration of foo() via:

foobar.begin()->foo();

won't work - I assume it's because it takes too much knowledge of what begin() returns. Interestingly, declaring a function like this:

bar * f() {
return new bar;
}


and using:

f()->foo();

will work, but it won't if f() is a template function, so I guess template parsing or the lack of it is the issue.




logzero

Yeah, have been rather sloppy. Sorry and thanks for the corrections.

I was looking for the declaration/implementation of bar method foo() obviously(or not?).

Is the successful compilation a requirement for the functionality to work? Doesn't seem so.

jarod42

Note that operator -> is more complicated that a simple function...

but it seems not be the problem since
(*foobar.begin()). doesn't complete neither (Release version).

ollydbg

I can confirm the bug, but fixing it is quite complex. The reason is that our parser can not handle template information correctly. Any good suggestions are welcome.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

p2rkw

I done few tests:

Debug log for line 66:
QuoteAI() Adding search namespace: Global namespace
BreakUpComponents() Breaking up '  aBar.getBar()->'
BreakUpComponents() Found component: 'aBar' (Class)
BreakUpComponents() Adding component: 'aBar'.
BreakUpComponents() Found component: 'getBar' (Class)
BreakUpComponents() Adding component: 'getBar'.
BreakUpComponents() Found component: '' (SearchText)
BreakUpComponents() Adding component: ''.
ResolveExpression() search scope is 2 result.
search scope: -1
search scope: 463
ResolveExpression() Looping 1 result.
ResolvExpression() Match:'aBar(ID=457) : type='A'
BreakUpComponents() Breaking up 'A'
BreakUpComponents() Found component: 'A' (SearchText)
BreakUpComponents() Adding component: 'A'.
ResolveExpression() search scope is 1 result.
search scope: 1259
ResolveExpression() Looping 1 result.
ResolvExpression() Match:'getBar(ID=1258) : type='T'
BreakUpComponents() Breaking up 'T'
BreakUpComponents() Found component: 'T' (SearchText)
BreakUpComponents() Adding component: 'T'.
ResolveExpression() search scope is 1 result.
search scope: 465
ResolveExpression() Looping 1 result.
ResolvExpression() Match:'tMethod(ID=464) : type='int'
AI() AI leave, returned 1 results
1 results
Generating tokens list...
Done generating tokens list

When breaking statement parser is looking for return value type of function before '->', and im my test it finds template parameter type ( in test named 'T' ). Parser don't recognize 'T' as template parameter but as normal class type, so it continues searching and finds class type with this name.

Test code:
#include <list>

struct bar {
void foo() {}
};

template<class T>
struct opArrow
{
  opArrow(T t) : t(t) {}

  T* operator -> (){
    return &t;
  }

  T t;
};

template <class T>
struct A{
  T* getBar(){
    return &bar1;
  }

  T getBar2(){
    return bar1;
  }

  opArrow<T> getIterator(){
    return opArrow<T>( bar1 );
  }

  T bar1;
};

struct T{
  int tMethod(){
    return 0;
  }
};
int main() {
std::list< bar> foobar;
foobar.push_back(bar());
foobar.begin()->foo();
foobar.begin()->foo();
bar bar1;
bar1.foo();
bar1.foo();

typedef std::list<bar> foobarT;
foobarT foobar2;
foobar2.begin()->foo();

foobar2.begin()->foo();

  foobar2.begin()->foo();

  bar1.foo();
  bar1.foo();

  foobar.begin()->foo();


  A<bar> aBar;

  //aBar.getBar()->

  aBar.getIterator()->foo(); //cc doesnt work here



  opArrow<bar> opBar1(bar());
}



ollydbg

Hi, p2rkw, thanks for your test.

So, the remaining feature improvement is that the "T" should be replaced to "class bar", I remember there are some code handling this in CC, but I'm not sure why it does not work anymore.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.