Skip to content
Permalink
Browse files

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.



git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256448 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information...
dmalcolm
dmalcolm committed Jan 10, 2018
1 parent 7d2193d commit d76863c8a62920c5a156125e68ad315b47bfcd24
@@ -1,3 +1,20 @@
2018-01-10 David Malcolm <dmalcolm@redhat.com>

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.

2018-01-10 H.J. Lu <hongjiu.lu@intel.com>

PR target/83735
@@ -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>
@@ -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 ();
}

@@ -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. */
@@ -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))
{
@@ -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 */
@@ -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
@@ -1,3 +1,55 @@
2018-01-10 David Malcolm <dmalcolm@redhat.com>

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.

2018-01-10 Marek Polacek <polacek@redhat.com>

PR c++/82541
@@ -528,6 +528,8 @@ null_ptr_cst_p (tree t)

if (cxx_dialect >= cxx11)
{
STRIP_ANY_LOCATION_WRAPPER (t);

/* Core issue 903 says only literal 0 is a null pointer constant. */
if (TREE_CODE (type) == INTEGER_TYPE
&& !char_type_p (type)
@@ -6531,7 +6533,7 @@ static void
conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
{
/* Issue warnings about peculiar, but valid, uses of NULL. */
if (expr == null_node && TREE_CODE (totype) != BOOLEAN_TYPE
if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
&& ARITHMETIC_TYPE_P (totype))
{
source_location loc =
@@ -7865,7 +7867,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
func(NULL);
}
*/
if (arg == null_node
if (null_node_p (arg)
&& DECL_TEMPLATE_INFO (fn)
&& cand->template_decl
&& !(flags & LOOKUP_EXPLICIT_TMPL_ARGS))
@@ -2064,7 +2064,7 @@ clear_fold_cache (void)

/* This function tries to fold an expression X.
To avoid combinatorial explosion, folding results are kept in fold_cache.
If we are processing a template or X is invalid, we don't fold at all.
If X is invalid, we don't fold at all.
For performance reasons we don't cache expressions representing a
declaration or constant.
Function returns X or its folded variant. */
@@ -2081,8 +2081,7 @@ cp_fold (tree x)
if (!x || x == error_mark_node)
return x;

if (processing_template_decl
|| (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
return x;

/* Don't bother to cache DECLs or constants. */
@@ -247,6 +247,8 @@ run_cp_tests (void)
c_family_tests ();

/* Additional C++-specific tests. */
cp_pt_c_tests ();
cp_tree_c_tests ();
}

} // namespace selftest
Oops, something went wrong.

0 comments on commit d76863c

Please sign in to comment.
You can’t perform that action at this time.