aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
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/cp
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/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c4
-rw-r--r--gcc/cp/cp-lang.c3
-rw-r--r--gcc/cp/parser.c14
4 files changed, 30 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c76340c..97d7e8d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2018-10-05 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-10-04 Nathan Sidwell <nathan@acm.org>
* lang-specs.h: Use string contatenation, not line splicing.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b2ca667..747f837 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8188,6 +8188,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
tree *fargs = (!nargs ? argarray
: (tree *) alloca (nargs * sizeof (tree)));
+ auto_vec<location_t> arglocs (nargs);
for (j = 0; j < nargs; j++)
{
/* For -Wformat undo the implicit passing by hidden reference
@@ -8197,10 +8198,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
fargs[j] = TREE_OPERAND (argarray[j], 0);
else
fargs[j] = maybe_constant_value (argarray[j]);
+ arglocs.quick_push (EXPR_LOC_OR_LOC (argarray[j], input_location));
}
warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
- nargs, fargs, NULL);
+ nargs, fargs, &arglocs);
}
if (DECL_INHERITED_CTOR (fn))
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 26a1e6d..a0b0102 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -83,6 +83,9 @@ static tree cxx_enum_underlying_base_type (const_tree);
#define LANG_HOOKS_RUN_LANG_SELFTESTS selftest::run_cp_tests
#endif /* #if CHECKING_P */
+#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
+#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
+
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a17cc3f..032108a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4034,6 +4034,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
tree value;
size_t count;
struct obstack str_ob;
+ struct obstack loc_ob;
cpp_string str, istr, *strs;
cp_token *tok;
enum cpp_ttype type, curr_type;
@@ -4090,6 +4091,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
{
location_t last_tok_loc = tok->location;
gcc_obstack_init (&str_ob);
+ gcc_obstack_init (&loc_ob);
count = 0;
do
@@ -4135,6 +4137,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
}
obstack_grow (&str_ob, &str, sizeof (cpp_string));
+ obstack_grow (&loc_ob, &tok->location, sizeof (location_t));
last_tok_loc = tok->location;
@@ -4173,6 +4176,12 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
{
value = build_string (istr.len, (const char *)istr.text);
free (CONST_CAST (unsigned char *, istr.text));
+ if (count > 1)
+ {
+ location_t *locs = (location_t *)obstack_finish (&loc_ob);
+ gcc_assert (g_string_concat_db);
+ g_string_concat_db->record_string_concatenation (count, locs);
+ }
switch (type)
{
@@ -4209,7 +4218,10 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
value = error_mark_node;
if (count > 1)
- obstack_free (&str_ob, 0);
+ {
+ obstack_free (&str_ob, 0);
+ obstack_free (&loc_ob, 0);
+ }
return cp_expr (value, loc);
}