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
This commit is contained in:
parent
60d87d8616
commit
9a004410d9
@ -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
|
||||
|
@ -93,6 +93,12 @@ public:
|
||||
set_location (make_location (m_loc, start, finish));
|
||||
}
|
||||
|
||||
cp_expr& maybe_add_location_wrapper ()
|
||||
{
|
||||
m_value = maybe_wrap_with_location (m_value, m_loc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
tree m_value;
|
||||
location_t m_loc;
|
||||
@ -7422,12 +7428,6 @@ extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree, tree);
|
||||
extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
|
||||
extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
|
||||
|
||||
#if CHECKING_P
|
||||
namespace selftest {
|
||||
extern void run_cp_tests (void);
|
||||
} // namespace selftest
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
/* Inline bodies. */
|
||||
|
||||
inline tree
|
||||
@ -7458,6 +7458,24 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
|
||||
return candidate == name;
|
||||
}
|
||||
|
||||
inline bool
|
||||
null_node_p (const_tree expr)
|
||||
{
|
||||
STRIP_ANY_LOCATION_WRAPPER (expr);
|
||||
return expr == null_node;
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
namespace selftest {
|
||||
extern void run_cp_tests (void);
|
||||
|
||||
/* Declarations for specific families of tests within cp,
|
||||
by source file, in alphabetical order. */
|
||||
extern void cp_pt_c_tests ();
|
||||
extern void cp_tree_c_tests (void);
|
||||
} // namespace selftest
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
/* -- end of C++ */
|
||||
|
||||
#endif /* ! GCC_CP_TREE_H */
|
||||
|
@ -1642,7 +1642,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
|
||||
tree conv = NULL_TREE;
|
||||
tree winner = NULL_TREE;
|
||||
|
||||
if (expr == null_node
|
||||
if (null_node_p (expr)
|
||||
&& (desires & WANT_INT)
|
||||
&& !(desires & WANT_NULL))
|
||||
{
|
||||
|
@ -3230,7 +3230,7 @@ args_to_string (tree p, int verbose)
|
||||
reinit_cxx_pp ();
|
||||
for (; p; p = TREE_CHAIN (p))
|
||||
{
|
||||
if (TREE_VALUE (p) == null_node)
|
||||
if (null_node_p (TREE_VALUE (p)))
|
||||
pp_cxx_ws_string (cxx_pp, "NULL");
|
||||
else
|
||||
dump_type (cxx_pp, error_type (TREE_VALUE (p)), flags);
|
||||
|
@ -577,7 +577,7 @@ build_throw (tree exp)
|
||||
return exp;
|
||||
}
|
||||
|
||||
if (exp == null_node)
|
||||
if (exp && null_node_p (exp))
|
||||
warning (0, "throwing NULL, which has integral, not pointer type");
|
||||
|
||||
if (exp != NULL_TREE)
|
||||
|
@ -2890,6 +2890,7 @@ write_expression (tree expr)
|
||||
/* Skip NOP_EXPR and CONVERT_EXPR. They can occur when (say) a pointer
|
||||
argument is converted (via qualification conversions) to another type. */
|
||||
while (CONVERT_EXPR_CODE_P (code)
|
||||
|| location_wrapper_p (expr)
|
||||
/* Parentheses aren't mangled. */
|
||||
|| code == PAREN_EXPR
|
||||
|| code == NON_LVALUE_EXPR)
|
||||
|
@ -2047,7 +2047,8 @@ static tree cp_parser_postfix_open_square_expression
|
||||
static tree cp_parser_postfix_dot_deref_expression
|
||||
(cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
|
||||
static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
|
||||
(cp_parser *, int, bool, bool, bool *, location_t * = NULL);
|
||||
(cp_parser *, int, bool, bool, bool *, location_t * = NULL,
|
||||
bool = false);
|
||||
/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
|
||||
enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
|
||||
static void cp_parser_pseudo_destructor_name
|
||||
@ -6620,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
|
||||
return compound_literal_p;
|
||||
}
|
||||
|
||||
/* Return true if EXPR is the integer constant zero or a complex constant
|
||||
of zero, without any folding, but ignoring location wrappers. */
|
||||
|
||||
static bool
|
||||
literal_integer_zerop (const_tree expr)
|
||||
{
|
||||
STRIP_ANY_LOCATION_WRAPPER (expr);
|
||||
return integer_zerop (expr);
|
||||
}
|
||||
|
||||
/* Parse a postfix-expression.
|
||||
|
||||
postfix-expression:
|
||||
@ -6831,6 +6842,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
||||
location_t typeid_loc
|
||||
= make_location (start_loc, start_loc, close_paren->location);
|
||||
postfix_expression.set_location (typeid_loc);
|
||||
postfix_expression.maybe_add_location_wrapper ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -7088,7 +7100,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
||||
(parser, non_attr,
|
||||
/*cast_p=*/false, /*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL,
|
||||
/*close_paren_loc=*/&close_paren_loc));
|
||||
/*close_paren_loc=*/&close_paren_loc,
|
||||
/*wrap_locations_p=*/true));
|
||||
if (is_builtin_constant_p)
|
||||
{
|
||||
parser->integral_constant_expression_p
|
||||
@ -7164,10 +7177,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
||||
tree arg0 = (*args)[0];
|
||||
tree arg1 = (*args)[1];
|
||||
tree arg2 = (*args)[2];
|
||||
int literal_mask = ((!!integer_zerop (arg1) << 1)
|
||||
| (!!integer_zerop (arg2) << 2));
|
||||
if (TREE_CODE (arg2) == CONST_DECL)
|
||||
arg2 = DECL_INITIAL (arg2);
|
||||
int literal_mask = ((literal_integer_zerop (arg1) << 1)
|
||||
| (literal_integer_zerop (arg2) << 2));
|
||||
warn_for_memset (input_location, arg0, arg2, literal_mask);
|
||||
}
|
||||
|
||||
@ -7621,6 +7632,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
|
||||
ALLOW_EXPANSION_P is true if this expression allows expansion of an
|
||||
argument pack.
|
||||
|
||||
WRAP_LOCATIONS_P is true if expressions within this list for which
|
||||
CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
|
||||
their source locations.
|
||||
|
||||
Returns a vector of trees. Each element is a representation of an
|
||||
assignment-expression. NULL is returned if the ( and or ) are
|
||||
missing. An empty, but allocated, vector is returned on no
|
||||
@ -7640,7 +7655,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
|
||||
bool cast_p,
|
||||
bool allow_expansion_p,
|
||||
bool *non_constant_p,
|
||||
location_t *close_paren_loc)
|
||||
location_t *close_paren_loc,
|
||||
bool wrap_locations_p)
|
||||
{
|
||||
vec<tree, va_gc> *expression_list;
|
||||
bool fold_expr_p = is_attribute_list != non_attr;
|
||||
@ -7663,12 +7679,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
|
||||
= parser->greater_than_is_operator_p;
|
||||
parser->greater_than_is_operator_p = true;
|
||||
|
||||
cp_expr expr (NULL_TREE);
|
||||
|
||||
/* Consume expressions until there are no more. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
|
||||
while (true)
|
||||
{
|
||||
tree expr;
|
||||
|
||||
/* At the beginning of attribute lists, check to see if the
|
||||
next token is an identifier. */
|
||||
if (is_attribute_list == id_attr
|
||||
@ -7722,11 +7738,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
|
||||
expr = make_pack_expansion (expr);
|
||||
}
|
||||
|
||||
if (wrap_locations_p)
|
||||
expr.maybe_add_location_wrapper ();
|
||||
|
||||
/* Add it to the list. We add error_mark_node
|
||||
expressions to the list, so that we can still tell if
|
||||
the correct form for a parenthesized expression-list
|
||||
is found. That gives better errors. */
|
||||
vec_safe_push (expression_list, expr);
|
||||
vec_safe_push (expression_list, expr.get_value ());
|
||||
|
||||
if (expr == error_mark_node)
|
||||
goto skip_comma;
|
||||
@ -7992,6 +8011,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
|
||||
|
||||
cp_expr ret_expr (ret);
|
||||
ret_expr.set_location (compound_loc);
|
||||
ret_expr = ret_expr.maybe_add_location_wrapper ();
|
||||
return ret_expr;
|
||||
}
|
||||
|
||||
@ -9831,6 +9851,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
||||
parser->integral_constant_expression_p = save_ice_p;
|
||||
parser->non_integral_constant_expression_p = save_non_ice_p;
|
||||
|
||||
expr = expr.maybe_add_location_wrapper ();
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
83
gcc/cp/pt.c
83
gcc/cp/pt.c
@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "type-utils.h"
|
||||
#include "gimplify.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "selftest.h"
|
||||
|
||||
/* The type of functions taking a tree, and some additional data, and
|
||||
returning an int. */
|
||||
@ -14924,6 +14925,18 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||
/* Ordinary template template argument. */
|
||||
return t;
|
||||
|
||||
case NON_LVALUE_EXPR:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
{
|
||||
/* Handle location wrappers by substituting the wrapped node
|
||||
first, *then* reusing the resulting type. Doing the type
|
||||
first ensures that we handle template parameters and
|
||||
parameter pack expansions. */
|
||||
gcc_assert (location_wrapper_p (t));
|
||||
tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
|
||||
return maybe_wrap_with_location (op0, EXPR_LOCATION (t));
|
||||
}
|
||||
|
||||
case CAST_EXPR:
|
||||
case REINTERPRET_CAST_EXPR:
|
||||
case CONST_CAST_EXPR:
|
||||
@ -18291,6 +18304,16 @@ tsubst_copy_and_build (tree t,
|
||||
case REQUIRES_EXPR:
|
||||
RETURN (tsubst_requires_expr (t, args, complain, in_decl));
|
||||
|
||||
case NON_LVALUE_EXPR:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
/* We should only see these for location wrapper nodes, or within
|
||||
instantiate_non_dependent_expr (when args is NULL_TREE). */
|
||||
gcc_assert (location_wrapper_p (t) || args == NULL_TREE);
|
||||
if (location_wrapper_p (t))
|
||||
RETURN (maybe_wrap_with_location (RECUR (TREE_OPERAND (t, 0)),
|
||||
EXPR_LOCATION (t)));
|
||||
/* fallthrough. */
|
||||
|
||||
default:
|
||||
/* Handle Objective-C++ constructs, if appropriate. */
|
||||
{
|
||||
@ -24982,6 +25005,7 @@ resolve_typename_type (tree type, bool only_current_p)
|
||||
tree
|
||||
build_non_dependent_expr (tree expr)
|
||||
{
|
||||
tree orig_expr = expr;
|
||||
tree inner_expr;
|
||||
|
||||
/* When checking, try to get a constant value for all non-dependent
|
||||
@ -24998,6 +25022,8 @@ build_non_dependent_expr (tree expr)
|
||||
&& !expanding_concept ())
|
||||
fold_non_dependent_expr (expr);
|
||||
|
||||
STRIP_ANY_LOCATION_WRAPPER (expr);
|
||||
|
||||
/* Preserve OVERLOADs; the functions must be available to resolve
|
||||
types. */
|
||||
inner_expr = expr;
|
||||
@ -25009,36 +25035,36 @@ build_non_dependent_expr (tree expr)
|
||||
inner_expr = TREE_OPERAND (inner_expr, 1);
|
||||
if (is_overloaded_fn (inner_expr)
|
||||
|| TREE_CODE (inner_expr) == OFFSET_REF)
|
||||
return expr;
|
||||
return orig_expr;
|
||||
/* There is no need to return a proxy for a variable. */
|
||||
if (VAR_P (expr))
|
||||
return expr;
|
||||
return orig_expr;
|
||||
/* Preserve string constants; conversions from string constants to
|
||||
"char *" are allowed, even though normally a "const char *"
|
||||
cannot be used to initialize a "char *". */
|
||||
if (TREE_CODE (expr) == STRING_CST)
|
||||
return expr;
|
||||
return orig_expr;
|
||||
/* Preserve void and arithmetic constants, as an optimization -- there is no
|
||||
reason to create a new node. */
|
||||
if (TREE_CODE (expr) == VOID_CST
|
||||
|| TREE_CODE (expr) == INTEGER_CST
|
||||
|| TREE_CODE (expr) == REAL_CST)
|
||||
return expr;
|
||||
return orig_expr;
|
||||
/* Preserve THROW_EXPRs -- all throw-expressions have type "void".
|
||||
There is at least one place where we want to know that a
|
||||
particular expression is a throw-expression: when checking a ?:
|
||||
expression, there are special rules if the second or third
|
||||
argument is a throw-expression. */
|
||||
if (TREE_CODE (expr) == THROW_EXPR)
|
||||
return expr;
|
||||
return orig_expr;
|
||||
|
||||
/* Don't wrap an initializer list, we need to be able to look inside. */
|
||||
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
|
||||
return expr;
|
||||
return orig_expr;
|
||||
|
||||
/* Don't wrap a dummy object, we need to be able to test for it. */
|
||||
if (is_dummy_object (expr))
|
||||
return expr;
|
||||
return orig_expr;
|
||||
|
||||
if (TREE_CODE (expr) == COND_EXPR)
|
||||
return build3 (COND_EXPR,
|
||||
@ -26601,4 +26627,47 @@ print_template_statistics (void)
|
||||
type_specializations->collisions ());
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
/* Verify that build_non_dependent_expr () works, for various expressions,
|
||||
and that location wrappers don't affect the results. */
|
||||
|
||||
static void
|
||||
test_build_non_dependent_expr ()
|
||||
{
|
||||
location_t loc = BUILTINS_LOCATION;
|
||||
|
||||
/* Verify constants, without and with location wrappers. */
|
||||
tree int_cst = build_int_cst (integer_type_node, 42);
|
||||
ASSERT_EQ (int_cst, build_non_dependent_expr (int_cst));
|
||||
|
||||
tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
|
||||
ASSERT_EQ (wrapped_int_cst, build_non_dependent_expr (wrapped_int_cst));
|
||||
|
||||
tree string_lit = build_string (4, "foo");
|
||||
TREE_TYPE (string_lit) = char_array_type_node;
|
||||
string_lit = fix_string_type (string_lit);
|
||||
ASSERT_EQ (string_lit, build_non_dependent_expr (string_lit));
|
||||
|
||||
tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
|
||||
ASSERT_EQ (wrapped_string_lit,
|
||||
build_non_dependent_expr (wrapped_string_lit));
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file. */
|
||||
|
||||
void
|
||||
cp_pt_c_tests ()
|
||||
{
|
||||
test_build_non_dependent_expr ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
#include "gt-cp-pt.h"
|
||||
|
@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "stringpool.h"
|
||||
#include "attribs.h"
|
||||
#include "flags.h"
|
||||
#include "selftest.h"
|
||||
|
||||
static tree bot_manip (tree *, int *, void *);
|
||||
static tree bot_replace (tree *, int *, void *);
|
||||
@ -240,6 +241,11 @@ lvalue_kind (const_tree ref)
|
||||
case NON_DEPENDENT_EXPR:
|
||||
return lvalue_kind (TREE_OPERAND (ref, 0));
|
||||
|
||||
case VIEW_CONVERT_EXPR:
|
||||
if (location_wrapper_p (ref))
|
||||
return lvalue_kind (TREE_OPERAND (ref, 0));
|
||||
/* Fallthrough. */
|
||||
|
||||
default:
|
||||
if (!TREE_TYPE (ref))
|
||||
return clk_none;
|
||||
@ -5346,4 +5352,64 @@ lang_check_failed (const char* file, int line, const char* function)
|
||||
}
|
||||
#endif /* ENABLE_TREE_CHECKING */
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
/* Verify that lvalue_kind () works, for various expressions,
|
||||
and that location wrappers don't affect the results. */
|
||||
|
||||
static void
|
||||
test_lvalue_kind ()
|
||||
{
|
||||
location_t loc = BUILTINS_LOCATION;
|
||||
|
||||
/* Verify constants and parameters, without and with
|
||||
location wrappers. */
|
||||
tree int_cst = build_int_cst (integer_type_node, 42);
|
||||
ASSERT_EQ (clk_none, lvalue_kind (int_cst));
|
||||
|
||||
tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
|
||||
ASSERT_EQ (clk_none, lvalue_kind (wrapped_int_cst));
|
||||
|
||||
tree string_lit = build_string (4, "foo");
|
||||
TREE_TYPE (string_lit) = char_array_type_node;
|
||||
string_lit = fix_string_type (string_lit);
|
||||
ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit));
|
||||
|
||||
tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
|
||||
ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit));
|
||||
|
||||
tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
|
||||
get_identifier ("some_parm"),
|
||||
integer_type_node);
|
||||
ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
|
||||
|
||||
tree wrapped_parm = maybe_wrap_with_location (parm, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_parm));
|
||||
ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_parm));
|
||||
|
||||
/* Verify that lvalue_kind of std::move on a parm isn't
|
||||
affected by location wrappers. */
|
||||
tree rvalue_ref_of_parm = move (parm);
|
||||
ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
|
||||
tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
|
||||
ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file. */
|
||||
|
||||
void
|
||||
cp_tree_c_tests ()
|
||||
{
|
||||
test_lvalue_kind ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
|
||||
#include "gt-cp-tree.h"
|
||||
|
@ -2202,6 +2202,8 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
|
||||
&& !same_type_p (t, wchar_type_node))
|
||||
return 0;
|
||||
|
||||
STRIP_ANY_LOCATION_WRAPPER (exp);
|
||||
|
||||
if (TREE_CODE (exp) == STRING_CST)
|
||||
{
|
||||
/* Make sure that we don't try to convert between char and wide chars. */
|
||||
@ -4317,7 +4319,7 @@ cp_build_binary_op (location_t location,
|
||||
}
|
||||
|
||||
/* Issue warnings about peculiar, but valid, uses of NULL. */
|
||||
if ((orig_op0 == null_node || orig_op1 == null_node)
|
||||
if ((null_node_p (orig_op0) || null_node_p (orig_op1))
|
||||
/* It's reasonable to use pointer values as operands of &&
|
||||
and ||, so NULL is no exception. */
|
||||
&& code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR
|
||||
@ -5734,7 +5736,7 @@ build_address (tree t)
|
||||
if (error_operand_p (t) || !cxx_mark_addressable (t))
|
||||
return error_mark_node;
|
||||
gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR);
|
||||
t = build_fold_addr_expr (t);
|
||||
t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t);
|
||||
if (TREE_CODE (t) != ADDR_EXPR)
|
||||
t = rvalue (t);
|
||||
return t;
|
||||
|
@ -1,3 +1,21 @@
|
||||
2018-01-10 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2018-01-10 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* gcc.target/i386/pr82618.c (dg-options): Add -mno-stv.
|
||||
|
@ -1,9 +1,6 @@
|
||||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
/* A collection of calls where argument 2 is of the wrong type.
|
||||
|
||||
TODO: we should put the caret and underline for the diagnostic
|
||||
at the second argument, rather than the close paren. */
|
||||
/* A collection of calls where argument 2 is of the wrong type. */
|
||||
|
||||
/* decl, with argname. */
|
||||
|
||||
@ -14,7 +11,7 @@ int test_1 (int first, int second, float third)
|
||||
return callee_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return callee_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
@ -32,7 +29,7 @@ int test_2 (int first, int second, float third)
|
||||
return callee_2 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return callee_2 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
@ -53,7 +50,7 @@ int test_3 (int first, int second, float third)
|
||||
return callee_3 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return callee_3 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
@ -71,7 +68,7 @@ int test_4 (int first, int second, float third)
|
||||
return s4::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return s4::member_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
struct s4 { static int member_1 (int one, const char *two, float three); };
|
||||
@ -89,7 +86,7 @@ int test_5 (int first, int second, float third)
|
||||
return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return inst.member_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
struct s5 { int member_1 (int one, const char *two, float three); };
|
||||
@ -106,7 +103,7 @@ int test_6 (int first, int second, float third, s6 *ptr)
|
||||
return ptr->member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return ptr->member_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
struct s6 { int member_1 (int one, const char *two, float three); };
|
||||
@ -128,7 +125,7 @@ int test_7 (int first, int second, float third)
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return test_7 <const char *> (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int test_7 (int one, T two, float three);
|
||||
@ -146,7 +143,7 @@ int test_8 (int first, int second, float third)
|
||||
return s8 <const char *>::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return s8 <const char *>::member_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
struct s8 { static int member_1 (int one, T two, float three); };
|
||||
@ -165,7 +162,7 @@ int test_9 (int first, int second, float third)
|
||||
return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return inst.member_1 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
struct s9 { int member_1 (int one, T two, float three); };
|
||||
@ -182,7 +179,7 @@ int test_10 (int first, int second, float third)
|
||||
return callee_10 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return callee_10 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
@ -200,7 +197,7 @@ int test_11 (int first, int second, float third)
|
||||
return callee_11 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return callee_11 (first, second, third);
|
||||
^
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
|
@ -19,6 +19,113 @@ extern void __emit_expression_range (int dummy, ...);
|
||||
|
||||
int global;
|
||||
|
||||
void test_global (void)
|
||||
{
|
||||
__emit_expression_range (0, global); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, global);
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_param (int param)
|
||||
{
|
||||
__emit_expression_range (0, param); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, param);
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_local (void)
|
||||
{
|
||||
int local = 5;
|
||||
|
||||
__emit_expression_range (0, local); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, local);
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_integer_constants (void)
|
||||
{
|
||||
__emit_expression_range (0, 1234); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 1234);
|
||||
^~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
/* Ensure that zero works. */
|
||||
|
||||
__emit_expression_range (0, 0); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 0);
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_character_constants (void)
|
||||
{
|
||||
__emit_expression_range (0, 'a'); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 'a');
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_floating_constants (void)
|
||||
{
|
||||
__emit_expression_range (0, 98.6); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 98.6);
|
||||
^~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, .6); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, .6);
|
||||
^~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, 98.); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 98.);
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, 6.022140857e23 ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 6.022140857e23 );
|
||||
^~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, 98.6f ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 98.6f );
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, 6.022140857e23l ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 6.022140857e23l );
|
||||
^~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
enum test_enum {
|
||||
TEST_ENUM_VALUE
|
||||
};
|
||||
|
||||
void test_enumeration_constant (void)
|
||||
{
|
||||
__emit_expression_range (0, TEST_ENUM_VALUE ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, TEST_ENUM_VALUE );
|
||||
^~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_parentheses (int a, int b)
|
||||
{
|
||||
__emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
|
||||
@ -103,67 +210,36 @@ void test_postfix_incdec (int i)
|
||||
|
||||
void test_sizeof (int i)
|
||||
{
|
||||
__emit_expression_range (0, sizeof(int) + i); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, sizeof i ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, sizeof(int) + i);
|
||||
~~~~~~~~~~~~^~~
|
||||
__emit_expression_range (0, sizeof i );
|
||||
^~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + sizeof(int)); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, sizeof (char) ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + sizeof(int));
|
||||
~~^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, sizeof i + i); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, sizeof i + i);
|
||||
~~~~~~~~~^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + sizeof i); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + sizeof i);
|
||||
~~^~~~~~~~~~
|
||||
__emit_expression_range (0, sizeof (char) );
|
||||
^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_alignof (int i)
|
||||
{
|
||||
__emit_expression_range (0, alignof(int) + i); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, alignof(int)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, alignof(int) + i);
|
||||
~~~~~~~~~~~~~^~~
|
||||
__emit_expression_range (0, alignof(int));
|
||||
^~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + alignof(int)); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, __alignof__(int)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + alignof(int));
|
||||
~~^~~~~~~~~~~~~~
|
||||
__emit_expression_range (0, __alignof__(int));
|
||||
^~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, __alignof__(int) + i); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, __alignof__ i); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, __alignof__(int) + i);
|
||||
~~~~~~~~~~~~~~~~~^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + __alignof__(int)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + __alignof__(int));
|
||||
~~^~~~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, __alignof__ i + i); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, __alignof__ i + i);
|
||||
~~~~~~~~~~~~~~^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + __alignof__ i); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + __alignof__ i);
|
||||
~~^~~~~~~~~~~~~~~
|
||||
__emit_expression_range (0, __alignof__ i);
|
||||
^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
@ -200,6 +276,15 @@ void test_indirection (int *ptr)
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_unary_plus (int i)
|
||||
{
|
||||
__emit_expression_range (0, +i ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, +i );
|
||||
^~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_unary_minus (int i)
|
||||
{
|
||||
__emit_expression_range (0, -i ); /* { dg-warning "range" } */
|
||||
@ -471,53 +556,36 @@ void test_comma_operator (int a, int b)
|
||||
|
||||
/* Literals. **************************************************/
|
||||
|
||||
/* We can't test the ranges of literals directly, since the underlying
|
||||
tree nodes don't retain a location. However, we can test that they
|
||||
have ranges during parsing by building compound expressions using
|
||||
them, and verifying the ranges of the compound expressions. */
|
||||
|
||||
void test_string_literals (int i)
|
||||
void test_string_literals ()
|
||||
{
|
||||
__emit_expression_range (0, "foo"[i] ); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, "0123456789"); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, "foo"[i] );
|
||||
~~~~~~~^
|
||||
__emit_expression_range (0, "0123456789");
|
||||
^~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, &"foo" "bar" ); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, "foo" "bar" ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, &"foo" "bar" );
|
||||
^~~~~~~~~~~~
|
||||
__emit_expression_range (0, "foo" "bar" );
|
||||
^~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
void test_numeric_literals (int i)
|
||||
{
|
||||
__emit_expression_range (0, 42 + i ); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, 42 ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, 42 + i );
|
||||
~~~^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + 42 ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + 42 );
|
||||
~~^~~~
|
||||
__emit_expression_range (0, 42 );
|
||||
^~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
/* Verify locations of negative literals (via folding of
|
||||
unary negation). */
|
||||
|
||||
__emit_expression_range (0, -42 + i ); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, -42 ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, -42 + i );
|
||||
~~~~^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i + -42 ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + -42 );
|
||||
~~^~~~~
|
||||
__emit_expression_range (0, -42 );
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, i ? 0 : -1 ); /* { dg-warning "range" } */
|
||||
@ -638,16 +706,10 @@ struct s { int i; float f; };
|
||||
|
||||
void test_builtin_offsetof (int i)
|
||||
{
|
||||
__emit_expression_range (0, i + __builtin_offsetof (struct s, f) ); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, __builtin_offsetof (struct s, f) ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, i + __builtin_offsetof (struct s, f) );
|
||||
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, __builtin_offsetof (struct s, f) + i ); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, __builtin_offsetof (struct s, f) + i );
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
|
||||
__emit_expression_range (0, __builtin_offsetof (struct s, f) );
|
||||
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
@ -856,28 +918,22 @@ namespace std
|
||||
|
||||
void test_typeid (int i)
|
||||
{
|
||||
__emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, typeid(i)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, &typeid(i));
|
||||
^~~~~~~~~~
|
||||
__emit_expression_range (0, typeid(i));
|
||||
^~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, &typeid(int)); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, typeid(int)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, &typeid(int));
|
||||
^~~~~~~~~~~~
|
||||
__emit_expression_range (0, typeid(int));
|
||||
^~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */
|
||||
__emit_expression_range (0, typeid(i * 2)); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, &typeid(i * 2));
|
||||
^~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
__emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
__emit_expression_range (0, typeid(int).foo);
|
||||
~~~~~~~~~~~~^~~
|
||||
__emit_expression_range (0, typeid(i * 2));
|
||||
^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
|
@ -7,4 +7,6 @@ foo (void)
|
||||
{
|
||||
const char *const msg = "abc";
|
||||
bar (1, msg);
|
||||
bar (1, msg + 1);
|
||||
bar (1, 1 + msg);
|
||||
}
|
||||
|
@ -1116,6 +1116,9 @@ struct GTY(()) tree_base {
|
||||
SSA_NAME_IS_VIRTUAL_OPERAND in
|
||||
SSA_NAME
|
||||
|
||||
EXPR_LOCATION_WRAPPER_P in
|
||||
NON_LVALUE_EXPR, VIEW_CONVERT_EXPR
|
||||
|
||||
private_flag:
|
||||
|
||||
TREE_PRIVATE in
|
||||
|
103
gcc/tree.c
103
gcc/tree.c
@ -12167,6 +12167,8 @@ tree_nop_conversion (const_tree exp)
|
||||
{
|
||||
tree outer_type, inner_type;
|
||||
|
||||
if (location_wrapper_p (exp))
|
||||
return true;
|
||||
if (!CONVERT_EXPR_P (exp)
|
||||
&& TREE_CODE (exp) != NON_LVALUE_EXPR)
|
||||
return false;
|
||||
@ -14093,6 +14095,42 @@ set_source_range (tree expr, source_range src_range)
|
||||
return adhoc;
|
||||
}
|
||||
|
||||
/* Return EXPR, potentially wrapped with a node expression LOC,
|
||||
if !CAN_HAVE_LOCATION_P (expr).
|
||||
|
||||
NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
|
||||
VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.
|
||||
|
||||
Wrapper nodes can be identified using location_wrapper_p. */
|
||||
|
||||
tree
|
||||
maybe_wrap_with_location (tree expr, location_t loc)
|
||||
{
|
||||
if (expr == NULL)
|
||||
return NULL;
|
||||
if (loc == UNKNOWN_LOCATION)
|
||||
return expr;
|
||||
if (CAN_HAVE_LOCATION_P (expr))
|
||||
return expr;
|
||||
/* We should only be adding wrappers for constants and for decls,
|
||||
or for some exceptional tree nodes (e.g. BASELINK in the C++ FE). */
|
||||
gcc_assert (CONSTANT_CLASS_P (expr)
|
||||
|| DECL_P (expr)
|
||||
|| EXCEPTIONAL_CLASS_P (expr));
|
||||
|
||||
/* For now, don't add wrappers to exceptional tree nodes, to minimize
|
||||
any impact of the wrapper nodes. */
|
||||
if (EXCEPTIONAL_CLASS_P (expr))
|
||||
return expr;
|
||||
|
||||
tree_code code = (CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST
|
||||
? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR);
|
||||
tree wrapper = build1_loc (loc, code, TREE_TYPE (expr), expr);
|
||||
/* Mark this node as being a wrapper. */
|
||||
EXPR_LOCATION_WRAPPER_P (wrapper) = 1;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/* Return the name of combined function FN, for debugging purposes. */
|
||||
|
||||
const char *
|
||||
@ -14464,6 +14502,70 @@ test_vector_cst_patterns ()
|
||||
check_vector_cst_fill (elements, build_vector (vector_type, elements), 4);
|
||||
}
|
||||
|
||||
/* Verify that STRIP_NOPS (NODE) is EXPECTED.
|
||||
Helper function for test_location_wrappers, to deal with STRIP_NOPS
|
||||
modifying its argument in-place. */
|
||||
|
||||
static void
|
||||
check_strip_nops (tree node, tree expected)
|
||||
{
|
||||
STRIP_NOPS (node);
|
||||
ASSERT_EQ (expected, node);
|
||||
}
|
||||
|
||||
/* Verify location wrappers. */
|
||||
|
||||
static void
|
||||
test_location_wrappers ()
|
||||
{
|
||||
location_t loc = BUILTINS_LOCATION;
|
||||
|
||||
/* Wrapping a constant. */
|
||||
tree int_cst = build_int_cst (integer_type_node, 42);
|
||||
ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_cst));
|
||||
ASSERT_FALSE (location_wrapper_p (int_cst));
|
||||
|
||||
tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
|
||||
ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_cst));
|
||||
ASSERT_EQ (int_cst, tree_strip_any_location_wrapper (wrapped_int_cst));
|
||||
|
||||
/* Wrapping a STRING_CST. */
|
||||
tree string_cst = build_string (4, "foo");
|
||||
ASSERT_FALSE (CAN_HAVE_LOCATION_P (string_cst));
|
||||
ASSERT_FALSE (location_wrapper_p (string_cst));
|
||||
|
||||
tree wrapped_string_cst = maybe_wrap_with_location (string_cst, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_string_cst));
|
||||
ASSERT_EQ (VIEW_CONVERT_EXPR, TREE_CODE (wrapped_string_cst));
|
||||
ASSERT_EQ (loc, EXPR_LOCATION (wrapped_string_cst));
|
||||
ASSERT_EQ (string_cst, tree_strip_any_location_wrapper (wrapped_string_cst));
|
||||
|
||||
|
||||
/* Wrapping a variable. */
|
||||
tree int_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("some_int_var"),
|
||||
integer_type_node);
|
||||
ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_var));
|
||||
ASSERT_FALSE (location_wrapper_p (int_var));
|
||||
|
||||
tree wrapped_int_var = maybe_wrap_with_location (int_var, loc);
|
||||
ASSERT_TRUE (location_wrapper_p (wrapped_int_var));
|
||||
ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_var));
|
||||
ASSERT_EQ (int_var, tree_strip_any_location_wrapper (wrapped_int_var));
|
||||
|
||||
/* Verify that "reinterpret_cast<int>(some_int_var)" is not a location
|
||||
wrapper. */
|
||||
tree r_cast = build1 (NON_LVALUE_EXPR, integer_type_node, int_var);
|
||||
ASSERT_FALSE (location_wrapper_p (r_cast));
|
||||
ASSERT_EQ (r_cast, tree_strip_any_location_wrapper (r_cast));
|
||||
|
||||
/* Verify that STRIP_NOPS removes wrappers. */
|
||||
check_strip_nops (wrapped_int_cst, int_cst);
|
||||
check_strip_nops (wrapped_string_cst, string_cst);
|
||||
check_strip_nops (wrapped_int_var, int_var);
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file. */
|
||||
|
||||
void
|
||||
@ -14473,6 +14575,7 @@ tree_c_tests ()
|
||||
test_identifiers ();
|
||||
test_labels ();
|
||||
test_vector_cst_patterns ();
|
||||
test_location_wrappers ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
47
gcc/tree.h
47
gcc/tree.h
@ -483,6 +483,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
||||
#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
|
||||
(EXP) = tree_ssa_strip_useless_type_conversions (EXP)
|
||||
|
||||
/* Remove any VIEW_CONVERT_EXPR or NON_LVALUE_EXPR that's purely
|
||||
in use to provide a location_t. */
|
||||
|
||||
#define STRIP_ANY_LOCATION_WRAPPER(EXP) \
|
||||
(EXP) = tree_strip_any_location_wrapper (CONST_CAST_TREE (EXP))
|
||||
|
||||
/* Nonzero if TYPE represents a vector type. */
|
||||
|
||||
#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
|
||||
@ -1180,6 +1186,8 @@ get_expr_source_range (tree expr)
|
||||
|
||||
extern void protected_set_expr_location (tree, location_t);
|
||||
|
||||
extern tree maybe_wrap_with_location (tree, location_t);
|
||||
|
||||
/* In a TARGET_EXPR node. */
|
||||
#define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
|
||||
#define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1)
|
||||
@ -3726,6 +3734,45 @@ valid_vector_subparts_p (poly_uint64 subparts)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* In NON_LVALUE_EXPR and VIEW_CONVERT_EXPR, set when this node is merely a
|
||||
wrapper added to express a location_t on behalf of the node's child
|
||||
(e.g. by maybe_wrap_with_location). */
|
||||
|
||||
#define EXPR_LOCATION_WRAPPER_P(NODE) \
|
||||
(TREE_CHECK2(NODE, NON_LVALUE_EXPR, VIEW_CONVERT_EXPR)->base.public_flag)
|
||||
|
||||
/* Test if EXP is merely a wrapper node, added to express a location_t
|
||||
on behalf of the node's child (e.g. by maybe_wrap_with_location). */
|
||||
|
||||
inline bool
|
||||
location_wrapper_p (const_tree exp)
|
||||
{
|
||||
/* A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and
|
||||
the flag EXPR_LOCATION_WRAPPER_P is set.
|
||||
It normally has the same type as its operand, but it can have a
|
||||
different one if the type of the operand has changed (e.g. when
|
||||
merging duplicate decls).
|
||||
|
||||
NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
|
||||
VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST. */
|
||||
if ((TREE_CODE (exp) == NON_LVALUE_EXPR
|
||||
|| TREE_CODE (exp) == VIEW_CONVERT_EXPR)
|
||||
&& EXPR_LOCATION_WRAPPER_P (exp))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Implementation of STRIP_ANY_LOCATION_WRAPPER. */
|
||||
|
||||
inline tree
|
||||
tree_strip_any_location_wrapper (tree exp)
|
||||
{
|
||||
if (location_wrapper_p (exp))
|
||||
return TREE_OPERAND (exp, 0);
|
||||
else
|
||||
return exp;
|
||||
}
|
||||
|
||||
#define error_mark_node global_trees[TI_ERROR_MARK]
|
||||
|
||||
#define intQI_type_node global_trees[TI_INTQI_TYPE]
|
||||
|
Loading…
Reference in New Issue
Block a user