Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  The older regression does not seem worth fixing.

-- >8 --

In the first testcase we're overeagerly diagnosing qualified name lookup
failure for f from the current instantiation B<T>::C ahead of time
because we (correctly) deem C to not have any direct dependent bases:
its only base is B<T> which is part of the current instantiation and
therefore not a dependent base, and we decide it's safe to diagnose name
lookup failure ahead of time.

But this testcase demonstrates it's not enough to consider only direct
dependent bases: f is defined in A<T> which is a dependent base of
B<T>, so qualified name lookup won't search it ahead of time and in
turn name lookup won't be exhaustive, and so it's wrong to diagnose
lookup failure ahead of time.  This ultimately suggests that
any_dependent_bases_p needs to consider indirect bases as well.

It seems sufficient to recurse into any !BINFO_DEPENDENT_BASE_P base
since the recursive call will exit early for non-dependent types.
So effectively we'll only recurse into bases belonging to the current
instantiation.

I considered making only dependentish_scope_p consider indirect
dependent bases, but it seems other any_dependent_bases_p callers
also want this behavior, e.g. build_new_method_call for benefit of
the second testcase (which is an even older regression since GCC 7).

        PR c++/117993

gcc/cp/ChangeLog:

        * search.cc (any_dependent_bases_p): Recurse into bases (of
        dependent type) that are not BINFO_DEPENDENT_BASE_P.  Document
        default argument.

gcc/testsuite/ChangeLog:

        * g++.dg/template/dependent-base4.C: New test.
        * g++.dg/template/dependent-base5.C: New test.
---
 gcc/cp/search.cc                              |  5 ++--
 .../g++.dg/template/dependent-base4.C         | 23 +++++++++++++++++++
 .../g++.dg/template/dependent-base5.C         | 22 ++++++++++++++++++
 3 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/dependent-base4.C
 create mode 100644 gcc/testsuite/g++.dg/template/dependent-base5.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index d438e18b74b..8a65dd3b68e 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -2843,7 +2843,7 @@ original_binfo (tree binfo, tree here)
    TYPE).  */
 
 bool
-any_dependent_bases_p (tree type)
+any_dependent_bases_p (tree type /* = current_nonlambda_class_type () */)
 {
   if (!type || !CLASS_TYPE_P (type) || !uses_template_parms (type))
     return false;
@@ -2858,7 +2858,8 @@ any_dependent_bases_p (tree type)
   unsigned i;
   tree base_binfo;
   FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_BINFOS (TYPE_BINFO (type)), i, base_binfo)
-    if (BINFO_DEPENDENT_BASE_P (base_binfo))
+    if (BINFO_DEPENDENT_BASE_P (base_binfo)
+       || any_dependent_bases_p (BINFO_TYPE (base_binfo)))
       return true;
 
   return false;
diff --git a/gcc/testsuite/g++.dg/template/dependent-base4.C 
b/gcc/testsuite/g++.dg/template/dependent-base4.C
new file mode 100644
index 00000000000..84e53b5f3fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-base4.C
@@ -0,0 +1,23 @@
+// PR c++/117993
+
+template<class T>
+struct A {
+  void f();
+  typedef void type;
+};
+
+template<class T>
+struct B : A<T> {
+  template<class U> struct C;
+};
+
+template<class T>
+template<class U>
+struct B<T>::C : B {
+  void g(C& c) {
+    this->f();           // { dg-bogus "member" }
+    c.f();               // { dg-bogus "member" }
+    C::f();              // { dg-bogus "member" }
+    typename C::type* p; // { dg-bogus "not name a type" }
+  }
+};
diff --git a/gcc/testsuite/g++.dg/template/dependent-base5.C 
b/gcc/testsuite/g++.dg/template/dependent-base5.C
new file mode 100644
index 00000000000..2e9cdaa242b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-base5.C
@@ -0,0 +1,22 @@
+template<class T>
+struct A { };
+
+template<class T>
+struct B : A<T> {
+  template<class U> struct C;
+};
+
+struct D { void f(); };
+
+template<class T>
+template<class U>
+struct B<T>::C : B {
+  void g() {
+    D::f(); // { dg-bogus "without object" }
+  }
+};
+
+template<>
+struct A<int> : D { };
+
+template struct B<int>::C<int>;
-- 
2.47.1.440.gcaacdb5dfd

Reply via email to