OK.
On Wed, Nov 29, 2017 at 4:26 PM, David Malcolm <dmalc...@redhat.com> wrote: > Whilst investigating PR c++/82893 I noticed that the location > of static_assert diagnostics uses that of the "static_assert" > token, which seemed suboptimal to me, e.g.: > > error: non-constant condition for static assertion > static_assert(sizeof(Baz<Bar>) == 8, ""); > ^~~~~~~~~~~~~ > > This patch changes it to use the location of the condition: > > error: non-constant condition for static assertion > static_assert(sizeof(Baz<Bar>) == 8, ""); > ~~~~~~~~~~~~~~~~~^~~~ > > thus highlighting the condition itself. > > On doing so I ran into issues where the condition has an > UNKNOWN_LOCATION, for traits and noexcept(), so I added > locations for these, and bulletproofed the routine in case > there are still ways to get an UNKNOWN_LOCATION for the > condition. > > Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. > > OK for trunk? > > 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. > --- > gcc/cp/parser.c | 54 > ++++++++++++++++------ > gcc/testsuite/g++.dg/cpp1y/static_assert3.C | 26 +++++++++++ > .../testsuite/20_util/duration/literals/range.cc | 2 +- > 3 files changed, 68 insertions(+), 14 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/static_assert3.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index 1ad351c..b0539896 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -2542,7 +2542,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 *); > @@ -8164,6 +8164,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); > @@ -8200,8 +8202,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: > @@ -9943,7 +9956,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; > @@ -10056,6 +10069,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); > > @@ -10099,20 +10115,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); > } > } > > @@ -13937,16 +13960,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, > @@ -14002,9 +14023,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/g++.dg/cpp1y/static_assert3.C > b/gcc/testsuite/g++.dg/cpp1y/static_assert3.C > new file mode 100644 > index 0000000..7bdc919 > --- /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/testsuite/20_util/duration/literals/range.cc > b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc > index 36e71ee..c0d1a6e 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<int64_t>::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 > -- > 1.8.5.3 >