aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-01-10 19:40:55 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-01-10 19:40:55 +0000
commit9a004410d9f64d658864a899ab911ae9a31c444c (patch)
tree74d2d62696c26cee3eb63313868f3150f67c4aa3 /gcc/cp
parent60d87d86163186669af4b0f493be462e2aadca77 (diff)
downloadgcc-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/cp')
-rw-r--r--gcc/cp/ChangeLog52
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/cp-gimplify.c5
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/cp-tree.h30
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/mangle.c1
-rw-r--r--gcc/cp/parser.c41
-rw-r--r--gcc/cp/pt.c83
-rw-r--r--gcc/cp/tree.c66
-rw-r--r--gcc/cp/typeck.c6
13 files changed, 265 insertions, 33 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d664bd2..d24c934 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 87bbf3c..c822a70 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index eda493a..e97247c 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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. */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 9992bc2c..6007094 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dff72a84..9c6c179 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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 */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 444a24f..7ed2aad 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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))
{
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index d8fbbde..cb1dcf3 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index b192762..669bf9f 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -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)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index bd74543..94c4bed 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f9181b7..b16597c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2deccd8..bb5908f 100644
--- a/gcc/cp/pt.c
+++ b/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"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 87b45e0..ed51c28 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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"
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dc04b4b..669a2b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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;