Commit 895aa8e1 by David Malcolm Committed by David Malcolm

c-format.c: suggest the correct format string to use (PR c/64955)

This adds fix-it hints to c-format.c so that it can (sometimes) suggest
the format string the user should have used.

The patch adds selftests for the new code in c-format.c.  These
selftests are thus lang-specific.  This is the first time we've had
lang-specific selftests, and hence the patch also adds a langhook for
running them.  (Note that currently the Makefile only invokes the
selftests for cc1).

gcc/c-family/ChangeLog:
	PR c/64955
	* c-common.h (selftest::c_format_c_tests): New declaration.
	(selftest::run_c_tests): New declaration.
	* c-format.c: Include "selftest.h.
	(format_warning_va): Add param "corrected_substring" and use
	it to add a replacement fix-it hint.
	(format_warning_at_substring): Likewise.
	(format_warning_at_char): Update for new param of
	format_warning_va.
	(argument_parser::check_argument_type): Pass "fki" to
	check_format_types.
	(check_format_types): Add param "fki" and pass it to
	format_type_warning.
	(deref_n_times): New function.
	(get_modifier_for_format_len): New function.
	(selftest::test_get_modifier_for_format_len): New function.
	(get_format_for_type): New function.
	(format_type_warning): Add param "fki" and use it to attempt
	to provide hints for argument types when calling
	format_warning_at_substring.
	(selftest::get_info): New function.
	(selftest::assert_format_for_type_streq): New function.
	(ASSERT_FORMAT_FOR_TYPE_STREQ): New macro.
	(selftest::test_get_format_for_type_printf): New function.
	(selftest::test_get_format_for_type_scanf): New function.
	(selftest::c_format_c_tests): New function.

gcc/c/ChangeLog:
	PR c/64955
	* c-lang.c (LANG_HOOKS_RUN_LANG_SELFTESTS): If CHECKING_P, wire
	this up to selftest::run_c_tests.
	(selftest::run_c_tests): New function.

