PR c++/84296 - ICE with qualified-id in template.
authorJason Merrill <jason@redhat.com>
Fri, 9 Feb 2018 19:10:42 +0000 (14:10 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 9 Feb 2018 19:10:42 +0000 (14:10 -0500)
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

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/scope5.C [new file with mode: 0644]

index ac53a74d35f9fd4e3651bf59fcc0f93ceb624e7c..fa66e1bd36364af197930425d4b3a1b8bf37dd66 100644 (file)
@@ -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>
 
index a9e4770152734029170156130a65975039881f98..9c57709e7a7ec8b21f03ac4d404b2613f70ce879 100644 (file)
@@ -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 (file)
index 0000000..629225c
--- /dev/null
@@ -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);
+}