diff options
author | David Malcolm <dmalcolm@redhat.com> | 2018-01-10 19:40:55 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2018-01-10 19:40:55 +0000 |
commit | 9a004410d9f64d658864a899ab911ae9a31c444c (patch) | |
tree | 74d2d62696c26cee3eb63313868f3150f67c4aa3 /gcc/c-family | |
parent | 60d87d86163186669af4b0f493be462e2aadca77 (diff) | |
download | gcc-9a004410d9f64d658864a899ab911ae9a31c444c.zip gcc-9a004410d9f64d658864a899ab911ae9a31c444c.tar.gz gcc-9a004410d9f64d658864a899ab911ae9a31c444c.tar.bz2 |
Preserving locations for variable-uses and constants (PR c++/43486)
This patch implements location wrapper nodes, preserving source locations
of the uses of variables and constants in various places in the
C++ frontend: at the arguments at callsites, and for typeid, alignof,
sizeof, and offsetof.
For example, it allows the C++ FE to underline the pertinent argument
for mismatching calls, for such expressions, improving:
extern int callee (int one, const char *two, float three);
int caller (int first, int second, float third)
{
return callee (first, second, third);
}
from
test.cc: In function 'int caller(int, int, float)':
test.cc:5:38: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
return callee (first, second, third);
^
test.cc:1:41: note: initializing argument 2 of 'int callee(int, const char*, float)'
extern int callee (int one, const char *two, float three);
~~~~~~~~~~~~^~~
to:
test.cc: In function 'int caller(int, int, float)':
test.cc:5:25: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
return callee (first, second, third);
^~~~~~
test.cc:1:41: note: initializing argument 2 of 'int callee(int, const char*, float)'
extern int callee (int one, const char *two, float three);
~~~~~~~~~~~~^~~
This is the combination of the following patches:
"[PATCH 01/14] C++: preserve locations within build_address"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00883.html
"[PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes"
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00591.html
"[PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS"
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01330.html
"[PATCH v4 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)"
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00660.html
"[PATCH 04/14] Update testsuite to show improvements"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00891.html
"[v3 of 05/14] C++: handle locations wrappers when calling warn_for_memset"
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01378.html
"[PATCH 07/14] reject_gcc_builtin: strip any location wrappers"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00886.html
"[v3 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind"
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01433.html
"[PATCH 09/14] Strip location wrappers in null_ptr_cst_p"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00888.html
"[PATCH 11/14] Handle location wrappers in string_conv_p"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00890.html
"[PATCH 12/14] C++: introduce null_node_p"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00894.html
"[v3 of PATCH 13/14] c-format.c: handle location wrappers"
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01494.html
"[PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers"
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00893.html
"[v3 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size"
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01380.html
"[PATCH] Add selftest for "fold_for_warn (error_mark_node)""
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01385.html
gcc/c-family/ChangeLog:
PR c++/43486
* c-common.c: Include "selftest.h".
(get_atomic_generic_size): Perform the test for integral type
before the range test for any integer constant, fixing indentation
of braces. Call fold_for_warn before testing for an INTEGER_CST.
(reject_gcc_builtin): Strip any location wrapper from EXPR.
(selftest::test_fold_for_warn): New function.
(selftest::c_common_c_tests): New function.
(selftest::c_family_tests): Call it, and
selftest::c_pretty_print_c_tests.
* c-common.h (selftest::c_pretty_print_c_tests): New decl.
* c-format.c (check_format_arg): Convert VAR_P check to a
fold_for_warn.
* c-pretty-print.c: Include "selftest.h".
(pp_c_cast_expression): Don't print casts for location wrappers.
(selftest::assert_c_pretty_printer_output): New function.
(ASSERT_C_PRETTY_PRINTER_OUTPUT): New macro.
(selftest::test_location_wrappers): New function.
(selftest::c_pretty_print_c_tests): New function.
* c-warn.c (warn_for_memset): Call fold_for_warn on the arguments.
gcc/cp/ChangeLog:
PR c++/43486
* call.c (null_ptr_cst_p): Strip location wrappers when
converting from '0' to a pointer type in C++11 onwards.
(conversion_null_warnings): Replace comparison with null_node with
call to null_node_p.
(build_over_call): Likewise.
* cp-gimplify.c (cp_fold): Remove the early bailout when
processing_template_decl.
* cp-lang.c (selftest::run_cp_tests): Call
selftest::cp_pt_c_tests and selftest::cp_tree_c_tests.
* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
(selftest::run_cp_tests): Move decl to bottom of file.
(null_node_p): New inline function.
(selftest::cp_pt_c_tests): New decl.
(selftest::cp_tree_c_tests): New decl.
* cvt.c (build_expr_type_conversion): Replace comparison with
null_node with call to null_node_p.
* error.c (args_to_string): Likewise.
* except.c (build_throw): Likewise.
* mangle.c (write_expression): Skip location wrapper nodes.
* parser.c (literal_integer_zerop): New function.
(cp_parser_postfix_expression): Call maybe_add_location_wrapper on
the result for RID_TYPEID. Pass true for new "wrap_locations_p"
param of cp_parser_parenthesized_expression_list. When calling
warn_for_memset, replace integer_zerop calls with
literal_integer_zerop, eliminating the double logical negation
cast to bool. Eliminate the special-casing for CONST_DECL in
favor of the fold_for_warn within warn_for_memset.
(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
param, defaulting to false. Convert "expr" to a cp_expr, and call
maybe_add_location_wrapper on it when wrap_locations_p is true.
(cp_parser_unary_expression): Call maybe_add_location_wrapper on
the result for RID_ALIGNOF and RID_SIZEOF.
(cp_parser_builtin_offsetof): Likewise.
* pt.c: Include "selftest.h".
(tsubst_copy): Handle location wrappers.
(tsubst_copy_and_build): Likewise.
(build_non_dependent_expr): Likewise.
(selftest::test_build_non_dependent_expr): New function.
(selftest::cp_pt_c_tests): New function.
* tree.c: Include "selftest.h".
(lvalue_kind): Handle VIEW_CONVERT_EXPR location wrapper nodes.
(selftest::test_lvalue_kind): New function.
(selftest::cp_tree_c_tests): New function.
* typeck.c (string_conv_p): Strip any location wrapper from "exp".
(cp_build_binary_op): Replace comparison with null_node with call
to null_node_p.
(build_address): Use location of operand when building address
expression.
gcc/testsuite/ChangeLog:
PR c++/43486
* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
to reflect that the arguments are correctly underlined.
* g++.dg/plugin/diagnostic-test-expressions-1.C: Add test coverage
for globals, params, locals and literals.
(test_sizeof): Directly test the location of "sizeof", rather than
when used in compound expressions.
(test_alignof): Likewise for "alignof".
(test_string_literals): Likewise for string literals.
(test_numeric_literals): Likewise for numeric literals.
(test_builtin_offsetof): Likewise for "__builtin_offsetof".
(test_typeid): Likewise for typeid.
(test_unary_plus): New.
* g++.dg/warn/Wformat-1.C: Add tests of pointer arithmetic on
format strings.
gcc/ChangeLog:
PR c++/43486
* tree-core.h: Document EXPR_LOCATION_WRAPPER_P's usage of
"public_flag".
* tree.c (tree_nop_conversion): Return true for location wrapper
nodes.
(maybe_wrap_with_location): New function.
(selftest::check_strip_nops): New function.
(selftest::test_location_wrappers): New function.
(selftest::tree_c_tests): Call it.
* tree.h (STRIP_ANY_LOCATION_WRAPPER): New macro.
(maybe_wrap_with_location): New decl.
(EXPR_LOCATION_WRAPPER_P): New macro.
(location_wrapper_p): New inline function.
(tree_strip_any_location_wrapper): New inline function.
From-SVN: r256448
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 39 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-family/c-format.c | 10 | ||||
-rw-r--r-- | gcc/c-family/c-pretty-print.c | 66 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 3 |
6 files changed, 126 insertions, 16 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e79d985..d6b6085 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,26 @@ +2018-01-10 David Malcolm <dmalcolm@redhat.com> + + PR c++/43486 + * c-common.c: Include "selftest.h". + (get_atomic_generic_size): Perform the test for integral type + before the range test for any integer constant, fixing indentation + of braces. Call fold_for_warn before testing for an INTEGER_CST. + (reject_gcc_builtin): Strip any location wrapper from EXPR. + (selftest::test_fold_for_warn): New function. + (selftest::c_common_c_tests): New function. + (selftest::c_family_tests): Call it, and + selftest::c_pretty_print_c_tests. + * c-common.h (selftest::c_pretty_print_c_tests): New decl. + * c-format.c (check_format_arg): Convert VAR_P check to a + fold_for_warn. + * c-pretty-print.c: Include "selftest.h". + (pp_c_cast_expression): Don't print casts for location wrappers. + (selftest::assert_c_pretty_printer_output): New function. + (ASSERT_C_PRETTY_PRINTER_OUTPUT): New macro. + (selftest::test_location_wrappers): New function. + (selftest::c_pretty_print_c_tests): New function. + * c-warn.c (warn_for_memset): Call fold_for_warn on the arguments. + 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 87bd326..097d192 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "substring-locations.h" #include "spellcheck.h" +#include "selftest.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -6737,8 +6738,15 @@ get_atomic_generic_size (location_t loc, tree function, for (x = n_param - n_model ; x < n_param; x++) { tree p = (*params)[x]; + if (!INTEGRAL_TYPE_P (TREE_TYPE (p))) + { + error_at (loc, "non-integer memory model argument %d of %qE", x + 1, + function); + return 0; + } + p = fold_for_warn (p); if (TREE_CODE (p) == INTEGER_CST) - { + { /* memmodel_base masks the low 16 bits, thus ignore any bits above it by using TREE_INT_CST_LOW instead of tree_to_*hwi. Those high bits will be checked later during expansion in target specific @@ -6748,14 +6756,7 @@ get_atomic_generic_size (location_t loc, tree function, "invalid memory model argument %d of %qE", x + 1, function); } - else - if (!INTEGRAL_TYPE_P (TREE_TYPE (p))) - { - error_at (loc, "non-integer memory model argument %d of %qE", x + 1, - function); - return 0; - } - } + } return size_0; } @@ -7846,6 +7847,8 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */) if (TREE_CODE (expr) == ADDR_EXPR) expr = TREE_OPERAND (expr, 0); + STRIP_ANY_LOCATION_WRAPPER (expr); + if (TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE && TREE_CODE (expr) == FUNCTION_DECL @@ -8187,12 +8190,30 @@ maybe_suggest_missing_token_insertion (rich_location *richloc, namespace selftest { +/* Verify that fold_for_warn on error_mark_node is safe. */ + +static void +test_fold_for_warn () +{ + ASSERT_EQ (error_mark_node, fold_for_warn (error_mark_node)); +} + +/* Run all of the selftests within this file. */ + +static void +c_common_c_tests () +{ + test_fold_for_warn (); +} + /* Run all of the tests within c-family. */ void c_family_tests (void) { + c_common_c_tests (); c_format_c_tests (); + c_pretty_print_c_tests (); c_spellcheck_cc_tests (); } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 00bfe59..d090881 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1450,6 +1450,7 @@ namespace selftest { /* Declarations for specific families of tests within c-family, by source file, in alphabetical order. */ extern void c_format_c_tests (void); + extern void c_pretty_print_c_tests (void); extern void c_spellcheck_cc_tests (void); /* The entrypoint for running all of the above tests. */ diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index e071145..7a69d5a 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -1536,12 +1536,10 @@ check_format_arg (void *ctx, tree format_tree, location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location); - if (VAR_P (format_tree)) - { - /* Pull out a constant value if the front end didn't. */ - format_tree = decl_constant_value (format_tree); - STRIP_NOPS (format_tree); - } + /* Pull out a constant value if the front end didn't, and handle location + wrappers. */ + format_tree = fold_for_warn (format_tree); + STRIP_NOPS (format_tree); if (integer_zerop (format_tree)) { diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index 6e4f85c..c9dd8ae 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "intl.h" #include "tree-pretty-print.h" +#include "selftest.h" /* The pretty-printer code is primarily designed to closely follow (GNU) C and C++ grammars. That is to be contrasted with spaghetti @@ -1809,7 +1810,8 @@ pp_c_cast_expression (c_pretty_printer *pp, tree e) case FIX_TRUNC_EXPR: CASE_CONVERT: case VIEW_CONVERT_EXPR: - pp_c_type_cast (pp, TREE_TYPE (e)); + if (!location_wrapper_p (e)) + pp_c_type_cast (pp, TREE_TYPE (e)); pp_c_cast_expression (pp, TREE_OPERAND (e, 0)); break; @@ -2400,3 +2402,65 @@ pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t) pp_c_identifier (pp, name); } + +#if CHECKING_P + +namespace selftest { + +/* Selftests for pretty-printing trees. */ + +/* Verify that EXPR printed by c_pretty_printer is EXPECTED, using + LOC as the effective location for any failures. */ + +static void +assert_c_pretty_printer_output (const location &loc, const char *expected, + tree expr) +{ + c_pretty_printer pp; + pp.expression (expr); + ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp)); +} + +/* Helper function for calling assert_c_pretty_printer_output. + This is to avoid having to write SELFTEST_LOCATION. */ + +#define ASSERT_C_PRETTY_PRINTER_OUTPUT(EXPECTED, EXPR) \ + SELFTEST_BEGIN_STMT \ + assert_c_pretty_printer_output ((SELFTEST_LOCATION), \ + (EXPECTED), \ + (EXPR)); \ + SELFTEST_END_STMT + +/* Verify that location wrappers don't show up in pretty-printed output. */ + +static void +test_location_wrappers () +{ + /* VAR_DECL. */ + tree id = get_identifier ("foo"); + tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, + integer_type_node); + tree wrapped_decl = maybe_wrap_with_location (decl, BUILTINS_LOCATION); + ASSERT_NE (wrapped_decl, decl); + ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", decl); + ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", wrapped_decl); + + /* INTEGER_CST. */ + tree int_cst = build_int_cst (integer_type_node, 42); + tree wrapped_cst = maybe_wrap_with_location (int_cst, BUILTINS_LOCATION); + ASSERT_NE (wrapped_cst, int_cst); + ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", int_cst); + ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", wrapped_cst); +} + +/* Run all of the selftests within this file. */ + +void +c_pretty_print_c_tests () +{ + test_location_wrappers (); +} + +} // namespace selftest + +#endif /* CHECKING_P */ diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 33cae8b..7d87c45 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -1868,6 +1868,9 @@ void warn_for_memset (location_t loc, tree arg0, tree arg2, int literal_zero_mask) { + arg0 = fold_for_warn (arg0); + arg2 = fold_for_warn (arg2); + if (warn_memset_transposed_args && integer_zerop (arg2) && (literal_zero_mask & (1 << 2)) != 0 |