https://gcc.gnu.org/g:6d3cc093428e42e0b04f53040f43f9ca1c6f9acb
commit r17-3861-g6d3cc093428e42e0b04f53040f43f9ca1c6f9acb Author: Lunex <[email protected]> Date: Tue Sep 1 13:34:05 2026 +0600 c++: lookup in enclosing scope when instantiating nested class bases r11-6815 (PR 82613) removed push_scope/pop_scope around base-clause substitution in instantiate_class_template. This broke lookup for using-declarations that bring enclosing-class members into scope during nested class instantiation. So let's restore the push_scope. But rather than pop_scope after the bases and then immediately push_nested_class, we can move the pop_scope to the end of the function and just pushclass/popclass for the class itself. PR c++/114804 gcc/cp/ChangeLog: * pt.cc (instantiate_class_template): Push enclosing scope before base substitution, pop at the end. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-base7.C: New test. Co-authored-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/pt.cc | 11 ++++++++--- gcc/testsuite/g++.dg/template/dependent-base7.C | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index ef912d1a7a7a..dd0efa541120 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -13025,6 +13025,10 @@ instantiate_class_template (tree type) /* Defer access checking while we substitute into the types named in the base-clause. */ push_deferring_access_checks (dk_deferred); + + /* Push into the containing scope for name lookup (114804). */ + tree pushed_scope = push_scope (CP_TYPE_CONTEXT (type)); + if (BINFO_N_BASE_BINFOS (pbinfo)) { tree pbase_binfo; @@ -13102,8 +13106,8 @@ instantiate_class_template (tree type) class, so that name lookups into base classes, etc. will work correctly. This is precisely analogous to what we do in begin_class_definition when defining an ordinary non-template - class, except we also need to push the enclosing classes. */ - push_nested_class (type); + class. */ + pushclass (type); /* Now check accessibility of the types named in its base-clause, relative to the scope of the class. */ @@ -13425,7 +13429,8 @@ instantiate_class_template (tree type) for (tree x : used) mark_used (x); - pop_nested_class (); + popclass (); + pop_scope (pushed_scope); maximum_field_alignment = saved_maximum_field_alignment; if (!fn_context) pop_from_top_level (); diff --git a/gcc/testsuite/g++.dg/template/dependent-base7.C b/gcc/testsuite/g++.dg/template/dependent-base7.C new file mode 100644 index 000000000000..d443cf7596b6 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-base7.C @@ -0,0 +1,21 @@ +// PR c++/114804 +// { dg-do compile { target c++11 } } + +template <int D> struct blurb +{ + constexpr static int d = D; +}; + +template <int> struct pant +{ +}; + +template <typename Base> struct bug : Base +{ + using Base::d; + struct problem : pant<d> + { + }; +}; + +template struct bug<blurb<2>>;
