public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC PATCH] parse #pragma GCC diagnostic in libcpp
@ 2015-07-29  4:43 Manuel López-Ibáñez
  2015-08-21 17:44 ` Manuel López-Ibáñez
  2015-09-25 15:58 ` Dodji Seketeli
  0 siblings, 2 replies; 7+ messages in thread
From: Manuel López-Ibáñez @ 2015-07-29  4:43 UTC (permalink / raw)
  To: Gcc Patch List
  Cc: Joseph S. Myers, Jason Merrill, Dodji Seketeli, Marek Polacek

[-- Attachment #1: Type: text/plain, Size: 1088 bytes --]

Currently, #pragma GCC diagnostic is handled entirely by the FE. This
has several drawbacks:

* PR c++/53431 - C++ preprocessor ignores #pragma GCC diagnostic: The
C++ parser lexes (and preprocesses) before handling the pragmas.

* PR 53920 - "gcc -E" does not honor #pragma GCC diagnostic ignored
"-Wunused-macro": Because -E does not invoke the FE code that parses
the FE pragmas.

* PR 64698 - preprocessor ignores #pragma GCC diagnostic when using
-save-temps. Same issue as above.

The following patch moves the handling of #pragma GCC diagnostic to
libcpp but keeps the interface with the diagnostic machinery in the FE
by using a call-back function.

One serious problem with this approach is that the preprocessor will
delete the pragmas from the preprocessed output, thus '-E',
'-save-temps'  will not contain the pragmas and compiling the
preprocessed file will trigger the warnings that they were meant to
suppress.  Any ideas how to prevent libcpp from deleting the #pragmas?

No Changelog since this is not a request for approval, but comments are welcome.

Cheers,

Manuel.

[-- Attachment #2: cpp_pragma.diff --]
[-- Type: text/plain, Size: 12672 bytes --]

Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(revision 226219)
+++ gcc/c-family/c-opts.c	(working copy)
@@ -969,10 +969,11 @@ c_common_post_options (const char **pfil
     }
 
   cb = cpp_get_callbacks (parse_in);
   cb->file_change = cb_file_change;
   cb->dir_change = cb_dir_change;
+  cb->handle_pragma_diagnostic = cb_handle_pragma_diagnostic;
   cpp_post_options (parse_in);
   init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in));
 
   input_location = UNKNOWN_LOCATION;
 
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 226219)
+++ gcc/c-family/c-common.h	(working copy)
@@ -769,10 +769,12 @@ extern void check_function_arguments_rec
 					      unsigned HOST_WIDE_INT);
 extern bool check_builtin_function_arguments (tree, int, tree *);
 extern void check_function_format (tree, int, tree *);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+extern void cb_handle_pragma_diagnostic (location_t, const char *,
+					 location_t, const char *);
 extern bool attribute_takes_identifier_p (const_tree);
 extern bool c_common_handle_option (size_t, const char *, int, int, location_t,
 				    const struct cl_option_handlers *);
 extern bool default_handle_c_option (size_t, const char *, int);
 extern tree c_common_type_for_mode (machine_mode, int);
Index: gcc/c-family/c-pragma.c
===================================================================
--- gcc/c-family/c-pragma.c	(revision 226219)
+++ gcc/c-family/c-pragma.c	(working copy)
@@ -699,58 +699,75 @@ handle_pragma_visibility (cpp_reader *du
     }
   if (pragma_lex (&x) != CPP_EOF)
     warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
 }
 
-static void
-handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
-{
-  const char *kind_string, *option_string;
-  unsigned int option_index;
-  enum cpp_ttype token;
+/* CPP call-back to handle "#pragma GCC diagnostic KIND_STRING
+   OPTION_STRING", where KIND_STRING is error, warning, ignored, push
+   or pop. LOC_KIND is the location of the KIND_STRING. LOC_OPTION is
+   the location of the warning option string.  */
+
+extern void
+cb_handle_pragma_diagnostic (location_t loc_kind, const char * kind_string,
+			     location_t loc_option, const char * option_string)
+{
+  if (!kind_string)
+    {
+      warning_at (loc_kind, OPT_Wpragmas,
+		  "missing [error|warning|ignored|push|pop]"
+		  " after %<#pragma GCC diagnostic%>");
+      return;
+    }
+
   diagnostic_t kind;
-  tree x;
-  struct cl_option_handlers handlers;
 
-  token = pragma_lex (&x);
-  if (token != CPP_NAME)
-    GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>");
-  kind_string = IDENTIFIER_POINTER (x);
   if (strcmp (kind_string, "error") == 0)
     kind = DK_ERROR;
   else if (strcmp (kind_string, "warning") == 0)
     kind = DK_WARNING;
   else if (strcmp (kind_string, "ignored") == 0)
     kind = DK_IGNORED;
   else if (strcmp (kind_string, "push") == 0)
     {
-      diagnostic_push_diagnostics (global_dc, input_location);
+      diagnostic_push_diagnostics (global_dc, loc_kind);
       return;
     }
   else if (strcmp (kind_string, "pop") == 0)
     {
-      diagnostic_pop_diagnostics (global_dc, input_location);
+      diagnostic_pop_diagnostics (global_dc, loc_kind);
       return;
     }
   else
-    GCC_BAD ("expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>");
+    {
+      warning_at (loc_kind, OPT_Wpragmas,
+		  "expected [error|warning|ignored|push|pop]"
+		  " after %<#pragma GCC diagnostic%>");
+      return;
+    }
 
-  token = pragma_lex (&x);
-  if (token != CPP_STRING)
-    GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
-  option_string = TREE_STRING_POINTER (x);
+  if (!option_string)
+    {
+      warning_at (loc_option, OPT_Wpragmas, "missing option"
+		  " after %<#pragma GCC diagnostic%> kind");
+      return;
+    }
+  /* option_string + 1 to skip the initial '-' */
+  unsigned int option_index =  find_opt (option_string + 1, c_family_lang_mask);
+  if (option_index == OPT_SPECIAL_unknown
+      || !(cl_options[option_index].flags & CL_WARNING))
+    {
+      warning_at (loc_option, OPT_Wpragmas, "unknown warning option"
+		  " after %<#pragma GCC diagnostic%> kind");
+      return;
+    }
+
+  struct cl_option_handlers handlers;
   set_default_handlers (&handlers);
-  for (option_index = 0; option_index < cl_options_count; option_index++)
-    if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
-      {
-	control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
-				input_location, c_family_lang_mask, &handlers,
-				&global_options, &global_options_set,
-				global_dc);
-	return;
-      }
-  GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
+  control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
+			  loc_kind, c_family_lang_mask, &handlers,
+			  &global_options, &global_options_set,
+			  global_dc);
 }
 
 /*  Parse #pragma GCC target (xxx) to set target specific options.  */
 static void
 handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
@@ -1451,11 +1468,10 @@ init_pragma (void)
   c_register_pragma (0, "pack", handle_pragma_pack);
 #endif
   c_register_pragma (0, "weak", handle_pragma_weak);
   c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
 
-  c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
   c_register_pragma ("GCC", "target", handle_pragma_target);
   c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
   c_register_pragma ("GCC", "push_options", handle_pragma_push_options);
   c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
   c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
