aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/cp-tree.h15
-rw-r--r--gcc/cp/pt.c25
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr85462.C38
5 files changed, 78 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e4c3deb..099407b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2018-04-20 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <paolo.carlini@oracle.com>
PR c++/84611
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8c5c84e..5af4928 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 1370e21..e2a12b9 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 2e8c9a3..3450e1d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/85462
+ * g++.dg/cpp0x/pr85462.C: New test.
+
2018-04-19 H.J. Lu <hongjiu.lu@intel.com>
* 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 0000000..8134d9c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr85462.C
@@ -0,0 +1,38 @@
+// PR c++/85462
+// { dg-do compile { target c++11 } }
+
+template <class T> struct D { using d = T *; };
+template <class, class, class> struct E;
+template <class T, class U> struct E<T, U, U> { using d = typename D<T>::d; };
+template <class T> struct G { using d = typename E<T, int, int>::d; };
+template <class T, class U> typename G<T>::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 <typename>
+struct I
+{
+ bool bar ();
+#undef A
+#define A(n) void f##n (A##n *);
+D(1)
+ void baz ();
+};
+A1000 v;
+template <typename T>
+bool I<T>::bar ()
+{
+#undef A
+#define A(n) A##n k##n = *foo<A##n> (v); f##n (&k##n);
+D(1)
+ foo<H> (v);
+ baz ();
+ return false;
+}
+struct J : I<int>
+{
+ void qux () { bar (); }
+};