gcc/ChangeLog:
	PR c/64955
	* langhooks-def.h (LANG_HOOKS_RUN_LANG_SELFTESTS): New default
	do-nothing langhook.
	(LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_RUN_LANG_SELFTESTS.
	* langhooks.h (struct lang_hooks): Add run_lang_selftests.
	* selftest-run-tests.c: Include "tree.h" and "langhooks.h".
	(selftest::run_tests): Call lang_hooks.run_lang_selftests.

gcc/testsuite/ChangeLog:
	PR c/64955
	* gcc.dg/format/diagnostic-ranges.c: Add fix-it hints to expected
	output.

From-SVN: r239260
parent b123572d
2016-08-08 David Malcolm <dmalcolm@redhat.com> 2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/64955
* langhooks-def.h (LANG_HOOKS_RUN_LANG_SELFTESTS): New default
do-nothing langhook.
(LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_RUN_LANG_SELFTESTS.
* langhooks.h (struct lang_hooks): Add run_lang_selftests.
* selftest-run-tests.c: Include "tree.h" and "langhooks.h".
(selftest::run_tests): Call lang_hooks.run_lang_selftests.
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR bootstrap/72844 PR bootstrap/72844
* input.c: Ensure that HAVE_ICONV is defined. * input.c: Ensure that HAVE_ICONV is defined.
......
2016-08-08 David Malcolm <dmalcolm@redhat.com> 2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/64955
* c-common.h (selftest::c_format_c_tests): New declaration.
(selftest::run_c_tests): New declaration.
* c-format.c: Include "selftest.h.
(format_warning_va): Add param "corrected_substring" and use
it to add a replacement fix-it hint.
(format_warning_at_substring): Likewise.
(format_warning_at_char): Update for new param of
format_warning_va.
(argument_parser::check_argument_type): Pass "fki" to
check_format_types.
(check_format_types): Add param "fki" and pass it to
format_type_warning.
(deref_n_times): New function.
(get_modifier_for_format_len): New function.
(selftest::test_get_modifier_for_format_len): New function.
(get_format_for_type): New function.
(format_type_warning): Add param "fki" and use it to attempt
to provide hints for argument types when calling
format_warning_at_substring.
(selftest::get_info): New function.
(selftest::assert_format_for_type_streq): New function.
(ASSERT_FORMAT_FOR_TYPE_STREQ): New macro.
(selftest::test_get_format_for_type_printf): New function.
(selftest::test_get_format_for_type_scanf): New function.
(selftest::c_format_c_tests): New function.
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/52952 PR c/52952
* c-format.c: Include "diagnostic.h". * c-format.c: Include "diagnostic.h".
(location_column_from_byte_offset): Delete. (location_column_from_byte_offset): Delete.
......
...@@ -1533,4 +1533,11 @@ extern bool valid_array_size_p (location_t, tree, tree); ...@@ -1533,4 +1533,11 @@ extern bool valid_array_size_p (location_t, tree, tree);
extern bool cilk_ignorable_spawn_rhs_op (tree); extern bool cilk_ignorable_spawn_rhs_op (tree);
extern bool cilk_recognize_spawn (tree, tree *); extern bool cilk_recognize_spawn (tree, tree *);
#if CHECKING_P
namespace selftest {
extern void c_format_c_tests (void);
extern void run_c_tests (void);
} // namespace selftest
#endif /* #if CHECKING_P */
#endif /* ! GCC_C_COMMON_H */ #endif /* ! GCC_C_COMMON_H */
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/64955
* c-lang.c (LANG_HOOKS_RUN_LANG_SELFTESTS): If CHECKING_P, wire
this up to selftest::run_c_tests.
(selftest::run_c_tests): New function.
2016-08-04 Thomas Schwinge <thomas@codesourcery.com> 2016-08-04 Thomas Schwinge <thomas@codesourcery.com>
* c-parser.c (struct oacc_routine_data): Add error_seen and * c-parser.c (struct oacc_routine_data): Add error_seen and
......
...@@ -38,7 +38,29 @@ enum c_language_kind c_language = clk_c; ...@@ -38,7 +38,29 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_INIT_TS #undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS c_common_init_ts #define LANG_HOOKS_INIT_TS c_common_init_ts
#if CHECKING_P
#undef LANG_HOOKS_RUN_LANG_SELFTESTS
#define LANG_HOOKS_RUN_LANG_SELFTESTS selftest::run_c_tests
#endif /* #if CHECKING_P */
/* Each front end provides its own lang hook initializer. */ /* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
#if CHECKING_P
namespace selftest {
/* Implementation of LANG_HOOKS_RUN_LANG_SELFTESTS for the C frontend. */
void
run_c_tests (void)
{
c_format_c_tests ();
}
} // namespace selftest
#endif /* #if CHECKING_P */
#include "gtype-c.h" #include "gtype-c.h"
...@@ -120,6 +120,7 @@ extern bool lhd_omp_mappable_type (tree); ...@@ -120,6 +120,7 @@ extern bool lhd_omp_mappable_type (tree);
#define LANG_HOOKS_BLOCK_MAY_FALLTHRU hook_bool_const_tree_true #define LANG_HOOKS_BLOCK_MAY_FALLTHRU hook_bool_const_tree_true
#define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false
#define LANG_HOOKS_DEEP_UNSHARING false #define LANG_HOOKS_DEEP_UNSHARING false
#define LANG_HOOKS_RUN_LANG_SELFTESTS lhd_do_nothing
/* Attribute hooks. */ /* Attribute hooks. */
#define LANG_HOOKS_ATTRIBUTE_TABLE NULL #define LANG_HOOKS_ATTRIBUTE_TABLE NULL
...@@ -319,7 +320,8 @@ extern void lhd_end_section (void); ...@@ -319,7 +320,8 @@ extern void lhd_end_section (void);
LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS, \ LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS, \
LANG_HOOKS_BLOCK_MAY_FALLTHRU, \ LANG_HOOKS_BLOCK_MAY_FALLTHRU, \
LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \ LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \
LANG_HOOKS_DEEP_UNSHARING \ LANG_HOOKS_DEEP_UNSHARING, \
LANG_HOOKS_RUN_LANG_SELFTESTS \
} }
#endif /* GCC_LANG_HOOKS_DEF_H */ #endif /* GCC_LANG_HOOKS_DEF_H */
...@@ -505,6 +505,9 @@ struct lang_hooks ...@@ -505,6 +505,9 @@ struct lang_hooks
gimplification. */ gimplification. */
bool deep_unsharing; bool deep_unsharing;
/* Run all lang-specific selftests. */
void (*run_lang_selftests) (void);
/* Whenever you add entries here, make sure you adjust langhooks-def.h /* Whenever you add entries here, make sure you adjust langhooks-def.h
and langhooks.c accordingly. */ and langhooks.c accordingly. */
}; };
......
...@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
#include "selftest.h" #include "selftest.h"
#include "tree.h"
#include "langhooks.h"
/* This function needed to be split out from selftest.c as it references /* This function needed to be split out from selftest.c as it references
tests from the whole source tree, and so is within tests from the whole source tree, and so is within
...@@ -70,6 +72,9 @@ selftest::run_tests () ...@@ -70,6 +72,9 @@ selftest::run_tests ()
/* This one relies on most of the above. */ /* This one relies on most of the above. */
function_tests_c_tests (); function_tests_c_tests ();
/* Run any lang-specific selftests. */
lang_hooks.run_lang_selftests ();
/* Finished running tests. */ /* Finished running tests. */
long finish_time = get_run_time (); long finish_time = get_run_time ();
long elapsed_time = finish_time - start_time; long elapsed_time = finish_time - start_time;
......
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/64955
* gcc.dg/format/diagnostic-ranges.c: Add fix-it hints to expected
output.
2016-08-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> 2016-08-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
* gcc.dg/tree-ssa/pr71078-1.c: Add require-effective-target * gcc.dg/tree-ssa/pr71078-1.c: Add require-effective-target
......
...@@ -12,6 +12,25 @@ void test_mismatching_types (const char *msg) ...@@ -12,6 +12,25 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf("hello %i", msg); printf("hello %i", msg);
~^ ~^
%s
{ dg-end-multiline-output "" } */
printf("hello %s", 42); /* { dg-warning "format '%s' expects argument of type 'char \\*', but argument 2 has type 'int'" } */
/* TODO: ideally would also underline "42". */
/* { dg-begin-multiline-output "" }
printf("hello %s", 42);
~^
%d
{ dg-end-multiline-output "" } */
printf("hello %i", (long)0); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'long int' " } */
/* TODO: ideally would also underline the argument. */
/* { dg-begin-multiline-output "" }
printf("hello %i", (long)0);
~^
%ld
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -23,6 +42,7 @@ void test_multiple_arguments (void) ...@@ -23,6 +42,7 @@ void test_multiple_arguments (void)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i", printf ("arg0: %i arg1: %s arg 2: %i",
~^ ~^
%d
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -33,6 +53,7 @@ void test_multiple_arguments_2 (int i, int j) ...@@ -33,6 +53,7 @@ void test_multiple_arguments_2 (int i, int j)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i", printf ("arg0: %i arg1: %s arg 2: %i",
~^ ~^
%d
100, i + j, 102); 100, i + j, 102);
~~~~~ ~~~~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
...@@ -67,6 +88,7 @@ void test_hex (const char *msg) ...@@ -67,6 +88,7 @@ void test_hex (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf("hello \x25\x69", msg); printf("hello \x25\x69", msg);
~~~~~~~^ ~~~~~~~^
%s
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -80,6 +102,7 @@ void test_oct (const char *msg) ...@@ -80,6 +102,7 @@ void test_oct (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf("hello \045\151", msg); printf("hello \045\151", msg);
~~~~~~~^ ~~~~~~~^
%s
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -98,6 +121,7 @@ void test_multiple (const char *msg) ...@@ -98,6 +121,7 @@ void test_multiple (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf("prefix" "\x25" "\151" "suffix", printf("prefix" "\x25" "\151" "suffix",
~~~~~~~~~~~^ ~~~~~~~~~~~^
%s
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -108,6 +132,7 @@ void test_u8 (const char *msg) ...@@ -108,6 +132,7 @@ void test_u8 (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf(u8"hello %i", msg); printf(u8"hello %i", msg);
~^ ~^
%s
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -117,6 +142,7 @@ void test_param (long long_i, long long_j) ...@@ -117,6 +142,7 @@ void test_param (long long_i, long long_j)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
printf ("foo %s bar", long_i + long_j); printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~ ~^ ~~~~~~~~~~~~~~~
%ld
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -192,13 +218,14 @@ void test_macro (const char *msg) ...@@ -192,13 +218,14 @@ void test_macro (const char *msg)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
#define INT_FMT "%i" #define INT_FMT "%i"
~^ ~^
%s
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
void test_non_contiguous_strings (void) void test_non_contiguous_strings (void)
{ {
__builtin_printf(" %" "d ", 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */ __builtin_printf(" %" "d ", 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */
/* { dg-message "26: format string is defined here" "" { target *-*-* } 200 } */ /* { dg-message "26: format string is defined here" "" { target *-*-* } 227 } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5); __builtin_printf(" %" "d ", 0.5);
^~~~ ^~~~
...@@ -206,6 +233,7 @@ void test_non_contiguous_strings (void) ...@@ -206,6 +233,7 @@ void test_non_contiguous_strings (void)
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5); __builtin_printf(" %" "d ", 0.5);
~~~~^ ~~~~^
%f
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment