https://gcc.gnu.org/g:57904dc27d5b27226912838cdd6b5272cec4d050

commit r15-6737-g57904dc27d5b27226912838cdd6b5272cec4d050
Author: Patrick Palka <ppa...@redhat.com>
Date:   Thu Jan 9 10:50:06 2025 -0500

    c++: current inst w/ indirect dependent bases [PR117993]
    
    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 direct base B<T> 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 from C won't search it ahead of time and
    in turn 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.
    
    To that end it seems sufficient to make the predicate 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 more narrowly 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.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/search.cc                                |  7 +++++--
 gcc/testsuite/g++.dg/template/dependent-base4.C | 23 +++++++++++++++++++++++
 gcc/testsuite/g++.dg/template/dependent-base5.C | 22 ++++++++++++++++++++++
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index af6c892d702d..cea9f7c689ba 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,10 @@ 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)
+       /* Recurse to also consider possibly dependent bases of a base that
+          is part of the current instantiation.  */
+       || 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 000000000000..84e53b5f3fb7
--- /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 000000000000..2e9cdaa242bc
--- /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>;

Reply via email to