aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-02-09 14:10:42 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-02-09 14:10:42 -0500
commitdd2799cc2212a72a1b31828918f9bb9287ab9780 (patch)
treeae21c88b70f99da0013ad2fd18c0a4282796fa0b
parent8c67920556efc5fa97c2080098c202e75b93e2a0 (diff)
downloadgcc-dd2799cc2212a72a1b31828918f9bb9287ab9780.zip
gcc-dd2799cc2212a72a1b31828918f9bb9287ab9780.tar.gz
gcc-dd2799cc2212a72a1b31828918f9bb9287ab9780.tar.bz2
PR c++/84296 - ICE with qualified-id in template.
PR c++/83714 * pt.c (unknown_base_ref_p): New. (instantiation_dependent_scope_ref_p): Use it instead of any_dependent_bases_p. From-SVN: r257538
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/pt.c28
-rw-r--r--gcc/testsuite/g++.dg/template/scope5.C66
3 files changed, 99 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ac53a74..fa66e1b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2018-02-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/84296 - ICE with qualified-id in template.
+ PR c++/83714
+ * pt.c (unknown_base_ref_p): New.
+ (instantiation_dependent_scope_ref_p): Use it instead of
+ any_dependent_bases_p.
+
2018-02-09 Marek Polacek <polacek@redhat.com>
Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a9e4770..9c57709 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -24012,6 +24012,30 @@ dependent_scope_p (tree scope)
&& !currently_open_class (scope));
}
+/* T is a SCOPE_REF. Return whether it represents a non-static member of
+ an unknown base of 'this' (and is therefore instantiation-dependent). */
+
+static bool
+unknown_base_ref_p (tree t)
+{
+ if (!current_class_ptr)
+ return false;
+
+ tree mem = TREE_OPERAND (t, 1);
+ if (shared_member_p (mem))
+ return false;
+
+ tree cur = current_nonlambda_class_type ();
+ if (!any_dependent_bases_p (cur))
+ return false;
+
+ tree ctx = TREE_OPERAND (t, 0);
+ if (DERIVED_FROM_P (ctx, cur))
+ return false;
+
+ return true;
+}
+
/* T is a SCOPE_REF; return whether we need to consider it
instantiation-dependent so that we can check access at instantiation
time even though we know which member it resolves to. */
@@ -24021,9 +24045,7 @@ instantiation_dependent_scope_ref_p (tree t)
{
if (DECL_P (TREE_OPERAND (t, 1))
&& CLASS_TYPE_P (TREE_OPERAND (t, 0))
- /* A dependent base could make a member inaccessible in the current
- class. */
- && !any_dependent_bases_p ()
+ && !unknown_base_ref_p (t)
&& accessible_in_template_p (TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1)))
return false;
diff --git a/gcc/testsuite/g++.dg/template/scope5.C b/gcc/testsuite/g++.dg/template/scope5.C
new file mode 100644
index 0000000..629225c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/scope5.C
@@ -0,0 +1,66 @@
+// PR c++/84296
+
+namespace b {}
+namespace c {
+using namespace b;
+}
+namespace b {
+template <int d> struct e { static const int f = d; };
+}
+template <typename> struct g;
+template <typename h, typename i, typename aa, typename j>
+struct g<h(i, aa, j)> : h::template ab<i, aa, j> {};
+struct k {
+ template <typename l> struct m { typedef typename g<l>::n o; };
+};
+template <typename> struct ac;
+struct r {
+ typedef ac<int> p;
+};
+template <typename q> struct s : k {
+ template <typename i, typename, typename>
+ struct ab : q::template t<typename i::u>::template ab<i, int, int> {};
+};
+struct ad {
+ typedef int u;
+};
+template <typename> struct ae;
+template <typename, typename ag> struct ah {
+ typedef ae<ag> ai;
+ typedef typename ai::template w<ai(r, int)>::o n;
+};
+struct x {
+ template <typename i, typename, typename> struct ab : ah<i, int> {};
+};
+struct y {
+ struct z {
+ template <typename> struct t : x {};
+ };
+ struct aj : s<z> {};
+};
+template <typename i> struct ak {
+ typedef y::aj al;
+ typedef typename al::m<al(i, int, int)>::o o;
+};
+struct am {
+ enum { an };
+};
+template <typename> struct ao {};
+template <typename af> struct ap : af::aq {};
+template <> struct ae<int> {
+ template <typename> struct w;
+ template <typename ar, typename as, typename at> struct w<ar(as, at)> {
+ typedef typename as::p o;
+ };
+};
+enum { a = b::e<0>::f };
+template <typename> class au;
+template <typename av> struct ac : ao<av> { typedef c::e<am::an> aq; };
+template <typename aw, typename i, typename ax> void ay(aw, i, ax) {
+ au<c::e<ap<typename ak<i>::o>::f> > az();
+}
+void v() {
+ ad a;
+ void az();
+ ay(az, a, v);
+}