Ping re this patch:

 https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00204.html

On Fri, 2017-05-26 at 15:35 -0400, David Malcolm wrote:
> On Wed, 2017-05-03 at 09:51 -0400, David Malcolm wrote:
> > On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
> > > On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> > > > +  /* First try const_cast.  */
> > > > +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain
> > > > */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "const_cast";
> > > > +
> > > > +  /* If that fails, try static_cast.  */
> > > > +  trial = build_static_cast (dst_type, orig_expr, 0 /*
> > > > complain
> > > > */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "static_cast";
> > > > +
> > > > +  /* Finally, try reinterpret_cast.  */
> > > > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
> > > > complain */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "reinterpret_cast";
> > > 
> > > I think you'll want tf_none instead of 0 /* complain */ in these.
> > > 
> > >   Marek
> > 
> > Thanks.
> > 
> > Here's an updated version of the patch.
> > 
> > Changes since v1:
> > - updated expected fixit-formatting (the new fix-it printer in
> >   r247548 handles this properly now)
> > - added new test cases as suggested by Florian
> > - use "tf_none" rather than "0 /* complain */"
> > 
> > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> > 
> > OK for trunk?
> > 
> > gcc/cp/ChangeLog:
> >     * parser.c (get_cast_suggestion): New function.
> >     (maybe_add_cast_fixit): New function.
> >     (cp_parser_cast_expression): Capture the location of the
> > closing
> >     parenthesis.  Call maybe_add_cast_fixit when emitting warnings
> >     about old-style casts.
> > 
> > gcc/testsuite/ChangeLog:
> >     * g++.dg/other/old-style-cast-fixits.C: New test case.
> > ---
> >  gcc/cp/parser.c                                    | 93
> > ++++++++++++++++++++-
> >  gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 95
> > ++++++++++++++++++++++
> >  2 files changed, 186 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast
> > -fixits.C
> > 
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index 4714bc6..2f83aa9 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression
> > (cp_parser *parser)
> >      }
> >  }
> >  
> > +/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR,
> > trying them
> > +   in the order: const_cast, static_cast, reinterpret_cast.
> > +
> > +   Don't suggest dynamic_cast.
> > +
> > +   Return the first legal cast kind found, or NULL otherwise.  */
> > +
> > +static const char *
> > +get_cast_suggestion (tree dst_type, tree orig_expr)
> > +{
> > +  tree trial;
> > +
> > +  /* Reuse the parser logic by attempting to build the various
> > kinds
> > of
> > +     cast, with "complain" disabled.
> > +     Identify the first such cast that is valid.  */
> > +
> > +  /* Don't attempt to run such logic within template processing. 
> >  */
> > +  if (processing_template_decl)
> > +    return NULL;
> > +
> > +  /* First try const_cast.  */
> > +  trial = build_const_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "const_cast";
> > +
> > +  /* If that fails, try static_cast.  */
> > +  trial = build_static_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "static_cast";
> > +
> > +  /* Finally, try reinterpret_cast.  */
> > +  trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "reinterpret_cast";
> > +
> > +  /* No such cast possible.  */
> > +  return NULL;
> > +}
> > +
> > +/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
> > +   suggesting how to convert a C-style cast of the form:
> > +
> > +     (DST_TYPE)ORIG_EXPR
> > +
> > +   to a C++-style cast.
> > +
> > +   The primary range of RICHLOC is asssumed to be that of the
> > original
> > +   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the
> > locations
> > +   of the parens in the C-style cast.  */
> > +
> > +static void
> > +maybe_add_cast_fixit (rich_location *rich_loc, location_t
> > open_paren_loc,
> > +                 location_t close_paren_loc, tree orig_expr,
> > +                 tree dst_type)
> > +{
> > +  /* This function is non-trivial, so bail out now if the warning
> > isn't
> > +     going to be emitted.  */
> > +  if (!warn_old_style_cast)
> > +    return;
> > +
> > +  /* Try to find a legal C++ cast, trying them in order:
> > +     const_cast, static_cast, reinterpret_cast.  */
> > +  const char *cast_suggestion = get_cast_suggestion (dst_type,
> > orig_expr);
> > +  if (!cast_suggestion)
> > +    return;
> > +
> > +  /* Replace the open paren with "CAST_SUGGESTION<".  */
> > +  pretty_printer pp;
> > +  pp_printf (&pp, "%s<", cast_suggestion);
> > +  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text
> > (&pp));
> > +
> > +  /* Replace the close paren with "> (".  */
> > +  rich_loc->add_fixit_replace (close_paren_loc, "> (");
> > +
> > +  /* Add a closing paren after the expr (the primary range of
> > RICH_LOC).  */
> > +  rich_loc->add_fixit_insert_after (")");
> > +}
> > +
> > +
> >  /* Parse a cast-expression.
> >  
> >     cast-expression:
> > @@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser *parser,
> > bool address_p, bool cast_p,
> >        /* Consume the `('.  */
> >        cp_token *open_paren = cp_lexer_consume_token (parser
> > ->lexer);
> >        location_t open_paren_loc = open_paren->location;
> > +      location_t close_paren_loc = UNKNOWN_LOCATION;
> >  
> >        /* A very tricky bit is that `(struct S) { 3 }' is a
> >      compound-literal (which we permit in C++ as an
> > extension).
> > @@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser
> > *parser,
> > bool address_p, bool cast_p,
> >       /* Look for the type-id.  */
> >       type = cp_parser_type_id (parser);
> >       /* Look for the closing `)'.  */
> > -     cp_parser_require (parser, CPP_CLOSE_PAREN,
> > RT_CLOSE_PAREN);
> > +     cp_token *close_paren
> > +       = cp_parser_require (parser, CPP_CLOSE_PAREN,
> > RT_CLOSE_PAREN);
> > +     if (close_paren)
> > +       close_paren_loc = close_paren->location;
> >       parser->in_type_id_in_expr_p =
> > saved_in_type_id_in_expr_p;
> >     }
> >  
> > @@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser
> > *parser,
> > bool address_p, bool cast_p,
> >               && !in_system_header_at (input_location)
> >               && !VOID_TYPE_P (type)
> >               && current_lang_name != lang_name_c)
> > -           warning (OPT_Wold_style_cast, "use of old-style
> > cast");
> > +           {
> > +             gcc_rich_location rich_loc (input_location);
> > +             maybe_add_cast_fixit (&rich_loc, open_paren_loc,
> > close_paren_loc,
> > +                                   expr, type);
> > +             warning_at_rich_loc (&rich_loc,
> > OPT_Wold_style_cast,
> > +                                  "use of old-style cast to
> > %qT", type);
> > +           }
> >  
> >           /* Only type conversions to integral or enumeration
> > types
> >              can be used in constant-expressions.  */
> > diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > new file mode 100644
> > index 0000000..a10b623
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > @@ -0,0 +1,95 @@
> > +// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
> > +
> > +struct foo {};
> > +struct bar { const foo *field; };
> > +
> > +void test_1 (void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            static_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_2 (const foo *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            const_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_3 (bar *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            reinterpret_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_4 (bar *ptr)
> > +{
> > +  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr->field;
> > +                        ^~~~~
> > +            -----------------
> > +            const_cast<foo *> (ptr->field)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_5 ()
> > +{
> > +  bar b_inst;
> > +  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)&b_inst;
> > +                    ^~~~~~
> > +            --------------
> > +            reinterpret_cast<foo *> (&b_inst)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* We don't offer suggestions for templates.  */
> > +
> > +template <typename T>
> > +void test_6 (void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* We don't offer suggestions where a single C++-style cast can't
> > be
> > +   used.  */
> > +
> > +void test_7 (const void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* Likewise, no single C++-style cast is usable here.  */
> > +
> > +void test_8 (const bar &b_inst)
> > +{
> > +  foo *f = (foo *)&b_inst;  // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)&b_inst;
> > +                    ^~~~~~
> > +     { dg-end-multiline-output "" } */
> > +}

Reply via email to