From: Jakub Jelinek Date: Fri, 20 Apr 2018 07:56:52 +0000 (+0200) Subject: re PR c++/85462 (internal compiler error: in inc_refcount_use, at cp/pt.c:8955) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e00e62761dbd91200af4e448ff13b598d918049f;p=gcc.git re PR c++/85462 (internal compiler error: in inc_refcount_use, at cp/pt.c:8955) PR c++/85462 * cp-tree.h (tinst_level): Remove in_system_header_p member, change refcount member from unsigned char to unsigned short, add refcount_infinity static data member, adjust comments. * pt.c (tinst_level::refcount_infinity): Define. (inc_refcount_use): Remove assert, don't increment if refcount is already refcount_infinity, adjust comment. (dec_refcount_use): Remove assert, don't decrement if refcount is refcount_infinity, adjust comment. (push_tinst_level_loc): Formatting fix. * g++.dg/cpp0x/pr85462.C: New test. From-SVN: r259516 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e4c3deb26fb..099407b9a14 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2018-04-20 Jakub Jelinek + + PR c++/85462 + * cp-tree.h (tinst_level): Remove in_system_header_p member, + change refcount member from unsigned char to unsigned short, + add refcount_infinity static data member, adjust comments. + * pt.c (tinst_level::refcount_infinity): Define. + (inc_refcount_use): Remove assert, don't increment if refcount + is already refcount_infinity, adjust comment. + (dec_refcount_use): Remove assert, don't decrement if refcount + is refcount_infinity, adjust comment. + (push_tinst_level_loc): Formatting fix. + 2018-04-19 Paolo Carlini PR c++/84611 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8c5c84e22b2..5af4928e2fb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5927,14 +5927,19 @@ struct GTY((chain_next ("%h.next"))) tinst_level { /* The location where the template is instantiated. */ location_t locus; - /* errorcount+sorrycount when we pushed this level. */ + /* errorcount + sorrycount when we pushed this level. */ unsigned short errors; - /* True if the location is in a system header. */ - bool in_system_header_p; + /* Count references to this object. If refcount reaches + refcount_infinity value, we don't increment or decrement the + refcount anymore, as the refcount isn't accurate anymore. + The object can be still garbage collected if unreferenced from + anywhere, which might keep referenced objects referenced longer than + otherwise necessary. Hitting the infinity is rare though. */ + unsigned short refcount; - /* Count references to this object. */ - unsigned char refcount; + /* Infinity value for the above refcount. */ + static const unsigned short refcount_infinity = (unsigned short) ~0; }; bool decl_spec_seq_has_spec_p (const cp_decl_specifier_seq *, cp_decl_spec); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1370e21ad59..e2a12b963ad 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8945,15 +8945,14 @@ tinst_level::to_list () return ret; } -/* Increment OBJ's refcount. */ +const unsigned short tinst_level::refcount_infinity; + +/* Increment OBJ's refcount unless it is already infinite. */ static tinst_level * inc_refcount_use (tinst_level *obj) { - if (obj) - { - ++obj->refcount; - gcc_assert (obj->refcount != 0); - } + if (obj && obj->refcount != tinst_level::refcount_infinity) + ++obj->refcount; return obj; } @@ -8966,15 +8965,16 @@ tinst_level::free (tinst_level *obj) tinst_level_freelist ().free (obj); } -/* Decrement OBJ's refcount. If it reaches zero, release OBJ's DECL - and OBJ, and start over with the tinst_level object that used to be - referenced by OBJ's NEXT. */ +/* Decrement OBJ's refcount if not infinite. If it reaches zero, release + OBJ's DECL and OBJ, and start over with the tinst_level object that + used to be referenced by OBJ's NEXT. */ static void dec_refcount_use (tinst_level *obj) { - while (obj && !--obj->refcount) + while (obj + && obj->refcount != tinst_level::refcount_infinity + && !--obj->refcount) { - gcc_assert (obj->refcount+1 != 0); tinst_level *next = obj->next; tinst_level::free (obj); obj = next; @@ -10145,8 +10145,7 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc) new_level->tldcl = tldcl; new_level->targs = targs; new_level->locus = loc; - new_level->errors = errorcount+sorrycount; - new_level->in_system_header_p = in_system_header_at (input_location); + new_level->errors = errorcount + sorrycount; new_level->next = NULL; new_level->refcount = 0; set_refcount_ptr (new_level->next, current_tinst_level); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2e8c9a3fbed..3450e1dca70 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-04-20 Jakub Jelinek + + PR c++/85462 + * g++.dg/cpp0x/pr85462.C: New test. + 2018-04-19 H.J. Lu * gcc.target/i386/pr85404.c: Require CET target. diff --git a/gcc/testsuite/g++.dg/cpp0x/pr85462.C b/gcc/testsuite/g++.dg/cpp0x/pr85462.C new file mode 100644 index 00000000000..8134d9c69f8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr85462.C @@ -0,0 +1,38 @@ +// PR c++/85462 +// { dg-do compile { target c++11 } } + +template struct D { using d = T *; }; +template struct E; +template struct E { using d = typename D::d; }; +template struct G { using d = typename E::d; }; +template typename G::d foo (U); +#define A(n) class A##n {}; +#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) A(n##5) A(n##6) A(n##7) A(n##8) A(n##9) +#define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) B(n##5) B(n##6) B(n##7) B(n##8) B(n##9) +#define D(n) C(n##0) C(n##1) C(n##2) C(n##3) C(n##4) +D(1) +class H; +template +struct I +{ + bool bar (); +#undef A +#define A(n) void f##n (A##n *); +D(1) + void baz (); +}; +A1000 v; +template +bool I::bar () +{ +#undef A +#define A(n) A##n k##n = *foo (v); f##n (&k##n); +D(1) + foo (v); + baz (); + return false; +} +struct J : I +{ + void qux () { bar (); } +};