aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-12-19 15:08:21 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-12-19 15:08:21 +0000
commitdfd7fdca2ac17d8b823a16700525824ca312ade0 (patch)
tree2bf4bf940ff4bc674f358d0968d5560dbdb0ed76 /gcc/cp/parser.c
parent9a0317e70007d6558e53a2ba5b104ff09b2e9642 (diff)
downloadgcc-dfd7fdca2ac17d8b823a16700525824ca312ade0.zip
gcc-dfd7fdca2ac17d8b823a16700525824ca312ade0.tar.gz
gcc-dfd7fdca2ac17d8b823a16700525824ca312ade0.tar.bz2
C++: more location wrapper nodes (PR c++/43064, PR c++/43486)
This is v6 of the patch, as posted to: https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01331.html The C++ frontend gained various location wrapper nodes in r256448 (GCC 8). That patch: https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00799.html added wrapper nodes around all nodes with !CAN_HAVE_LOCATION_P for: * arguments at callsites, and for * typeid, alignof, sizeof, and offsetof. This is a followup to that patch, adding many more location wrappers to the C++ frontend. It adds location wrappers for nodes with !CAN_HAVE_LOCATION_P to: * all literal nodes (in cp_parser_primary_expression) * all id-expression nodes (in finish_id_expression), except within a decltype. * all mem-initializer nodes within a mem-initializer-list (in cp_parser_mem_initializer) However, the patch also adds some suppressions: regions in the parser for which wrapper nodes will not be created: * within a template-parameter-list or template-argument-list (in cp_parser_template_parameter_list and cp_parser_template_argument_list respectively), to avoid encoding the spelling location of the nodes in types. For example, "array<10>" and "array<10>" are the same type, despite the fact that the two different "10" tokens are spelled in different locations in the source. * within a gnu-style attribute (none of are handlers are set up to cope with location wrappers yet) * within various OpenMP clauses The patch enables various improvements to locations for bad initializations, for -Wchar-subscripts, and enables various other improvements in the followup patch. For example, given the followup buggy mem-initializer: class X { X() : bad(42), good(42) { } void* bad; int good; }; previously, our diagnostic was on the final close parenthesis of the mem-initializer-list, leaving it unclear where the problem is: t.cc: In constructor 'X::X()': t.cc:3:16: error: invalid conversion from 'int' to 'void*' [-fpermissive] 3 | good(42) | ^ | | | int whereas with the patch we highlight which expression is bogus: t.cc: In constructor 'X::X()': t.cc:2:13: error: invalid conversion from 'int' to 'void*' [-fpermissive] 2 | X() : bad(42), | ^~ | | | int Similarly, the diagnostic for this bogus initialization: i.cc:1:44: error: initializer-string for array of chars is too long [-fpermissive] 1 | char test[3][4] = { "ok", "too long", "ok" }; | ^ is improved by the patch so that it indicates which string is too long: i.cc:1:27: error: initializer-string for array of chars is too long [-fpermissive] 1 | char test[3][4] = { "ok", "too long", "ok" }; | ^~~~~~~~~~ gcc/c-family/ChangeLog: PR c++/43064 PR c++/43486 * c-common.c (unsafe_conversion_p): Fold any location wrapper. (verify_tree): Handle location wrappers. (c_common_truthvalue_conversion): Strip any location wrapper. Handle CONST_DECL. (fold_offsetof): Strip any location wrapper. (complete_array_type): Likewise for initial_value. (convert_vector_to_array_for_subscript): Call fold_for_warn on the index before checking for INTEGER_CST. * c-pretty-print.c (c_pretty_printer::primary_expression): Don't print parentheses around location wrappers. * c-warn.c (warn_logical_operator): Call fold_for_warn on op_right before checking for INTEGER_CST. (warn_tautological_bitwise_comparison): Call tree_strip_any_location_wrapper on lhs, rhs, and bitop's operand before checking for INTEGER_CST. (readonly_error): Strip any location wrapper. (warn_array_subscript_with_type_char): Strip location wrappers before checking for INTEGER_CST. Use the location of the index if available. gcc/ChangeLog: PR c++/43064 PR c++/43486 * convert.c: Include "selftest.h". (preserve_any_location_wrapper): New function. (convert_to_pointer_maybe_fold): Update to handle location wrappers. (convert_to_real_maybe_fold): Likewise. (convert_to_integer_1): Strip expr when using TREE_OVERFLOW. Handle location wrappers when checking for INTEGER_CST. (convert_to_integer_maybe_fold): Update to handle location wrappers. (convert_to_complex_maybe_fold): Likewise. (selftest::test_convert_to_integer_maybe_fold): New functions. (selftest::convert_c_tests): New function. * convert.h (preserve_any_location_wrapper): New decl. * fold-const.c (size_binop_loc): Strip location wrappers when using TREE_OVERFLOW. (operand_equal_p): Strip any location wrappers. (integer_valued_real_p): Strip any location wrapper. * selftest-run-tests.c (selftest::run_tests): Call selftest::convert_c_tests. * selftest.h (selftest::convert_c_tests): New decl. * tree.c (build_complex): Assert that REAL and IMAG are constants. (integer_zerop): Look through location wrappers. (integer_onep): Likewise. (integer_each_onep): Likewise. (integer_all_onesp): Likewise. (integer_minus_onep): Likewise. (integer_pow2p): Likewise. (integer_nonzerop): Likewise. (integer_truep): Likewise. (fixed_zerop): Likewise. (real_zerop): Likewise. (real_onep): Likewise. (real_minus_onep): Likewise. (tree_int_cst_equal): Likewise. (simple_cst_equal): Treat location wrappers with non-equal source locations as being unequal. (uniform_integer_cst_p): Look through location wrappers. (maybe_wrap_with_location): Don't create wrappers if any auto_suppress_location_wrappers are active. (suppress_location_wrappers): New variable. (selftest::test_predicates): New test. (selftest::tree_c_tests): Call it. * tree.h (CONSTANT_CLASS_OR_WRAPPER_P): New macro. (suppress_location_wrappers): New decl. (class auto_suppress_location_wrappers): New class. gcc/cp/ChangeLog: PR c++/43064 PR c++/43486 * call.c (build_conditional_expr_1): Strip location wrappers when checking for CONST_DECL. (conversion_null_warnings): Use location of "expr" if available. * class.c (fixed_type_or_null): Handle location wrappers. * constexpr.c (potential_constant_expression_1): Likewise. * cvt.c (ignore_overflows): Strip location wrappers when checking for INTEGER_CST, and re-wrap the result if present. (ocp_convert): Call fold_for_warn before checking for INTEGER_CST. * decl.c (reshape_init_r): Strip any location wrapper. (undeduced_auto_decl): Likewise. * expr.c (mark_discarded_use): Likewise for expr. * init.c (build_aggr_init): Likewise before checking init for DECL_P. (warn_placement_new_too_small): Call fold_for_warn on adj before checking for CONSTANT_CLASS_P, and on nelts. Strip any location wrapper from op0 and on oper before checking for VAR_P. * parser.c (cp_parser_primary_expression): Call maybe_add_location_wrapper on numeric and string literals. (cp_parser_postfix_expression): Strip any location wrapper when checking for DECL_IS_BUILTIN_CONSTANT_P. (cp_parser_unary_expression): Ensure that folding of NEGATE_EXPR around a constant happens in the presence of location wrappers and returns a wrapped result. (cp_parser_has_attribute_expression): Strip any location wrapper from "oper". (cp_parser_binary_expression): Strip any location wrapper when checking for DECL_P on the lhs. (cp_parser_decltype): Strip any location wrapper from result of cp_parser_decltype_expr. (cp_parser_mem_initializer): Add location wrappers to the parenthesized expression list. (cp_parser_template_parameter_list): Don't create wrapper nodes within a template-parameter-list. (cp_parser_template_argument_list): Don't create wrapper nodes within a template-argument-list. (cp_parser_parameter_declaration): Strip location wrappers from default arguments. (cp_parser_gnu_attribute_list): Don't create wrapper nodes. (cp_parser_std_attribute_spec_seq): Likewise. (cp_parser_omp_all_clauses): Don't create wrapper nodes within OpenMP clauses. (cp_parser_omp_for_loop): Likewise. (cp_parser_omp_declare_reduction_exprs): Likewise. * pt.c (convert_nontype_argument_function): Strip location wrappers from fn_no_ptr before checking for FUNCTION_DECL. (tsubst_default_argument): Move note about which callsite led to instantiation to after the check_default_argument call. (do_auto_deduction): Likewise from init before checking for DECL_P. * semantics.c (force_paren_expr): Likewise from expr before checking for DECL_P. (finish_parenthesized_expr): Likewise from expr before checking for STRING_CST. (perform_koenig_lookup): Likewise from fn. (finish_call_expr): Likewise. (finish_id_expression): Rename to... (finish_id_expression_1): ...this, calling maybe_add_location_wrapper on the result. (capture_decltype): Use lookup_name_real rather than value_member when looking up decl within the capture-list. * tree.c (cp_stabilize_reference): Strip any location wrapper. (builtin_valid_in_constant_expr_p): Likewise. (strip_typedefs_expr): Strip any location wrapper before checking for decls or constants. (is_overloaded_fn): Likewise. (maybe_get_fns): Likewise. (selftest::test_lvalue_kind): Verify lvalue_p. * typeck.c (cxx_sizeof_expr): Strip any location wrapper. (cxx_alignof_expr): Likewise. (is_bitfield_expr_with_lowered_type): Handle location wrappers. (cp_build_array_ref): Call maybe_constant_value on "idx". (cp_build_binary_op): Strip location wrapper from first_arg before checking for PARM_DECL. Likewise for op1 before checking for INTEGER_CST in two places. Likewise for orig_op0 and orig_op1 when checking for STRING_CST. (cp_build_addr_expr_1): Likewise for arg when checking for FUNCTION_DECL. (cp_build_modify_expr): Likewise for newrhs when checking for STRING_CST. (convert_for_assignment): Don't strip location wrappers when stripping NON_LVALUE_EXPR. (maybe_warn_about_returning_address_of_local): Strip location wrapper from whats_returned before checking for DECL_P. (can_do_nrvo_p): Strip location wrapper from retval. (treat_lvalue_as_rvalue_p): Likewise. (check_return_expr): Likewise. * typeck2.c (cxx_incomplete_type_diagnostic): Strip location wrapper from value before checking for VAR_P or PARM_DECL. (digest_init_r): Strip location wrapper from init. When copying "init", also copy the wrapped node. gcc/objc/ChangeLog: PR c++/43064 PR c++/43486 * objc-act.c (objc_maybe_build_component_ref): Strip any location wrapper before checking for UOBJC_SUPER_decl and self_decl. (objc_finish_message_expr): Strip any location wrapper. (gen_declaration): Strip location wrappers from "w". gcc/testsuite/ChangeLog: PR c++/43064 PR c++/43486 * c-c++-common/pr51712.c (valid2): Mark xfail as passing on C++. * g++.dg/cpp0x/constexpr-47969.C: Update column of expected error. * g++.dg/cpp0x/constexpr-ex2.C: Likewise. * g++.dg/cpp0x/scoped_enum2.C: Likewise. * g++.dg/cpp1z/decomp48.C: Update expected location of warning for named local variables to use that of the local variable. * g++.dg/ext/vla1.C: Update column. * g++.dg/init/array43.C: Update expected column to be that of the initializer. * g++.dg/init/initializer-string-too-long.C: New test. * g++.dg/init/new44.C: Add "-ftrack-macro-expansion=0". * g++.dg/init/pr43064-1.C: New test. * g++.dg/init/pr43064-2.C: New test. * g++.dg/init/pr43064-3.C: New test. * g++.dg/other/fold1.C: Update column of expected error. * g++.dg/parse/crash36.C: Likewise. * g++.dg/plugin/diagnostic-test-expressions-1.C: Add negative integer and float expressions. * g++.dg/template/defarg6.C: Move expected error to the default argument; add expected message about where instantiated. * g++.dg/wrappers/Wparentheses.C: New test. * g++.old-deja/g++.bugs/900402_02.C: Update column of expected error. From-SVN: r267272
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c75
1 files changed, 58 insertions, 17 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b57e35d..c0552b5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5232,7 +5232,8 @@ cp_parser_primary_expression (cp_parser *parser,
if (!cast_p)
cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
}
- return cp_expr (token->u.value, token->location);
+ return (cp_expr (token->u.value, token->location)
+ .maybe_add_location_wrapper ());
case CPP_CHAR_USERDEF:
case CPP_CHAR16_USERDEF:
@@ -5254,9 +5255,10 @@ cp_parser_primary_expression (cp_parser *parser,
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
argument to cp_parser_string_literal. */
- return cp_parser_string_literal (parser,
- parser->translate_strings_p,
- true);
+ return (cp_parser_string_literal (parser,
+ parser->translate_strings_p,
+ true)
+ .maybe_add_location_wrapper ());
case CPP_OPEN_PAREN:
/* If we see `( { ' then we are looking at the beginning of
@@ -7169,8 +7171,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
is_member_access = false;
+ tree stripped_expression
+ = tree_strip_any_location_wrapper (postfix_expression);
is_builtin_constant_p
- = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+ = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression);
if (is_builtin_constant_p)
{
/* The whole point of __builtin_constant_p is to allow
@@ -8363,18 +8367,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
case NEGATE_EXPR:
/* Immediately fold negation of a constant, unless the constant is 0
(since -0 == 0) or it would overflow. */
- if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
- && CONSTANT_CLASS_P (cast_expression)
- && !integer_zerop (cast_expression)
- && !TREE_OVERFLOW (cast_expression))
+ if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER)
{
- tree folded = fold_build1 (unary_operator,
- TREE_TYPE (cast_expression),
- cast_expression);
- if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+ tree stripped_expr
+ = tree_strip_any_location_wrapper (cast_expression);
+ if (CONSTANT_CLASS_P (stripped_expr)
+ && !integer_zerop (stripped_expr)
+ && !TREE_OVERFLOW (stripped_expr))
{
- expression = cp_expr (folded, loc);
- break;
+ tree folded = fold_build1 (unary_operator,
+ TREE_TYPE (stripped_expr),
+ stripped_expr);
+ if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+ {
+ expression = maybe_wrap_with_location (folded, loc);
+ break;
+ }
}
}
/* Fall through. */
@@ -8489,6 +8497,8 @@ cp_parser_has_attribute_expression (cp_parser *parser)
if (!oper || oper == error_mark_node)
oper = cp_parser_unary_expression (parser);
+ STRIP_ANY_LOCATION_WRAPPER (oper);
+
/* Go back to evaluating expressions. */
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
@@ -9508,7 +9518,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|| (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0)))
!= BOOLEAN_TYPE))))
/* Avoid warning for !!b == y where b is boolean. */
- && (!DECL_P (current.lhs)
+ && (!DECL_P (tree_strip_any_location_wrapper (current.lhs))
|| TREE_TYPE (current.lhs) == NULL_TREE
|| TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE))
warn_logical_not_parentheses (current.loc, current.tree_type,
@@ -14546,6 +14556,7 @@ cp_parser_decltype (cp_parser *parser)
++c_inhibit_evaluation_warnings;
expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
+ STRIP_ANY_LOCATION_WRAPPER (expr);
/* Go back to evaluating expressions. */
--cp_unevaluated_operand;
@@ -14923,7 +14934,9 @@ cp_parser_mem_initializer (cp_parser* parser)
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*close_paren_loc=*/NULL,
+ /*wrap_locations_p=*/true);
if (vec == NULL)
return error_mark_node;
expression_list = build_tree_list_vec (vec);
@@ -15464,6 +15477,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
{
tree parameter_list = NULL_TREE;
+ /* Don't create wrapper nodes within a template-parameter-list,
+ since we don't want to have different types based on the
+ spelling location of constants and decls within them. */
+ auto_suppress_location_wrappers sentinel;
+
begin_template_parm_list ();
/* The loop below parses the template parms. We first need to know
@@ -16636,6 +16654,9 @@ cp_parser_template_argument_list (cp_parser* parser)
bool saved_ice_p;
bool saved_non_ice_p;
+ /* Don't create location wrapper nodes within a template-argument-list. */
+ auto_suppress_location_wrappers sentinel;
+
saved_in_template_argument_list_p = parser->in_template_argument_list_p;
parser->in_template_argument_list_p = true;
/* Even if the template-id appears in an integral
@@ -22313,6 +22334,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
else
default_argument = NULL_TREE;
+ if (default_argument)
+ STRIP_ANY_LOCATION_WRAPPER (default_argument);
+
/* Generate a location for the parameter, ranging from the start of the
initial token to the end of the final token (using input_location for
the latter, set up by cp_lexer_set_source_position_from_token when
@@ -25661,6 +25685,10 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
tree attribute_list = NULL_TREE;
bool save_translate_strings_p = parser->translate_strings_p;
+ /* Don't create wrapper nodes within attributes: the
+ handlers don't know how to handle them. */
+ auto_suppress_location_wrappers sentinel;
+
parser->translate_strings_p = false;
while (true)
{
@@ -26106,6 +26134,10 @@ cp_parser_std_attribute_spec_seq (cp_parser *parser)
tree attr_specs = NULL_TREE;
tree attr_last = NULL_TREE;
+ /* Don't create wrapper nodes within attributes: the
+ handlers don't know how to handle them. */
+ auto_suppress_location_wrappers sentinel;
+
while (true)
{
tree attr_spec = cp_parser_std_attribute_spec (parser);
@@ -34880,6 +34912,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
bool first = true;
cp_token *token = NULL;
+ /* Don't create location wrapper nodes within OpenMP clauses. */
+ auto_suppress_location_wrappers sentinel;
+
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
pragma_omp_clause c_kind;
@@ -36597,6 +36632,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
}
loc = cp_lexer_consume_token (parser->lexer)->location;
+ /* Don't create location wrapper nodes within an OpenMP "for"
+ statement. */
+ auto_suppress_location_wrappers sentinel;
+
matching_parens parens;
if (!parens.require_open (parser))
return NULL;
@@ -39168,6 +39207,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
else
{
cp_parser_parse_tentatively (parser);
+ /* Don't create location wrapper nodes here. */
+ auto_suppress_location_wrappers sentinel;
tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,