jump to tags when writing C++ code with overloaded functions

95 views
Skip to first unread message

Dominique Pelle

unread,
Apr 12, 2008, 2:53:40 AM4/12/08
to vim...@googlegroups.com
When writing C code, I'm very happy with exuberant ctags or cscope
integration in Vim to jump to function definitions by pressing CTRL-]
(or g CTRL-]).

But when I'm writing C++ code, it does not work well, mostly because
of overloaded functions and class derivation. I realize of course
that C++ syntax does not make it easy.

Is there a way to jump to the right member function definition
(with CTRL-] or any other way) when that function is overloaded
or when that member function is defined in base and derived class?

Here is an example:

--- 8< --- cut here --- 8< --- cut here --- 8< ---
1 struct base {
2 void method1(int a);
3 };
4
5 void base::method1(int a) {
6 // ...
7 }
8
9 struct derived : base {
10 void method1(int a);
11
12 void method2(int a);
13 void method2(int a, int b);
14 };
15
16 void derived::method1(int a) {
17 // ...
18 }
19
20 void derived::method2(int a) {
21 // ...
22 }
23
24 void derived::method2(int a, int b) {
25 // ...
26 }
27
28 int main() {
29 base b;
30 derived d;
31
32 b.method1(0); // CTRL-] should jump to base::method1(int a)
33 d.method1(0); // CTRL-] should jump to derived::method1(int a)
34
35 d.method2(0); // CTRL-] should jump to derived::method2(int a)
36 d.method2(0, 0); // CTRL-] should jump to derived::method2(int a, int b)
37
38 return 0;
39 }
--- 8< --- cut here --- 8< --- cut here --- 8< ---

I create a tag file with:

$ find . -name '*.cpp' |
ctags -L - --language-force=c++ --c++-kinds=+p \
--fields=+iaS --extra=+f+q -f tags

And in my ~/.vimrc, I have "set tags=tags"

If cursor is on 'method2' at line 36 of above example, pressing CTRL-]
jumps to line 12 (instead of line 24).

If instead of pressing CTRL-] at line 36, I press g CTRL-], Vim
proposes the 4 possible jumps...

1 FSC p method2 bar.cpp
struct:derived access:public signature:(int a)
void method2(int a);
2 FSC p method2 bar.cpp
struct:derived access:public signature:(int a, int b)
void method2(int a, int b);
3 F C f method2 bar.cpp
class:derived signature:(int a)
void derived::method2(int a) {
4 F C f method2 bar.cpp
class:derived signature:(int a, int b)
void derived::method2(int a, int b) {

... and I have to select manually select where to jump, which is not
always as simple as in this sample case.

-> So my question: is there any better way to use ctags (or any other
tool or plugin) to jump to function definitions when writing C++ code
with Vim?

I'm using:

- vim-7.1.293
- cscope-15.6
- exuberant ctags-5.7

I'm also using the following plugins. Though very useful, they don't
do what I really want:

- omnicomplete (from Vissale Neang)
- taglist (from Yegappan Lakshmanan)

Thanks
-- Dominique

A.Politz

unread,
Apr 12, 2008, 5:37:56 AM4/12/08
to vim...@googlegroups.com
Dominique Pelle wrote:

>[...]


>
>I'm also using the following plugins. Though very useful, they don't
>do what I really want:
>
>- omnicomplete (from Vissale Neang)
>
>
>

omnicomplete has to have this information, just a matter of getting to it.

-ap

--
:wq

Dominique Pelle

unread,
Apr 14, 2008, 5:21:11 AM4/14/08
to vim...@googlegroups.com
Dominique Pelle <dominiq...@gmail.com> wrote:

> When writing C code, I'm very happy with exuberant ctags or cscope
> integration in Vim to jump to function definitions by pressing CTRL-]
> (or g CTRL-]).
>
> But when I'm writing C++ code, it does not work well, mostly because
> of overloaded functions and class derivation. I realize of course
> that C++ syntax does not make it easy.


