ctags processing jumps to wrong tag?

813 views
Skip to first unread message

Ben Fritz

unread,
Jan 29, 2013, 11:48:00 AM1/29/13
to vim...@googlegroups.com
I generate CTags for C code with the following:

" -R : recursive
" --extra=+f : include file name as a tag
" --fields=+S : include signature (e.g. parameter list)
" K : include kind of tag as full name
" -k : not kind of tag as single letter
" --totals : print on standard output total number of tags, etc.
" --c-kinds=+p : include function prototype in C code
let ctags_command=Tlist_Ctags_Cmd.' -R --extra=+f --fields=+SK-k --totals --c-kinds=+p .'

I have 'cscopetag' set, so that pressing CTRL-] on a tag name with multiple matches will prompt me before jumping.

When I CTRL-] on a function name, I usually get 2 hits, one for the prototype, the other for the function. If both are in the same file, choosing either hit will jump to the prototype always.

Does anyone else see this issue? Am I doing something wrong?

Ivan Sichmann Freitas

unread,
Jan 29, 2013, 7:44:48 PM1/29/13
to vim...@googlegroups.com
On Tue, Jan 29, 2013 at 08:48:00AM -0800, Ben Fritz did gyre and gimble:
I have the same behavior here, when setting 'cscopetag' on. Here's my
ctag's line:
ctags -R --c-kinds=+pm --c++-kinds=+cpmn --fields=+iaS --extra=+q -I *

--
Ivan Sichmann Freitas
GNU/Linux user #509059
SDF Arpa Member http://isf.sdf.org/about.html

Benjamin Fritz

unread,
Jan 30, 2013, 11:35:44 AM1/30/13
to vim_use
After some investigation, the root cause is that ctags by default uses
a search pattern for the tag location. Thus when a function prototype
and definition are spread over multiple lines, and the first line is
the same for each, the tag location in the generated tags file uses an
identical pattern.

This is somewhat documented (but not explicitly):

http://ctags.sourceforge.net/ctags.html#CAVEATS

I see three ways to fix this:

1. Modify the file to force a difference between the prototype and
function definition. Not really an option, files I edit are under
strict change control and this would be a fairly pointless edit.
2. Move the prototypes into a header file. Not an option for the same
reason as (1), and because the problem occurs mostly for "private"
helper functions scoped to the file itself using the static keyword.
3. Generate tags using line numbers as locations, by adding
--excmd=number to my ctags options. I don't like this method because
then jumping to tags with an older tags file will miss frequently if
the file has changed.

Is there some unknown fourth option without the drawbacks of (3) that
does not involve modifying the file itself? Just generating tags for
prototypes using line numbers but using patterns for the rest of the
tags would be a decent compromise, but I'm not sure how I'd accomplish
that (if it's even possible).

See attached test C file and generated tags file demonstrating this problem.
tagtest.c
tags

Ben Fritz

unread,
Jan 30, 2013, 1:02:19 PM1/30/13
to vim...@googlegroups.com
On Wednesday, January 30, 2013 10:35:44 AM UTC-6, Ben Fritz wrote:
>
> After some investigation, the root cause is that ctags by default uses
>
> a search pattern for the tag location. Thus when a function prototype
>
> and definition are spread over multiple lines, and the first line is
>
> the same for each, the tag location in the generated tags file uses an
>
> identical pattern.
>
>
>
> This is somewhat documented (but not explicitly):
>
>
>
> http://ctags.sourceforge.net/ctags.html#CAVEATS
>
>
>
> I see three ways to fix this:
>
>
>
> 1. Modify the file to force a difference between the prototype and
>
> function definition. Not really an option, files I edit are under
>
> strict change control and this would be a fairly pointless edit.
>
> 2. Move the prototypes into a header file. Not an option for the same
>
> reason as (1), and because the problem occurs mostly for "private"
>
> helper functions scoped to the file itself using the static keyword.
>
> 3. Generate tags using line numbers as locations, by adding
>
> --excmd=number to my ctags options. I don't like this method because
>
> then jumping to tags with an older tags file will miss frequently if
>
> the file has changed.
>
>
>
> Is there some unknown fourth option without the drawbacks of (3) that
>
> does not involve modifying the file itself?

I found a reasonable workaround for my uses. Using the -B flag to ctags generation generates backwards search patterns from the end of the file, so always the last occurrence (the function definition) is found instead of always the first (the function prototype). This makes the prototype for these functions inaccessible via tag jumping, but normally I want the function definition anyway so it's less of an issue than the behavior without -B.

> Just generating tags for
>
> prototypes using line numbers but using patterns for the rest of the
>
> tags would be a decent compromise, but I'm not sure how I'd accomplish
>
> that (if it's even possible).
>
>

I realized after some thought that this still wouldn't work, unless I also use backwards search. I may experiment sometime to see if I can generating ONLY prototype tags and append them to a tags file generated without prototypes. Then I could use forward search for prototypes and backwards search for definitions.

Ben Fritz

unread,
Jan 30, 2013, 1:14:05 PM1/30/13
to vim...@googlegroups.com
On Wednesday, January 30, 2013 12:02:19 PM UTC-6, Ben Fritz wrote:
>
> I found a reasonable workaround for my uses. Using the -B flag to ctags
> generation generates backwards search patterns from the end of the file,
> so always the last occurrence (the function definition) is found instead
> of always the first (the function prototype). This makes the prototype for
> these functions inaccessible via tag jumping, but normally I want the
> function definition anyway so it's less of an issue than the behavior
> without -B.
>
> I may experiment sometime to see if I can generating ONLY prototype tags
> and append them to a tags file generated without prototypes. Then I could
> use forward search for prototypes and backwards search for definitions.

Forward searching prototypes and backward searching functions is actually
really easy, I found. Just invoke ctags twice, as follows:

!"C:/Documents and Settings/ben/ctags58_win32/ctags.exe" --extra=+f --fields=+SK-k --totals -B %
!"C:/Documents and Settings/ben/ctags58_win32/ctags.exe" --extra=+f --fields=+SK-k --totals --c-kinds=p -a %

Now I can access both the prototype and the function definition regardless
of how similar the location pattern!

Reply all
Reply to author
Forward
0 new messages