[PATCH, c-family] Fix a PCH thinko (and thus PR61250).
authorIain Sandoe <iain@sandoe.co.uk>
Fri, 23 Aug 2019 12:41:39 +0000 (12:41 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Fri, 23 Aug 2019 12:41:39 +0000 (12:41 +0000)
When we are parsing a source file, the very first token might
be a PRAGMA_GCC_PCH_PREPROCESS.  This indicates that we are going
read in a PCH file (named as the value of the pragma).  If we don't
see this pragma, then we know that it's OK to release any resources
that the host might have set aside for the PCH file.

This fixes a thinko in the current implementation, in that the decision
to release resources was happening unconditionally right after the first
token is extracted but before it's been checked or acted upon.

This leads to the pch bug (seen on Darwin), because we actually do release
resources - which are subsequently (reasonably) assumed to be available
when reading a PCH file.  We then get random crashes or hangs depending
on the interaction between unmmap and malloc.

The bug is present everywhere but doesn't show on (say) Linux, since
the release of PCH resources is a NOP there.

This effects all the c-family front ends, because they all use c_lex_with_flags ()
to implement this.

The solution is to check for the PRAGMA_GCC_PCH_PREPROCESS and only call
c_common_no_more_pch () when that is not the first token.

A secondary effect of the collection is that the name of the PCH file
can be collected during the ggc_pch_read() reset of state.  Therefore
we should issue any diagnostic that might name the file before the
collections are triggered.

gcc/c-family/

2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* c-lex.c (c_lex_with_flags):  Don't call
c_common_no_more_pch () from here.

gcc/c/

2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* c-parser.c (c_parse_file): Call c_common_no_more_pch ()
after determining that the first token is not
PRAGMA_GCC_PCH_PREPROCESS.

gcc/cp/

2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* parser.c (cp_parser_initial_pragma): Call c_common_no_more_pch ()
after determining that the first token is not
PRAGMA_GCC_PCH_PREPROCESS.

gcc/

2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* ggc-page.c (ggc_pch_read): Read the ggc_pch_ondisk structure
and issue any diagnostics needed before collecting the pre-PCH
state.

From-SVN: r274856

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-lex.c
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/ggc-page.c

index 62aebf25ddce0d40784526318344dbad5d15ffee..86669dd5cf3622278ec9deec4ede6cb2a86997b7 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * ggc-page.c (ggc_pch_read): Read the ggc_pch_ondisk structure
+       and issue any diagnostics needed before collecting the pre-PCH
+       state.
+
 2019-08-23  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/91283
index b8920f1c18dac287df5349f84486e5fe4f63b71b..2ab1c98b26018d101eda8c2d6dc92436e7ee3e27 100644 (file)
@@ -1,3 +1,9 @@
+2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * c-lex.c (c_lex_with_flags):  Don't call
+       c_common_no_more_pch () from here.
+
 2019-08-23  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/91283
index 851fd704e5d37a7b0bffee7064cfa2d20c51c7f5..e3c602fbb8d4b61364b056ddc0afdc2fe787ab82 100644 (file)
@@ -394,7 +394,6 @@ enum cpp_ttype
 c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
                  int lex_flags)
 {
-  static bool no_more_pch;
   const cpp_token *tok;
   enum cpp_ttype type;
   unsigned char add_flags = 0;
@@ -628,12 +627,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
   if (cpp_flags)
     *cpp_flags = tok->flags | add_flags;
 
-  if (!no_more_pch)
-    {
-      no_more_pch = true;
-      c_common_no_more_pch ();
-    }
-
   timevar_pop (TV_CPP);
 
   return type;
index 0b3dc74f50f87f66e457b4545cb57a8f6eef7732..b7b45f504a1c65bbc15a163295832a9797a33f92 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * c-parser.c (c_parse_file): Call c_common_no_more_pch ()
+       after determining that the first token is not
+       PRAGMA_GCC_PCH_PREPROCESS.
+
 2019-08-22  Eric Botcazou  <ebotcazou@adacore.com>
 
        * c-parser.c (c_parser_declaration_or_fndef): Set DECL_ARGUMENTS of a
index 7397f536032e643dd75ffc0017a4c35141379f7c..6070502deb51c4c16e9ca37001ff51407f7759e2 100644 (file)
@@ -20263,6 +20263,8 @@ c_parse_file (void)
 
   if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
     c_parser_pragma_pch_preprocess (&tparser);
+  else
+    c_common_no_more_pch ();
 
   the_parser = ggc_alloc<c_parser> ();
   *the_parser = tparser;
index d2b96231fd04e3900565ac001c59d05bf192fb76..f014423ca00903e1cfd51a20f91f72d279f9598b 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * parser.c (cp_parser_initial_pragma): Call c_common_no_more_pch ()
+       after determining that the first token is not
+       PRAGMA_GCC_PCH_PREPROCESS.
+
 2019-08-22  Marek Polacek  <polacek@redhat.com>
 
        PR c++/91304 - prefix attributes ignored in condition.
index b410a6c030f29fda4e672c4ec70a4c83bcbd5e9a..504f77a4908955ba29d05a42c77e0cd8010011f3 100644 (file)
@@ -41357,7 +41357,10 @@ cp_parser_initial_pragma (cp_token *first_token)
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (cp_parser_pragma_kind (first_token) != PRAGMA_GCC_PCH_PREPROCESS)
-    return;
+    {
+      c_common_no_more_pch ();
+      return;
+    }
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (first_token->type == CPP_STRING)
index a2736bc1dfa0fa8d47ce3d7459fcdbeaf07e395d..220f20c5cfe7a90a7b8a86e60015a6ffd0a1e5e2 100644 (file)
@@ -2556,6 +2556,9 @@ ggc_pch_read (FILE *f, void *addr)
 
   count_old_page_tables = G.by_depth_in_use;
 
+  if (fread (&d, sizeof (d), 1, f) != 1)
+    fatal_error (input_location, "cannot read PCH file: %m");
+
   /* We've just read in a PCH file.  So, every object that used to be
      allocated is now free.  */
   clear_marks ();
@@ -2584,8 +2587,6 @@ ggc_pch_read (FILE *f, void *addr)
 
   /* Allocate the appropriate page-table entries for the pages read from
      the PCH file.  */
-  if (fread (&d, sizeof (d), 1, f) != 1)
-    fatal_error (input_location, "cannot read PCH file: %m");
 
   for (i = 0; i < NUM_ORDERS; i++)
     {