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&regrtested 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
>

Reply via email to