[gcc r17-3479] c++: Avoid access check for dependent lookup result [PR124983]

Jason Merrill via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:151ded854245c1578706a9da4843f17f55de33d0

commit r17-3479-g151ded854245c1578706a9da4843f17f55de33d0
Author: Odysseas Georgoudis <[email protected]>
Date:   Sun Jul 26 23:48:20 2026 +0100

    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 refers to a member of a
    dependent scope, not just when it remains a USING_DECL.
    
    gcc/cp/ChangeLog:
    
            PR c++/124983
            * search.cc (lookup_member): Skip access checks for declarations
            from dependent scope.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/124983
            * g++.dg/template/pr124983.C: New test.
    
    Signed-off-by: Odysseas Georgoudis <[email protected]>
    Co-authored-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/search.cc                         |  7 +++--
 gcc/testsuite/g++.dg/template/pr124983.C | 49 ++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index a51fd1cd6a75..9845032d28d2 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1280,9 +1280,10 @@ 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.  */
-      if (TREE_CODE (decl) != USING_DECL
-	  && !DECL_IOBJ_MEMBER_FUNCTION_P (decl)
+      /* A dependent declaration will be checked after tsubsting.  */
+      if (!dependent_scope_p (DECL_CONTEXT (decl))
+	  && !(DECL_DECLARES_FUNCTION_P (decl)
+	       && DECL_IOBJ_MEMBER_FUNCTION_P (decl))
 	  && !perform_or_defer_access_check (basetype_path, decl, decl,
 					     complain, afi))
 	return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/template/pr124983.C b/gcc/testsuite/g++.dg/template/pr124983.C
new file mode 100644
index 000000000000..72819af48c0e
--- /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" }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.