On Thu, Dec 12, 2024 at 2:34 PM Patrick Palka <ppa...@redhat.com> wrote: > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? The older regression does not seem worth fixing.
Ping. > > -- >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 >