aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2019-08-23 12:41:39 +0000
committerIain Sandoe <iains@gcc.gnu.org>2019-08-23 12:41:39 +0000
commit22f8849d06019e925eb8669274a03daf02e71cc6 (patch)
tree02a55a67e0aa768f2069352f6c08491e3446b2bd /gcc
parentdf375b0321f9a5360fd04435ee5832c253aa4175 (diff)
downloadgcc-22f8849d06019e925eb8669274a03daf02e71cc6.zip
gcc-22f8849d06019e925eb8669274a03daf02e71cc6.tar.gz
gcc-22f8849d06019e925eb8669274a03daf02e71cc6.tar.bz2
[PATCH, c-family] Fix a PCH thinko (and thus PR61250).
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-lex.c7
-rw-r--r--gcc/c/ChangeLog7
-rw-r--r--gcc/c/c-parser.c2
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c5
-rw-r--r--gcc/ggc-page.c5
8 files changed, 36 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 62aebf2..86669dd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index b8920f1c..2ab1c98 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 851fd70..e3c602f 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -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;
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 0b3dc74..b7b45f5 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -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
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7397f53..6070502 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -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;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d2b9623..f014423 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b410a6c..504f77a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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)
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index a2736bc..220f20c 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -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++)
{