Index: gcc/testsuite/c-c++-common/cpp/pragma-gcc-diag.c
===================================================================
--- gcc/testsuite/c-c++-common/cpp/pragma-gcc-diag.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cpp/pragma-gcc-diag.c	(revision 0)
@@ -0,0 +1,5 @@
+/* { dg-do preprocess } */
+/* { dg-options "-Wunused-macros -E" } */
+/* PR preprocessor/53920 */
+#pragma GCC diagnostic ignored "-Wunused-macros"
+#define FOO
Index: gcc/testsuite/c-c++-common/pragma-diag-5.c
===================================================================
--- gcc/testsuite/c-c++-common/pragma-diag-5.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pragma-diag-5.c	(revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wundef" } */
+#pragma GCC diagnostic ignored "-Wundef"
+#if FOO
+#endif
+int main (void) { return 42; }
Index: gcc/testsuite/c-c++-common/pragma-diag-3.c
===================================================================
--- gcc/testsuite/c-c++-common/pragma-diag-3.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pragma-diag-3.c	(revision 0)
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+#pragma GCC diagnostic /* { dg-warning "missing" "missing" } */
+#pragma GCC diagnostic warn /* { dg-warning "24:expected" } */
+#pragma GCC diagnostic ignored "-Wfoo" /* { dg-warning "32:unknown" } */
Index: gcc/testsuite/c-c++-common/pragma-diag-4.c
===================================================================
--- gcc/testsuite/c-c++-common/pragma-diag-4.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pragma-diag-4.c	(revision 0)
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+#pragma GCC diagnostic error "-fstrict-aliasing" /* { dg-warning "unknown" } */
+#pragma GCC diagnostic error "-Werror" /* { dg-warning "unknown" } */
+
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c	(revision 226219)
+++ libcpp/directives.c	(working copy)
@@ -42,12 +42,11 @@ typedef void (*pragma_cb) (cpp_reader *)
 struct pragma_entry
 {
   struct pragma_entry *next;
   const cpp_hashnode *pragma;	/* Name and length.  */
   bool is_nspace;
-  bool is_internal;
-  bool is_deferred;
+  bool is_deferred; /* !is_deferred means that it is internal.  */
   bool allow_expansion;
   union {
     pragma_cb handler;
     struct pragma_entry *space;
     unsigned int ident;
@@ -114,10 +113,11 @@ static char ** restore_registered_pragma
                                            char **);
 static void do_pragma_once (cpp_reader *);
 static void do_pragma_poison (cpp_reader *);
 static void do_pragma_system_header (cpp_reader *);
 static void do_pragma_dependency (cpp_reader *);
+static void do_pragma_diagnostic (cpp_reader *pfile);
 static void do_pragma_warning_or_error (cpp_reader *, bool error);
 static void do_pragma_warning (cpp_reader *);
 static void do_pragma_error (cpp_reader *);
 static void do_linemarker (cpp_reader *);
 static const cpp_token *get_token_no_padding (cpp_reader *);
@@ -1234,11 +1234,11 @@ register_pragma_internal (cpp_reader *pf
 			  const char *name, pragma_cb handler)
 {
   struct pragma_entry *entry;
 
   entry = register_pragma_1 (pfile, space, name, false);
-  entry->is_internal = true;
+  entry->is_deferred = false; /* it is internal.  */
   entry->u.handler = handler;
 }
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
    goes in the global namespace.  HANDLER is the handler it will call,
@@ -1264,11 +1264,11 @@ cpp_register_pragma (cpp_reader *pfile, 
       entry->u.handler = handler;
     }
 }
 
 /* Similarly, but create mark the pragma for deferred processing.
-   When found, a CPP_PRAGMA token will be insertted into the stream
+   When found, a CPP_PRAGMA token will be inserted into the stream
    with IDENT in the token->u.pragma slot.  */
 void
 cpp_register_deferred_pragma (cpp_reader *pfile, const char *space,
 			      const char *name, unsigned int ident,
 			      bool allow_expansion, bool allow_name_expansion)
@@ -1298,10 +1298,11 @@ _cpp_init_internal_pragmas (cpp_reader *
   register_pragma_internal (pfile, "GCC", "system_header",
 			    do_pragma_system_header);
   register_pragma_internal (pfile, "GCC", "dependency", do_pragma_dependency);
   register_pragma_internal (pfile, "GCC", "warning", do_pragma_warning);
   register_pragma_internal (pfile, "GCC", "error", do_pragma_error);
+  register_pragma_internal (pfile, "GCC", "diagnostic", do_pragma_diagnostic);
 }
 
 /* Return the number of registered pragmas in PE.  */
 
 static int
@@ -1669,10 +1670,46 @@ do_pragma_dependency (cpp_reader *pfile)
     }
 
   free ((void *) fname);
 }
 
