https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56856

--- Comment #11 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Author: dmalcolm
Date: Fri Oct  5 19:02:17 2018
New Revision: 264887

URL: https://gcc.gnu.org/viewcvs?rev=264887&root=gcc&view=rev
Log:
Support string locations for C++ in -Wformat (PR c++/56856)

-Wformat in the C++ FE doesn't work as well as it could:
(a) it doesn't report precise locations within the string literal, and
(b) it doesn't underline arguments for those arguments !CAN_HAVE_LOCATION_P,
despite having location wrapper nodes.

For example:

  Wformat-ranges.C:32:10: warning: format '%s' expects argument of type
'char*', but argument 2 has type 'int' [-Wformat=]
  32 |   printf("hello %s", 42);
     |          ^~~~~~~~~~

(a) is due to not wiring up the langhook for extracting substring
    locations.

    This patch uses the one in c-family; it also fixes string literal
    parsing so that it records string concatenations (needed for
    extracting substring locations from concatenated strings).

(b) is due to the call to maybe_constant_value here:
       fargs[j] = maybe_constant_value (argarray[j]);
    within build_over_call.

    The patch fixes this by building a vec of location_t values when
    calling check_function_arguments.
    I attempted to eliminate the maybe_constant_value call here, but
    it's needed by e.g. check_function_sentinel for detecting NULL,
    and that code is in "c-family", so it can't simply call into
    maybe_constant_value (which is in "cp").

With this patch, the output for the above example is improved to:

  Wformat-ranges.C:32:18: warning: format '%s' expects argument of type
'char*', but argument 2 has type 'int' [-Wformat=]
  32 |   printf("hello %s", 42);
     |                 ~^   ~~
     |                  |   |
     |                  |   int
     |                  char*
     |                 %d

gcc/cp/ChangeLog:
        PR c++/56856
        * call.c (build_over_call): Build a vec of locations of the
        arguments before the call to maybe_constant_value, and pass to
        check_function_arguments.
        * cp-lang.c (LANG_HOOKS_GET_SUBSTRING_LOCATION): Define as
        c_get_substring_location.
        * parser.c (cp_parser_string_literal): Capture string
        concatenation locations.

gcc/ChangeLog:
        PR c++/56856
        * input.c (expand_location_to_spelling_point): Add param "aspect"
        and use rather than hardcoding LOCATION_ASPECT_CARET.
        (get_substring_ranges_for_loc): Handle the case of a single token
        within a macro expansion.
        * input.h (expand_location_to_spelling_point): Add "aspect" param,
        defaulting to LOCATION_ASPECT_CARET.

gcc/testsuite/ChangeLog:
        PR c++/56856
        * g++.dg/ext/builtin4.C: Set expected location for warning to the
        correct location within the format string.
        * g++.dg/plugin/plugin.exp (plugin_test_list): Add the plugin and
        files for testing locations within string literal locations from
        the C frontend.
        * g++.dg/warn/Wformat-method.C: New test.
        * g++.dg/warn/Wformat-pr71863.C: New test.
        * g++.dg/warn/Wformat-ranges-c++11.C: New test.
        * g++.dg/warn/Wformat-ranges.C: New test, based on
        gcc.dg/format/diagnostic-ranges.c.
        * gcc.dg/plugin/diagnostic-test-string-literals-1.c
        (test_multitoken_macro): Generalize expected output to work with
        both C and C++.
        * gcc.dg/plugin/diagnostic-test-string-literals-2.c
        (test_stringified_token_1): Likewise.
        (test_stringified_token_3): Likewise.


Added:
    trunk/gcc/testsuite/g++.dg/warn/Wformat-method.C
    trunk/gcc/testsuite/g++.dg/warn/Wformat-pr71863.C
    trunk/gcc/testsuite/g++.dg/warn/Wformat-ranges-c++11.C
    trunk/gcc/testsuite/g++.dg/warn/Wformat-ranges.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-lang.c
    trunk/gcc/cp/parser.c
    trunk/gcc/input.c
    trunk/gcc/input.h
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/ext/builtin4.C
    trunk/gcc/testsuite/g++.dg/plugin/plugin.exp
    trunk/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
    trunk/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
    trunk/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c

Reply via email to