I've been pondering about this problem and I had the
following idea:

How about using the output of objdump on the linked ELF
to find the information where to jump?

Let's take the example I gave in the original message:

So when pressing CTRL-] on 'method2' on line bar.cpp:36,
how can we find where to jump? method2 called at line
bar.cpp:36 is defined in 4 different places, but the correct
place where to jump should be line bar.cpp:24.

If I compile with -g and run objdump, I see this:

--- 8< --- cut here --- 8< --- cut here --- 8< ---

$ g++ -g bar.cpp

$ objdump --disassemble --source \
--line-numbers --demangle \
--no-show-raw-insn a.out
[...snip...]
/home/dope/bar.cpp:36


d.method2(0, 0); // CTRL-] should jump to derived::method2(int a, int b)

80483a6: movl $0x0,0x8(%esp)
80483ae: movl $0x0,0x4(%esp)
80483b6: lea 0xfffffffa(%ebp),%eax
80483b9: mov %eax,(%esp)
80483bc: call 8048356 <derived::method2(int, int)>
[...snip...]


--- 8< --- cut here --- 8< --- cut here --- 8< ---

So method2 called at line bar.cpp:36 (where CTRL ] is pressed)
is defined at address 0x8048356. If I search for this address
"^ 8048356" in the output of objdump, I see this:

--- 8< --- cut here --- 8< --- cut here --- 8< ---

/home/dope/bar.cpp:24

void derived::method2(int a, int b) {

8048356: push %ebp


--- 8< --- cut here --- 8< --- cut here --- 8< ---

Bingo! This is exactly the information we need.
CTRL ] can then jump to line bar.cpp:24 (which is
indeed the correct place where to jump).

It is an exact method without requiring heuristics
to parse complex c++ code. If speed matters,
it could be made fast if we index the output of
objdump by:

- source file + line number, to find bar.cpp:36 where
CTRL ] is pressed in O(log(n))
- and by address, to find address of callee (8048356
in my example) in O(log(n)).

That could really help c++ developers who use Vim.

-- Dominique

Ni

unread,
Apr 14, 2008, 7:47:01 AM4/14/08
to vim_use
Nice!
Really, I think that g++ or whatever should parse all instead of us.
You gave me start.

So sources have to be complied before ctrl-] .Or you suggest to make
instance compile on ctrl-]?


On Apr 14, 12:21 pm, "Dominique Pelle" <dominique.pe...@gmail.com>
wrote:

Ni

unread,
Apr 14, 2008, 9:23:26 AM4/14/08
to vim_use
One problem, though.
objdump in my .o file doesn't show class name. but use additional
symbols in method name.

On Apr 14, 12:21 pm, "Dominique Pelle" <dominique.pe...@gmail.com>
wrote:

Dominique Pelle

unread,
Apr 14, 2008, 9:54:37 AM4/14/08
to vim...@googlegroups.com
How does the output of objdump looks like for you? (compared to what I
gave in my previous email). Did you demangle the names? (--demangle
options for me). I used objdump from GNU binutils.

Also, you need to use objdump on the linked executable (not the *.o)
to get the proper address of the function where to jump to.

-- Dominique

Ni

unread,
Apr 14, 2008, 1:01:02 PM4/14/08
to vim_use
version 2.15.92.0.2 20040927
I am afraid I can not get access to another one.

What do you think about 700mb executable file?
Will it still be a good idea without some database cashing?

On Apr 14, 4:54 pm, "Dominique Pelle" <dominique.pe...@gmail.com>
wrote:
> How does the output of objdump looks like for you? (compared to what I
> gave in my previous email). Did you demangle the names? (--demangle
> options for me). I used objdump from GNU binutils.
>
> Also, you need to use objdump on the linked executable (not the *.o)
> to get the proper address of the function where to jump to.
>
> -- Dominique
>
Reply all
Reply to author
Forward
0 new messages