+/* Handle a "#pragma GCC diagnostic".  We parse the #pragma here to
+   set up the classification as early as possible, but we let the FEs
+   handle the actual implementation because CPP does not have access
+   to the diagnostic interfaces.  */
+static void
+do_pragma_diagnostic (cpp_reader *pfile)
+{
+  const cpp_token *tok = _cpp_lex_token (pfile);
+  source_location loc_kind = tok->src_loc;
+  const unsigned char * kind_string = 
+    (tok->type == CPP_NAME || tok->type == CPP_KEYWORD) 
+    ? cpp_token_as_text (pfile, tok)
+    : NULL;
+
+  const unsigned char * option_string = NULL;
+  source_location loc_option = loc_kind;
+  if (kind_string)
+    {
+      tok = _cpp_lex_token (pfile);
+      loc_option = tok->src_loc;
+      cpp_string str;
+      if (tok->type == CPP_STRING
+	  && cpp_interpret_string_notranslate (pfile, &tok->val.str, 1, &str,
+						CPP_STRING)
+	  && str.len > 0)
+	{
+	  option_string = str.text;
+	}
+    }
+  if (pfile->cb.handle_pragma_diagnostic)
+    pfile->cb.handle_pragma_diagnostic (loc_kind, (const char *) kind_string,
+					loc_option, (const char *) option_string);
+  if (option_string)
+    free ((void *) option_string);
+}
+
 /* Issue a diagnostic with the message taken from the pragma.  If
    ERROR is true, the diagnostic is a warning, otherwise, it is an
    error.  */
 static void
 do_pragma_warning_or_error (cpp_reader *pfile, bool error)
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 226219)
+++ libcpp/include/cpplib.h	(working copy)
@@ -591,10 +591,13 @@ struct cpp_callbacks
   /* Callback to identify whether an attribute exists.  */
   int (*has_attribute) (cpp_reader *);
 
   /* Callback that can change a user builtin into normal macro.  */
   bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *);
+
+  void (*handle_pragma_diagnostic) (source_location, const char*,
+				    source_location, const char*);
 };
 
 #ifdef VMS
 #define INO_T_CPP ino_t ino[3]
 #else

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-07-29  4:43 [RFC PATCH] parse #pragma GCC diagnostic in libcpp Manuel López-Ibáñez
@ 2015-08-21 17:44 ` Manuel López-Ibáñez
  2015-09-20 18:23   ` Manuel López-Ibáñez
  2015-09-25 15:58 ` Dodji Seketeli
  1 sibling, 1 reply; 7+ messages in thread
From: Manuel López-Ibáñez @ 2015-08-21 17:44 UTC (permalink / raw)
  To: Gcc Patch List
  Cc: Joseph S. Myers, Jason Merrill, Dodji Seketeli, Marek Polacek

Any comments on this? https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02414.html

I don't see any other way to fix these PRs, but I don't know how to
keep the pragmas from being deleted by the preprocessor.

Cheers,

Manuel.

On 29 July 2015 at 00:46, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
> Currently, #pragma GCC diagnostic is handled entirely by the FE. This
> has several drawbacks:
>
> * PR c++/53431 - C++ preprocessor ignores #pragma GCC diagnostic: The
> C++ parser lexes (and preprocesses) before handling the pragmas.
>
> * PR 53920 - "gcc -E" does not honor #pragma GCC diagnostic ignored
> "-Wunused-macro": Because -E does not invoke the FE code that parses
> the FE pragmas.
>
> * PR 64698 - preprocessor ignores #pragma GCC diagnostic when using
> -save-temps. Same issue as above.
>
> The following patch moves the handling of #pragma GCC diagnostic to
> libcpp but keeps the interface with the diagnostic machinery in the FE
> by using a call-back function.
>
> One serious problem with this approach is that the preprocessor will
> delete the pragmas from the preprocessed output, thus '-E',
> '-save-temps'  will not contain the pragmas and compiling the
> preprocessed file will trigger the warnings that they were meant to
> suppress.  Any ideas how to prevent libcpp from deleting the #pragmas?
>
> No Changelog since this is not a request for approval, but comments are welcome.
>
> Cheers,
>
> Manuel.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-08-21 17:44 ` Manuel López-Ibáñez
@ 2015-09-20 18:23   ` Manuel López-Ibáñez
  2015-09-23 23:43     ` Joseph Myers
  0 siblings, 1 reply; 7+ messages in thread
