aboutsummaryrefslogtreecommitdiff
path: root/gcc/input.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-10-05 19:02:17 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-10-05 19:02:17 +0000
commit0d48e8779c6a9ac88f5efd1b4a2d40f43ef75faf (patch)
tree153fa1d9d2a0ab481ba54a9f2f4ed6e311e2a5bf /gcc/input.c
parent1f58c814c0ade165b1691d79a79843ea31d6428b (diff)
downloadgcc-0d48e8779c6a9ac88f5efd1b4a2d40f43ef75faf.zip
gcc-0d48e8779c6a9ac88f5efd1b4a2d40f43ef75faf.tar.gz
gcc-0d48e8779c6a9ac88f5efd1b4a2d40f43ef75faf.tar.bz2
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. From-SVN: r264887
Diffstat (limited to 'gcc/input.c')
-rw-r--r--gcc/input.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/gcc/input.c b/gcc/input.c
index d65a82d..b4b7136 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -813,10 +813,10 @@ expand_location (source_location loc)
"<built-in>". */
expanded_location
-expand_location_to_spelling_point (source_location loc)
+expand_location_to_spelling_point (source_location loc,
+ enum location_aspect aspect)
{
- return expand_location_1 (loc, /*expansion_point_p=*/false,
- LOCATION_ASPECT_CARET);
+ return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
}
/* The rich_location class within libcpp requires a way to expand
@@ -1397,24 +1397,32 @@ get_substring_ranges_for_loc (cpp_reader *pfile,
source_range src_range = get_range_from_loc (line_table, strlocs[i]);
if (src_range.m_start >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
- /* If the string is within a macro expansion, we can't get at the
- end location. */
- return "macro expansion";
-
- if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS)
- /* If so, we can't reliably determine where the token started within
- its line. */
- return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS";
-
- if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS)
- /* If so, we can't reliably determine where the token finished within
- its line. */
- return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS";
+ {
+ /* If the string token was within a macro expansion, then we can
+ cope with it for the simple case where we have a single token.
+ Otherwise, bail out. */
+ if (src_range.m_start != src_range.m_finish)
+ return "macro expansion";
+ }
+ else
+ {
+ if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* If so, we can't reliably determine where the token started within
+ its line. */
+ return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS";
+
+ if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* If so, we can't reliably determine where the token finished
+ within its line. */
+ return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS";
+ }
expanded_location start
- = expand_location_to_spelling_point (src_range.m_start);
+ = expand_location_to_spelling_point (src_range.m_start,
+ LOCATION_ASPECT_START);
expanded_location finish
- = expand_location_to_spelling_point (src_range.m_finish);
+ = expand_location_to_spelling_point (src_range.m_finish,
+ LOCATION_ASPECT_FINISH);
if (start.file != finish.file)
return "range endpoints are in different files";
if (start.line != finish.line)