Re: [PATCH v2] C++: Add fix-it hints for -Wold-style-cast

2017-06-20 Thread Jason Merrill
On Wed, May 3, 2017 at 9:51 AM, 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 on x86_64-pc-linux-gnu.
>
> OK for trunk?

OK.

Jason


[PING^3] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast

2017-06-20 Thread David Malcolm
Ping re this patch:

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

(more description can be seen in v1 of the patch here:
  https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01429.html
)


On Mon, 2017-06-05 at 12:41 -0400, David Malcolm wrote:
> 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 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 

[PING^2] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast

2017-06-05 Thread David Malcolm
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 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 (, "%s<", cast_suggestion);
> > +  

[PING] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast

2017-05-26 Thread David Malcolm
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 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 (, "%s<", cast_suggestion);
> +  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text
> ());
> +
> +  /* 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 

[PATCH v2] C++: Add fix-it hints for -Wold-style-cast

2017-05-03 Thread David Malcolm
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 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 (, "%s<", cast_suggestion);
+  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text ());
+
+  /* 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