From: Manuel López-Ibáñez @ 2015-09-20 18:23 UTC (permalink / raw)
  To: Gcc Patch List
  Cc: Joseph S. Myers, Jason Merrill, Dodji Seketeli, Marek Polacek

PING^2: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02414.html

On 21 August 2015 at 19:41, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
> Any comments on this? https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02414.html
>
> I don't see any other way to fix these PRs, but I don't know how to
> keep the pragmas from being deleted by the preprocessor.
>
> Cheers,
>
> Manuel.
>
> On 29 July 2015 at 00:46, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
>> Currently, #pragma GCC diagnostic is handled entirely by the FE. This
>> has several drawbacks:
>>
>> * PR c++/53431 - C++ preprocessor ignores #pragma GCC diagnostic: The
>> C++ parser lexes (and preprocesses) before handling the pragmas.
>>
>> * PR 53920 - "gcc -E" does not honor #pragma GCC diagnostic ignored
>> "-Wunused-macro": Because -E does not invoke the FE code that parses
>> the FE pragmas.
>>
>> * PR 64698 - preprocessor ignores #pragma GCC diagnostic when using
>> -save-temps. Same issue as above.
>>
>> The following patch moves the handling of #pragma GCC diagnostic to
>> libcpp but keeps the interface with the diagnostic machinery in the FE
>> by using a call-back function.
>>
>> One serious problem with this approach is that the preprocessor will
>> delete the pragmas from the preprocessed output, thus '-E',
>> '-save-temps'  will not contain the pragmas and compiling the
>> preprocessed file will trigger the warnings that they were meant to
>> suppress.  Any ideas how to prevent libcpp from deleting the #pragmas?
>>
>> No Changelog since this is not a request for approval, but comments are welcome.
>>
>> Cheers,
>>
>> Manuel.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-09-20 18:23   ` Manuel López-Ibáñez
@ 2015-09-23 23:43     ` Joseph Myers
  0 siblings, 0 replies; 7+ messages in thread
From: Joseph Myers @ 2015-09-23 23:43 UTC (permalink / raw)
  To: Manuel López-Ibáñez
  Cc: Gcc Patch List, Jason Merrill, Dodji Seketeli, Marek Polacek

