From 591996bad79b7b109bb01fba69b1c7acc054e287 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 29 Nov 2017 22:07:32 +0000 Subject: [PATCH] C++: improve location of static_assert errors gcc/cp/ChangeLog: * parser.c (cp_parser_unary_expression): Generate a location for "noexcept". (cp_parser_trait_expr): Generate and return a location_t, converting the return type from tree to cp_expr. (cp_parser_static_assert): Pass location of the condition to finish_static_assert, rather than that of the "static_assert" token, where available. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/static_assert3.C: New test case. libstdc++-v3/ChangeLog: * testsuite/20_util/duration/literals/range.cc: Update expected line of a static_assert failure. From-SVN: r255255 --- gcc/cp/ChangeLog | 10 ++++ gcc/cp/parser.c | 54 ++++++++++++++----- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/cpp1y/static_assert3.C | 26 +++++++++ libstdc++-v3/ChangeLog | 5 ++ .../20_util/duration/literals/range.cc | 2 +- 6 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/static_assert3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f9fdf1b91d4..e6851d34318 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-11-29 David Malcolm + + * parser.c (cp_parser_unary_expression): Generate a location for + "noexcept". + (cp_parser_trait_expr): Generate and return a location_t, + converting the return type from tree to cp_expr. + (cp_parser_static_assert): Pass location of the condition to + finish_static_assert, rather than that of the "static_assert" + token, where available. + 2017-11-29 Paolo Carlini PR c++/82293 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 43fc1be299f..03aeaea7597 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2530,7 +2530,7 @@ static void cp_parser_late_parsing_default_args (cp_parser *, tree); static tree cp_parser_sizeof_operand (cp_parser *, enum rid); -static tree cp_parser_trait_expr +static cp_expr cp_parser_trait_expr (cp_parser *, enum rid); static bool cp_parser_declares_only_class_p (cp_parser *); @@ -7981,6 +7981,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, bool saved_non_integral_constant_expression_p; bool saved_greater_than_is_operator_p; + location_t start_loc = token->location; + cp_lexer_consume_token (parser->lexer); matching_parens parens; parens.require_open (parser); @@ -8017,8 +8019,19 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, parser->type_definition_forbidden_message = saved_message; + location_t finish_loc + = cp_lexer_peek_token (parser->lexer)->location; parens.require_close (parser); - return finish_noexcept_expr (expr, tf_warning_or_error); + + /* Construct a location of the form: + noexcept (expr) + ^~~~~~~~~~~~~~~ + with start == caret, finishing at the close-paren. */ + location_t noexcept_loc + = make_location (start_loc, start_loc, finish_loc); + + return cp_expr (finish_noexcept_expr (expr, tf_warning_or_error), + noexcept_loc); } default: @@ -9760,7 +9773,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) Returns a representation of the expression, the underlying type of the type at issue when KEYWORD is RID_UNDERLYING_TYPE. */ -static tree +static cp_expr cp_parser_trait_expr (cp_parser* parser, enum rid keyword) { cp_trait_kind kind; @@ -9873,6 +9886,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) gcc_unreachable (); } + /* Get location of initial token. */ + location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; + /* Consume the token. */ cp_lexer_consume_token (parser->lexer); @@ -9916,20 +9932,27 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) } } + location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; parens.require_close (parser); + /* Construct a location of the form: + __is_trivially_copyable(_Tp) + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + with start == caret, finishing at the close-paren. */ + location_t trait_loc = make_location (start_loc, start_loc, finish_loc); + /* Complete the trait expression, which may mean either processing the trait expr now or saving it for template instantiation. */ switch (kind) { case CPTK_UNDERLYING_TYPE: - return finish_underlying_type (type1); + return cp_expr (finish_underlying_type (type1), trait_loc); case CPTK_BASES: - return finish_bases (type1, false); + return cp_expr (finish_bases (type1, false), trait_loc); case CPTK_DIRECT_BASES: - return finish_bases (type1, true); + return cp_expr (finish_bases (type1, true), trait_loc); default: - return finish_trait_expr (kind, type1, type2); + return cp_expr (finish_trait_expr (kind, type1, type2), trait_loc); } } @@ -13725,16 +13748,14 @@ cp_parser_linkage_specification (cp_parser* parser) static void cp_parser_static_assert(cp_parser *parser, bool member_p) { - tree condition; + cp_expr condition; + location_t token_loc; tree message; - cp_token *token; - location_t saved_loc; bool dummy; /* Peek at the `static_assert' token so we can keep track of exactly where the static assertion started. */ - token = cp_lexer_peek_token (parser->lexer); - saved_loc = token->location; + token_loc = cp_lexer_peek_token (parser->lexer)->location; /* Look for the `static_assert' keyword. */ if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, @@ -13790,9 +13811,16 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /* A semicolon terminates the declaration. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + /* Get the location for the static assertion. Use that of the + condition if available, otherwise, use that of the "static_assert" + token. */ + location_t assert_loc = condition.get_location (); + if (assert_loc == UNKNOWN_LOCATION) + assert_loc = token_loc; + /* Complete the static assertion, which may mean either processing the static assert now or saving it for template instantiation. */ - finish_static_assert (condition, message, saved_loc, member_p); + finish_static_assert (condition, message, assert_loc, member_p); } /* Parse the expression in decltype ( expression ). */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f65c3d916b6..1b6e93a7986 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-11-29 David Malcolm + + * g++.dg/cpp1y/static_assert3.C: New test case. + 2017-11-29 Paolo Carlini PR c++/82293 diff --git a/gcc/testsuite/g++.dg/cpp1y/static_assert3.C b/gcc/testsuite/g++.dg/cpp1y/static_assert3.C new file mode 100644 index 00000000000..7bdc919b4d6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/static_assert3.C @@ -0,0 +1,26 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-fdiagnostics-show-caret" } + +class is_not_empty +{ + int i; +}; + +/* Verify location of static_assert failure (and of traits). */ + +static_assert(__is_empty(is_not_empty), "message"); // { dg-error "static assertion failed: message" } +/* { dg-begin-multiline-output "" } + static_assert(__is_empty(is_not_empty), "message"); + ^~~~~~~~~~~~~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ + + +/* Again, this time verifying location of "noexcept". */ + +extern void might_throw (); + +static_assert(noexcept(might_throw ()), "message"); // { dg-error "static assertion failed: message" } +/* { dg-begin-multiline-output "" } + static_assert(noexcept(might_throw ()), "message"); + ^~~~~~~~~~~~~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index aa764f54702..a82f464c1b8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2017-11-29 David Malcolm + + * testsuite/20_util/duration/literals/range.cc: Update expected + line of a static_assert failure. + 2017-11-28 Glen Joseph Fernandes * include/bits/ptr_traits.h (to_address): Implement to_address. diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc index 36e71eea72b..c0d1a6e5885 100644 --- a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc +++ b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc @@ -26,6 +26,6 @@ test01() // std::numeric_limits::max() == 9223372036854775807; auto h = 9223372036854775808h; - // { dg-error "cannot be represented" "" { target *-*-* } 891 } + // { dg-error "cannot be represented" "" { target *-*-* } 892 } } // { dg-prune-output "in constexpr expansion" } // needed for -O0