On Mon, 2016-08-22 at 21:25 -0600, Martin Sebor wrote:
> > > Beyond that, the range normally works fine, except when macros
> > > are involved like they are in my tests. You can see the effect
> > > in the range.out file. (This works without your patch but it
> > > could very well be because I didn't set it up right.)
> >
> > Sadly I can't figure out what's going wrong - but the code's
> > changed a
> > lot at my end since then. Sorry.
>
> I have integrated the latest (already committed) version of your
> patch into my -Wformat-length patch. Everything (well almost)
> works and I get nice ranges for the format string and for (some)
> arguments.
>
> I was surprised at how long it took me to switch from the previous
> implementation (also copied from c-format.c) to this new API. As
> before, I had to copy bits and pieces of code from other parts of
> the compiler to get it to work. I was also surprised at how complex
> making use of it is. It added 130 lines of code to the pass, which
> is 40 more than what I had before. It seems that the
> format_warning_at_substring function from c-format.c (perhaps
> generalized and with some reasonable defaults hardcoded) should
> be defined where other parts of GCC (including the middle end)
> can reuse it.
I'm guessing that it was difficult because the most useful parts are
currently in c-format.c, whereas your code is in the middle-end.
Is the latest version of your patch posted somewhere where I can see
it?
The substring_loc class should probably be moved from c-family to gcc
also. We might need a langhook to support that though (not sure yet).
I'd be up for doing these moves (maybe moving
format_warning_at_substring to diagnostic.h/c), but I'd prefer to see
your patch first.
> I ran into a few minor glitches while testing it and I raised
> the following bugs for two of them:
>
> 77328 - incorrect caret location in -Wformat calling printf
> via a macro (this was pre-existing)
> 77331 - incorrect range location in -Wformat with a concatenated
> format literal (this is new)
>
> The third issue seems like a limitation that I should be able to
> overcome but I couldn't figure out how using the new API. The
> problem is that there doesn't seem to be a way to point the caret
> at the closing quote of a string, like for example in the following
> test. Even though by default the whole string is underlined (and
> the caret points to the opening quote), there doesn't seem to be
> a way to specify a range where the caret points to the other quote.
> It's no big deal and I only noticed it because one of my tests
> started failing, but it seems like it should be possible.
>
> $ cat t.c && /build/gcc-49905/gcc/xgcc -B /build/gcc-49905/gcc -S
> -Wformat t.c
> char d [2];
>
> void f (void)
> {
> __builtin_sprintf (d, "%sX", "1");
> }
> t.c: In function ‘f’:
> t.c:5:25: warning: writing a terminating nul past the end of the
> destination [-Wformat-length=]
> __builtin_sprintf (d, "%sX", "1");
> ^~~~~
> What I would like to see is similar to what I get when one of
> the format string characters is written past the end:
>
> t.c:5:30: warning: writing format character ‘Z’ at offset 4 past the
> end
> of the destination [-Wformat-length=]
> __builtin_sprintf (d, "%sXYZ", "");
> ^
>
So would you like the output to look like this:
Option (a): underline whole string, with caret at close-quote
t.c: In function ‘f’:
t.c:5:25: warning: writing a terminating nul past the end of the
destination [-Wformat-length=]
__builtin_sprintf (d, "%sX", "1");
~~~~^
or like this:
Option (b): just the close-quote
t.c: In function ‘f’:
t.c:5:25: warning: writing a terminating nul past
the end of the
destination [-Wformat-length=]
__builtin_sprintf (d,
"%sX", "1");
^
?
(do you also emit a note/inform showing the size of d?)
What API are you using to emit the warning? Given the location of the
string as a whole expressed as a location_t, you can probably do
something like this:
location_t
option_a (location_t string_as_a_whole_loc)
{
source_range src_range
= get_range_from_loc (line_table, string_as_a_whole_loc);
return make_location (src_range.m_finish, /* caret */
src_range.m_start, src_range.m_finish);
}
location_t
option_b (location_t string_as_a_whole_loc)
{
source_range
src_range
= get_range_from_loc (line_table, string_as_a_whole_loc);
return src_range.m_finish;
}
(these could be added to libcpp)
but I get the impression you want something like this integrated into
the format_warning or substring_loc APIs (and it's hard to tell without
seeing your patch).
Hope this is helpful
Dave