[-- Attachment #1: Type: text/plain, Size: 859 bytes --]

On Sun, 20 Sep 2015, Manuel López-Ibáñez wrote:

> PING^2: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02414.html
> 
> On 21 August 2015 at 19:41, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
> > Any comments on this? https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02414.html
> >
> > I don't see any other way to fix these PRs, but I don't know how to
> > keep the pragmas from being deleted by the preprocessor.

I'd suppose you want a new type of pragma, that acts like a combination of 
a deferred one and one for which a handler is called immediately by 
libcpp.  libcpp would call the handler but also create a CPP_PRAGMA token.  
The front-end code calling pragma handlers would need to know to do 
nothing with such pragmas; the token would only be for textual 
preprocessor output.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-07-29  4:43 [RFC PATCH] parse #pragma GCC diagnostic in libcpp Manuel López-Ibáñez
  2015-08-21 17:44 ` Manuel López-Ibáñez
@ 2015-09-25 15:58 ` Dodji Seketeli
  2015-09-27 12:03   ` Manuel López-Ibáñez
  1 sibling, 1 reply; 7+ messages in thread
From: Dodji Seketeli @ 2015-09-25 15:58 UTC (permalink / raw)
  To: Manuel López-Ibáñez
  Cc: Gcc Patch List, Joseph S. Myers, Jason Merrill, Marek Polacek

Manuel López-Ibáñez <lopezibanez@gmail.com> writes:

> Currently, #pragma GCC diagnostic is handled entirely by the FE. This
> has several drawbacks:
>
> * PR c++/53431 - C++ preprocessor ignores #pragma GCC diagnostic: The
> C++ parser lexes (and preprocesses) before handling the pragmas.
>
> * PR 53920 - "gcc -E" does not honor #pragma GCC diagnostic ignored
> "-Wunused-macro": Because -E does not invoke the FE code that parses
> the FE pragmas.
>
> * PR 64698 - preprocessor ignores #pragma GCC diagnostic when using
> -save-temps. Same issue as above.
>
> The following patch moves the handling of #pragma GCC diagnostic to
> libcpp but keeps the interface with the diagnostic machinery in the FE
> by using a call-back function.
>
> One serious problem with this approach is that the preprocessor will
> delete the pragmas from the preprocessed output, thus '-E',
> '-save-temps'  will not contain the pragmas and compiling the
> preprocessed file will trigger the warnings that they were meant to
> suppress.  Any ideas how to prevent libcpp from deleting the #pragmas?

[...]

Joseph Myers <joseph@codesourcery.com> writes:

> On Sun, 20 Sep 2015, Manuel López-Ibáñez wrote:

>> > I don't see any other way to fix these PRs, but I don't know how to
>> > keep the pragmas from being deleted by the preprocessor.
>
> I'd suppose you want a new type of pragma, that acts like a combination of 
> a deferred one and one for which a handler is called immediately by 
> libcpp.  libcpp would call the handler but also create a CPP_PRAGMA token.  
> The front-end code calling pragma handlers would need to know to do 
> nothing with such pragmas; the token would only be for textual 
> preprocessor output.

Right.  I was thinking about something along those lines as well.

So in concrete terms, in libcpp, once do_pragma() has handled the
pragma, it does two things that are interesting to us:

  * If the pragma is an internal one -- one that is handled immediately by
    libcpp, then it keeps going, chewing away at more tokens.

  * If the pragma is a deffered one -- one that is to be handled later
    by the FE, it updates pfile->directive_result.type to CPP_PRAGMA
    (and sets up some ancillary state there too).

The caller of do_pragma(), which is destringize_and_run() then detects
that pfile->directive_result.type is set, and then puts the tokens of
the pragma back into the input stream again.  So next time the FE
requests more tokens, it's going to get the same pragma tokens.

So, maybe you could alter pragma_entry::is_deferred; change it into a
flag which type is an enum that says how the the pragma is to be
handled; either internally and its tokens shouldn't be visible to the FE
(this is what the current pragma_entry::is_internal means), internally
and the tokens would be visible to the FE, or deferred.

Then do do_pragma() would be adjusted to change the if (p->is_deferred)
clause to allow the third handling kind I just talked about.

I hope this helps.

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-09-25 15:58 ` Dodji Seketeli
@ 2015-09-27 12:03   ` Manuel López-Ibáñez
  2015-09-27 14:45     ` Dodji Seketeli
  0 siblings, 1 reply; 7+ messages in thread
From: Manuel López-Ibáñez @ 2015-09-27 12:03 UTC (permalink / raw)
  To: Dodji Seketeli
  Cc: Gcc Patch List, Joseph S. Myers, Jason Merrill, Marek Polacek

On 25 September 2015 at 17:14, Dodji Seketeli <dodji@redhat.com> wrote:
> The caller of do_pragma(), which is destringize_and_run() then detects
> that pfile->directive_result.type is set, and then puts the tokens of
> the pragma back into the input stream again.  So next time the FE
> requests more tokens, it's going to get the same pragma tokens.
>
> So, maybe you could alter pragma_entry::is_deferred; change it into a
> flag which type is an enum that says how the the pragma is to be
> handled; either internally and its tokens shouldn't be visible to the FE
> (this is what the current pragma_entry::is_internal means), internally
> and the tokens would be visible to the FE, or deferred.
>
> Then do do_pragma() would be adjusted to change the if (p->is_deferred)
> clause to allow the third handling kind I just talked about.

I could not make it work by touching directive_result.type. However,
behaving as if the pragma was unknown did work:

@@ -1414,11 +1435,11 @@ do_pragma (cpp_reader *pfile)
        }
     }

   if (p)
     {
-      if (p->is_deferred)
+      if (p->type == DEFERRED)
        {
          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;
@@ -1439,11 +1460,12 @@ do_pragma (cpp_reader *pfile)
          (*p->u.handler) (pfile);
          if (p->allow_expansion)
            pfile->state.prevent_expansion++;
        }
     }
