On 9/1/26 3:34 AM, [email protected] wrote:
From: Lunex <[email protected]>
Thanks for the patch! I'm pushing it with some adjustments.
This patch is trivial enough not to worry about copyright, but if you
want to continue contributing under this pseudonym I encourage you to
file a copyright assignment with the FSF. See
https://gcc.gnu.org/contribute.html#legal for more information.
PR c++/114804
For future reference, the PR number should go at the top of the
ChangeLog entries.
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.
This restores the enclosing-class scope push/pop that was there before
r11-6815.
gcc/cp/ChangeLog:
* pt.cc (instantiate_class_template): Push enclosing class scope
before base substitution, pop after.
gcc/testsuite/ChangeLog:
* g++.dg/template/pr114804.C: New test.
And please name testcases by what they are testing, not just the PR;
I've renamed it to dependent-base7.C.
@@ -13093,6 +13096,9 @@ instantiate_class_template (tree type)
information. */
xref_basetypes (type, base_list);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+
apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
(int) ATTR_FLAG_TYPE_IN_PLACE,
args, tf_error, NULL_TREE);
It occurred to me that rather than pop all the way out and then almost
immediately push_nested_class again, we could stay in the enclosing
scope and only push one level into the class we're defining.
+++ b/gcc/testsuite/g++.dg/template/pr114804.C
@@ -0,0 +1,21 @@
+// PR c++/114804
+// { dg-do compile }
Also this needs { target c++11 } to avoid FAILing in C++98 mode. How
did you test the patch?
Here's what I'm pushing:
From 6d3cc093428e42e0b04f53040f43f9ca1c6f9acb Mon Sep 17 00:00:00 2001
From: Lunex <[email protected]>
Date: Tue, 1 Sep 2026 13:34:05 +0600
Subject: [PATCH] c++: lookup in enclosing scope when instantiating nested
class bases
To: [email protected]
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]>
---
gcc/cp/pt.cc | 11 +++++++---
.../g++.dg/template/dependent-base7.C | 21 +++++++++++++++++++
2 files changed, 29 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/template/dependent-base7.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ef912d1a7a7..dd0efa54112 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 00000000000..d443cf7596b
--- /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>>;
--
2.55.0