From 7f14d4aed5312630afd040366cdb03604cc15fab Mon Sep 17 00:00:00 2001
From: Odysseas Georgoudis <odygrd@hotmail.com>
Date: Sun, 26 Jul 2026 23:48:20 +0100
Subject: [PATCH] c++: Avoid access check for dependent lookup result
 [PR124983]

strip_using_decl turns a dependent typename USING_DECL into a dependent
TYPE_DECL.  If member lookup finds that declaration while looking for a
typo correction, lookup_member can therefore try to perform an access
check on it.  Access checks for dependent declarations need to wait until
substitution, and enforce_access asserts this invariant.

Skip the access check whenever the lookup result still uses template
parameters, not just when it remains a USING_DECL.

gcc/cp/ChangeLog:

	PR c++/124983
	* search.cc (lookup_member): Skip access checks for dependent
	declarations.

gcc/testsuite/ChangeLog:

	PR c++/124983
	* g++.dg/template/pr124983.C: New test.

Signed-off-by: Odysseas Georgoudis <odygrd@hotmail.com>
---
 gcc/cp/search.cc                         |  3 +-
 gcc/testsuite/g++.dg/template/pr124983.C | 49 ++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr124983.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index a51fd1cd6a7..c5e586b6c27 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1280,8 +1280,9 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type,
     {
       tree decl = is_overloaded_fn (rval) ? get_first_fn (rval) : rval;
       decl = strip_using_decl (decl);
-      /* A dependent USING_DECL will be checked after tsubsting.  */
+      /* A dependent declaration will be checked after tsubsting.  */
       if (TREE_CODE (decl) != USING_DECL
+	  && !uses_template_parms (decl)
 	  && !DECL_IOBJ_MEMBER_FUNCTION_P (decl)
 	  && !perform_or_defer_access_check (basetype_path, decl, decl,
 					     complain, afi))
diff --git a/gcc/testsuite/g++.dg/template/pr124983.C b/gcc/testsuite/g++.dg/template/pr124983.C
new file mode 100644
index 00000000000..72819af48c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr124983.C
@@ -0,0 +1,49 @@
+// PR c++/124983
+// { dg-do compile }
+
+template <class T>
+struct A
+{
+  using typename T::Type;
+
+  void f()
+  {
+    this->type(); // { dg-error "no member named 'type'; did you mean 'Type'" }
+  }
+};
+
+template <class T>
+struct B
+{
+  typedef typename T::Type Type;
+  static T Value;
+
+  void f()
+  {
+    this->type(); // { dg-error "no member named 'type'; did you mean 'Type'" }
+    this->value(); // { dg-error "no member named 'value'; did you mean 'Value'" }
+  }
+};
+
+struct X
+{
+  typedef int Type;
+};
+
+template <class T>
+struct C
+{
+private:
+  typedef typename T::Type Type; // { dg-message "declared private" }
+  static T Value; // { dg-message "declared private" }
+};
+
+template <class T>
+void g()
+{
+  typename C<T>::Type t; // { dg-error "private within this context" }
+  (void) C<T>::Value; // { dg-error "private within this context" }
+  (void) t;
+}
+
+template void g<X>(); // { dg-message "required from here" }
-- 
2.43.5