-  else if (pfile->cb.def_pragma)
+
+  if ((!p || p->type == INTERNAL_VISIBLE) && pfile->cb.def_pragma)
     {
       if (count == 1 || pfile->context->prev == NULL)
        _cpp_backup_tokens (pfile, count);
       else
        {

Yet, there is another problem. Now the FE sees the pragma and it warns
with -Wunknown-pragma. But if we register the pragma in the FE to
ignore it, then we get

cc1plus: internal compiler error: #pragma GCC diagnostic is already registered

Cheers,

Manuel.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH] parse #pragma GCC diagnostic in libcpp
  2015-09-27 12:03   ` Manuel López-Ibáñez
@ 2015-09-27 14:45     ` Dodji Seketeli
  0 siblings, 0 replies; 7+ messages in thread
From: Dodji Seketeli @ 2015-09-27 14:45 UTC (permalink / raw)
  To: Manuel López-Ibáñez
  Cc: Gcc Patch List, Joseph S. Myers, Jason Merrill, Marek Polacek

Manuel López-Ibáñez <lopezibanez@gmail.com> writes:

> On 25 September 2015 at 17:14, Dodji Seketeli <dodji@redhat.com> wrote:
>> The caller of do_pragma(), which is destringize_and_run() then detects
>> that pfile->directive_result.type is set, and then puts the tokens of
>> the pragma back into the input stream again.  So next time the FE
>> requests more tokens, it's going to get the same pragma tokens.
>>
>> So, maybe you could alter pragma_entry::is_deferred; change it into a
>> flag which type is an enum that says how the the pragma is to be
>> handled; either internally and its tokens shouldn't be visible to the FE
>> (this is what the current pragma_entry::is_internal means), internally
>> and the tokens would be visible to the FE, or deferred.
>>
>> Then do do_pragma() would be adjusted to change the if (p->is_deferred)
>> clause to allow the third handling kind I just talked about.

[...]

> behaving as if the pragma was unknown did work:
>
> @@ -1414,11 +1435,11 @@ do_pragma (cpp_reader *pfile)
>         }
>      }
>
>    if (p)
>      {
> -      if (p->is_deferred)
> +      if (p->type == DEFERRED)
>         {
>           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;
> @@ -1439,11 +1460,12 @@ do_pragma (cpp_reader *pfile)
>           (*p->u.handler) (pfile);
>           if (p->allow_expansion)
>             pfile->state.prevent_expansion++;
>         }
>      }
> -  else if (pfile->cb.def_pragma)
> +
> +  if ((!p || p->type == INTERNAL_VISIBLE) && pfile->cb.def_pragma)
>      {
>        if (count == 1 || pfile->context->prev == NULL)
>         _cpp_backup_tokens (pfile, count);
>        else
>         {
>
> Yet, there is another problem. Now the FE sees the pragma and it warns
> with -Wunknown-pragma.

Couldn't we change the FE to make it not warn on pragma entries of type
INTERNAL_VISIBLE?

Thank you for looking into this.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-09-27  1:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-29  4:43 [RFC PATCH] parse #pragma GCC diagnostic in libcpp Manuel López-Ibáñez
2015-08-21 17:44 ` Manuel López-Ibáñez
2015-09-20 18:23   ` Manuel López-Ibáñez
2015-09-23 23:43     ` Joseph Myers
2015-09-25 15:58 ` Dodji Seketeli
2015-09-27 12:03   ` Manuel López-Ibáñez
2015-09-27 14:45     ` Dodji Seketeli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).