diff mbox

PR preprocessor/53469 - argument tokens of _Pragma miss virtual location

Message ID m3396jwaqe.fsf@redhat.com
State New
Headers show

Commit Message

Dodji Seketeli May 29, 2012, 10:19 a.m. UTC
Hello,

Consider this short test snippet:

-------------------------8-------------------
    #define STRINGIFY(x) #x
    #define TEST(x) \
      _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
      typedef int myint;

    void bar ()
    {
      TEST(myint)
    }
-------------------------8-------------------

The _Pragma is effectively ignored, and compiling with
-Wunused-local-typedefs warns on the local typedef, even though the
pragma should have prevented the warning to be emitted.

This is because when the preprocessor sees the _Pragma operator and
then goes to handle the first token ('GCC' here) that makes up its
operands, it retains the spelling location of that token, not its
virtual location.

Later when diagnostic_report_diagnostic is called to emit the warning
(or ignore it because of the pragma), it compares the location of the
first operand of the pragma with the location of the unused location,
(by calling linemap_location_before_p) and that comparison fails
because in this case, both locations should be virtual.

This patch fixes the issue by teaching the pragma handling to use
virtual locations.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.

libcpp/

	PR preprocessor/53469
	* directives.c (do_pragma): Use the virtual location for the
	pragma token, instead of its spelling location.

gcc/testsuite/

	PR preprocessor/53469
	* gcc.dg/cpp/_Pragma7.c: New test case.
---
 gcc/testsuite/ChangeLog             |    5 +++++
 gcc/testsuite/gcc.dg/cpp/_Pragma7.c |   14 ++++++++++++++
 libcpp/ChangeLog                    |    6 ++++++
 libcpp/directives.c                 |    8 +++++---
 4 files changed, 30 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/cpp/_Pragma7.c

Comments

Paolo Carlini May 29, 2012, 11:05 a.m. UTC | #1
Hi,

On 05/29/2012 12:19 PM, Dodji Seketeli wrote:
> The _Pragma is effectively ignored,
hi Dodji, and sorry for taking the occasion to mention other issues with 
pragmas which definitely can be handled separately, but I can't resist 
;) In fact we have a number of open PRs:

     http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47347
     http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48914
     http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431

all having to do with "#pragma GCC diagnostic ignored" and since you 
looked into this code I'm wondering if you can see a pattern, something 
which may explain all of them at once? (too good to be true, eh?)

Thanks anyway,
Paolo.
Dodji Seketeli July 26, 2012, 3:33 p.m. UTC | #2
Hello

I am friendly pinging this patch that felt below my radar.

Dodji Seketeli <dodji@redhat.com> a écrit:

> Hello,
>
> Consider this short test snippet:
>
> -------------------------8-------------------
>     #define STRINGIFY(x) #x
>     #define TEST(x) \
>       _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
>       typedef int myint;
>
>     void bar ()
>     {
>       TEST(myint)
>     }
> -------------------------8-------------------
>
> The _Pragma is effectively ignored, and compiling with
> -Wunused-local-typedefs warns on the local typedef, even though the
> pragma should have prevented the warning to be emitted.
>
> This is because when the preprocessor sees the _Pragma operator and
> then goes to handle the first token ('GCC' here) that makes up its
> operands, it retains the spelling location of that token, not its
> virtual location.
>
> Later when diagnostic_report_diagnostic is called to emit the warning
> (or ignore it because of the pragma), it compares the location of the
> first operand of the pragma with the location of the unused location,
> (by calling linemap_location_before_p) and that comparison fails
> because in this case, both locations should be virtual.
>
> This patch fixes the issue by teaching the pragma handling to use
> virtual locations.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
>
> libcpp/
>
> 	PR preprocessor/53469
> 	* directives.c (do_pragma): Use the virtual location for the
> 	pragma token, instead of its spelling location.
>
> gcc/testsuite/
>
> 	PR preprocessor/53469
> 	* gcc.dg/cpp/_Pragma7.c: New test case.
> ---
>  gcc/testsuite/ChangeLog             |    5 +++++
>  gcc/testsuite/gcc.dg/cpp/_Pragma7.c |   14 ++++++++++++++
>  libcpp/ChangeLog                    |    6 ++++++
>  libcpp/directives.c                 |    8 +++++---
>  4 files changed, 30 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/cpp/_Pragma7.c
>
> diff --git a/gcc/testsuite/gcc.dg/cpp/_Pragma7.c b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> new file mode 100644
> index 0000000..a7a5b1b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> @@ -0,0 +1,14 @@
> +/*
> +  Origin: PR preprocessor/53469
> +  { dg-do compile }
> + */
> +
> +#define STRINGIFY(x) #x
> +#define TEST(x) \
> +  _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
> +  typedef int myint;
> +
> +void bar ()
> +{
> +  TEST(myint)
> +}
> diff --git a/libcpp/directives.c b/libcpp/directives.c
> index e46280e..cd880f1 100644
> --- a/libcpp/directives.c
> +++ b/libcpp/directives.c
> @@ -1347,13 +1347,15 @@ static void
>  do_pragma (cpp_reader *pfile)
>  {
>    const struct pragma_entry *p = NULL;
> -  const cpp_token *token, *pragma_token = pfile->cur_token;
> +  const cpp_token *token, *pragma_token;
> +  source_location pragma_token_virt_loc = 0;
>    cpp_token ns_token;
>    unsigned int count = 1;
>  
>    pfile->state.prevent_expansion++;
>  
> -  token = cpp_get_token (pfile);
> +  pragma_token = token = cpp_get_token_with_location (pfile,
> +						      &pragma_token_virt_loc);
>    ns_token = *token;
>    if (token->type == CPP_NAME)
>      {
> @@ -1407,7 +1409,7 @@ do_pragma (cpp_reader *pfile)
>      {
>        if (p->is_deferred)
>  	{
> -	  pfile->directive_result.src_loc = pragma_token->src_loc;
> +	  pfile->directive_result.src_loc = pragma_token_virt_loc;
>  	  pfile->directive_result.type = CPP_PRAGMA;
>  	  pfile->directive_result.flags = pragma_token->flags;
>  	  pfile->directive_result.val.pragma = p->u.ident;
Dodji Seketeli Aug. 27, 2012, 7:52 a.m. UTC | #3
PING^2.

Dodji Seketeli <dodji@redhat.com> writes:

> Hello,
>
> Consider this short test snippet:
>
> -------------------------8-------------------
>     #define STRINGIFY(x) #x
>     #define TEST(x) \
>       _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
>       typedef int myint;
>
>     void bar ()
>     {
>       TEST(myint)
>     }
> -------------------------8-------------------
>
> The _Pragma is effectively ignored, and compiling with
> -Wunused-local-typedefs warns on the local typedef, even though the
> pragma should have prevented the warning to be emitted.
>
> This is because when the preprocessor sees the _Pragma operator and
> then goes to handle the first token ('GCC' here) that makes up its
> operands, it retains the spelling location of that token, not its
> virtual location.
>
> Later when diagnostic_report_diagnostic is called to emit the warning
> (or ignore it because of the pragma), it compares the location of the
> first operand of the pragma with the location of the unused location,
> (by calling linemap_location_before_p) and that comparison fails
> because in this case, both locations should be virtual.
>
> This patch fixes the issue by teaching the pragma handling to use
> virtual locations.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
>
> libcpp/
>
> 	PR preprocessor/53469
> 	* directives.c (do_pragma): Use the virtual location for the
> 	pragma token, instead of its spelling location.
>
> gcc/testsuite/
>
> 	PR preprocessor/53469
> 	* gcc.dg/cpp/_Pragma7.c: New test case.
> ---
>  gcc/testsuite/ChangeLog             |    5 +++++
>  gcc/testsuite/gcc.dg/cpp/_Pragma7.c |   14 ++++++++++++++
>  libcpp/ChangeLog                    |    6 ++++++
>  libcpp/directives.c                 |    8 +++++---
>  4 files changed, 30 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/cpp/_Pragma7.c
>
> diff --git a/gcc/testsuite/gcc.dg/cpp/_Pragma7.c b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> new file mode 100644
> index 0000000..a7a5b1b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> @@ -0,0 +1,14 @@
> +/*
> +  Origin: PR preprocessor/53469
> +  { dg-do compile }
> + */
> +
> +#define STRINGIFY(x) #x
> +#define TEST(x) \
> +  _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
> +  typedef int myint;
> +
> +void bar ()
> +{
> +  TEST(myint)
> +}
> diff --git a/libcpp/directives.c b/libcpp/directives.c
> index e46280e..cd880f1 100644
> --- a/libcpp/directives.c
> +++ b/libcpp/directives.c
> @@ -1347,13 +1347,15 @@ static void
>  do_pragma (cpp_reader *pfile)
>  {
>    const struct pragma_entry *p = NULL;
> -  const cpp_token *token, *pragma_token = pfile->cur_token;
> +  const cpp_token *token, *pragma_token;
> +  source_location pragma_token_virt_loc = 0;
>    cpp_token ns_token;
>    unsigned int count = 1;
>  
>    pfile->state.prevent_expansion++;
>  
> -  token = cpp_get_token (pfile);
> +  pragma_token = token = cpp_get_token_with_location (pfile,
> +						      &pragma_token_virt_loc);
>    ns_token = *token;
>    if (token->type == CPP_NAME)
>      {
> @@ -1407,7 +1409,7 @@ do_pragma (cpp_reader *pfile)
>      {
>        if (p->is_deferred)
>  	{
> -	  pfile->directive_result.src_loc = pragma_token->src_loc;
> +	  pfile->directive_result.src_loc = pragma_token_virt_loc;
>  	  pfile->directive_result.type = CPP_PRAGMA;
>  	  pfile->directive_result.flags = pragma_token->flags;
>  	  pfile->directive_result.val.pragma = p->u.ident;
Jakub Jelinek Aug. 27, 2012, 7:56 a.m. UTC | #4
On Mon, Aug 27, 2012 at 09:52:04AM +0200, Dodji Seketeli wrote:
> PING^2.

This is ok for trunk.  Thanks.

> > Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
> >
> > libcpp/
> >
> > 	PR preprocessor/53469
> > 	* directives.c (do_pragma): Use the virtual location for the
> > 	pragma token, instead of its spelling location.
> >
> > gcc/testsuite/
> >
> > 	PR preprocessor/53469
> > 	* gcc.dg/cpp/_Pragma7.c: New test case.
> > ---
> >  gcc/testsuite/ChangeLog             |    5 +++++
> >  gcc/testsuite/gcc.dg/cpp/_Pragma7.c |   14 ++++++++++++++
> >  libcpp/ChangeLog                    |    6 ++++++
> >  libcpp/directives.c                 |    8 +++++---
> >  4 files changed, 30 insertions(+), 3 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> >
> > diff --git a/gcc/testsuite/gcc.dg/cpp/_Pragma7.c b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> > new file mode 100644
> > index 0000000..a7a5b1b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
> > @@ -0,0 +1,14 @@
> > +/*
> > +  Origin: PR preprocessor/53469
> > +  { dg-do compile }
> > + */
> > +
> > +#define STRINGIFY(x) #x
> > +#define TEST(x) \
> > +  _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
> > +  typedef int myint;
> > +
> > +void bar ()
> > +{
> > +  TEST(myint)
> > +}
> > diff --git a/libcpp/directives.c b/libcpp/directives.c
> > index e46280e..cd880f1 100644
> > --- a/libcpp/directives.c
> > +++ b/libcpp/directives.c
> > @@ -1347,13 +1347,15 @@ static void
> >  do_pragma (cpp_reader *pfile)
> >  {
> >    const struct pragma_entry *p = NULL;
> > -  const cpp_token *token, *pragma_token = pfile->cur_token;
> > +  const cpp_token *token, *pragma_token;
> > +  source_location pragma_token_virt_loc = 0;
> >    cpp_token ns_token;
> >    unsigned int count = 1;
> >  
> >    pfile->state.prevent_expansion++;
> >  
> > -  token = cpp_get_token (pfile);
> > +  pragma_token = token = cpp_get_token_with_location (pfile,
> > +						      &pragma_token_virt_loc);
> >    ns_token = *token;
> >    if (token->type == CPP_NAME)
> >      {
> > @@ -1407,7 +1409,7 @@ do_pragma (cpp_reader *pfile)
> >      {
> >        if (p->is_deferred)
> >  	{
> > -	  pfile->directive_result.src_loc = pragma_token->src_loc;
> > +	  pfile->directive_result.src_loc = pragma_token_virt_loc;
> >  	  pfile->directive_result.type = CPP_PRAGMA;
> >  	  pfile->directive_result.flags = pragma_token->flags;
> >  	  pfile->directive_result.val.pragma = p->u.ident;
> 
> -- 
> 		Dodji

	Jakub
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/cpp/_Pragma7.c b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
new file mode 100644
index 0000000..a7a5b1b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/_Pragma7.c
@@ -0,0 +1,14 @@ 
+/*
+  Origin: PR preprocessor/53469
+  { dg-do compile }
+ */
+
+#define STRINGIFY(x) #x
+#define TEST(x) \
+  _Pragma(STRINGIFY(GCC diagnostic ignored "-Wunused-local-typedefs")) \
+  typedef int myint;
+
+void bar ()
+{
+  TEST(myint)
+}
diff --git a/libcpp/directives.c b/libcpp/directives.c
index e46280e..cd880f1 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -1347,13 +1347,15 @@  static void
 do_pragma (cpp_reader *pfile)
 {
   const struct pragma_entry *p = NULL;
-  const cpp_token *token, *pragma_token = pfile->cur_token;
+  const cpp_token *token, *pragma_token;
+  source_location pragma_token_virt_loc = 0;
   cpp_token ns_token;
   unsigned int count = 1;
 
   pfile->state.prevent_expansion++;
 
-  token = cpp_get_token (pfile);
+  pragma_token = token = cpp_get_token_with_location (pfile,
+						      &pragma_token_virt_loc);
   ns_token = *token;
   if (token->type == CPP_NAME)
     {
@@ -1407,7 +1409,7 @@  do_pragma (cpp_reader *pfile)
     {
       if (p->is_deferred)
 	{
-	  pfile->directive_result.src_loc = pragma_token->src_loc;
+	  pfile->directive_result.src_loc = pragma_token_virt_loc;
 	  pfile->directive_result.type = CPP_PRAGMA;
 	  pfile->directive_result.flags = pragma_token->flags;
 	  pfile->directive_result.val.pragma = p->u.ident;