Author: Zhikai Zeng
Date: 2025-06-10T11:50:22-07:00
New Revision: 46b7a88548e5016f403cdc5f2cb1e4ff09353c3b

URL: 
https://github.com/llvm/llvm-project/commit/46b7a88548e5016f403cdc5f2cb1e4ff09353c3b
DIFF: 
https://github.com/llvm/llvm-project/commit/46b7a88548e5016f403cdc5f2cb1e4ff09353c3b.diff

LOG: fix access checking about function overloading (#107768)

fix https://github.com/llvm/llvm-project/issues/107629

After some more debugging, I find out that we will check access here at
https://github.com/llvm/llvm-project/blob/8e010ac5a173c9dee44b44324169a3e100a1a6fc/clang/lib/Sema/SemaInit.cpp#L7807

And for `f()` inside code below, `Found.getAccess()` is `AS_none` hence
`CheckAddressOfMemberAccess` return `AR_accessible` directly.

```cpp
struct Base {
public:
  int f(int);
private:
  int f();  // expect-note {{declared private here}}
};

struct Derived : public Base {};

void f() {
  int(Derived::* public_f)(int) = &Derived::f;
  int(Derived::* private_f)() = &Derived::f;  // expect-error {{'f' is a 
private member of 'Base'}}
}
```

I think the `Found.getAccess()` is intended to be `AS_none` so I just
add one more access check for the `UnresolvedLookupExpr` when
`Found.getAccess()` is `AS_none`. If add the check unconditionally clang
will report lots of duplicate errors and cause several unit tests to
fail.

I also test the UB mentioned in
https://github.com/llvm/llvm-project/issues/107629 and clang now display
4 `false` as expecetd.

Co-authored-by: Erich Keane <eke...@nvidia.com>

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaOverload.cpp
    clang/test/CXX/class.access/p4.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index beed0da6883d6..f36c82bff2ef8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -840,6 +840,7 @@ Bug Fixes to C++ Support
 - Fixed a pack substitution bug in deducing class template partial 
specializations. (#GH53609)
 - Fixed a crash when constant evaluating some explicit object member 
assignment operators. (#GH142835)
 - Fixed an access checking bug when substituting into concepts (#GH115838)
+- Fix a bug where private access specifier of overloaded function not 
respected. (#GH107629)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5a19dacdc4d84..cf455f4588de3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -16981,6 +16981,9 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr 
*E, DeclAccessPair Found,
   }
 
   if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    if (Found.getAccess() == AS_none) {
+      CheckUnresolvedLookupAccess(ULE, Found);
+    }
     // FIXME: avoid copy.
     TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
     if (ULE->hasExplicitTemplateArgs()) {

diff  --git a/clang/test/CXX/class.access/p4.cpp 
b/clang/test/CXX/class.access/p4.cpp
index ca98c9f90bd89..6d4c8c004911d 100644
--- a/clang/test/CXX/class.access/p4.cpp
+++ b/clang/test/CXX/class.access/p4.cpp
@@ -21,11 +21,13 @@ namespace test0 {
   public:
     void foo(Public&);
   protected:
-    void foo(Protected&); // expected-note 2 {{declared protected here}}
+    void foo(Protected&); // expected-note 4 {{declared protected here}}
   private:
-    void foo(Private&); // expected-note 2 {{declared private here}}
+    void foo(Private&); // expected-note 4 {{declared private here}}
   };
 
+  class B : public A {};
+
   void test(A *op) {
     op->foo(PublicInst);
     op->foo(ProtectedInst); // expected-error {{'foo' is a protected member}}
@@ -35,6 +37,16 @@ namespace test0 {
     void (A::*b)(Protected&) = &A::foo; // expected-error {{'foo' is a 
protected member}}
     void (A::*c)(Private&) = &A::foo; // expected-error {{'foo' is a private 
member}}
   }
+
+  void test(B *op) {
+    op->foo(PublicInst);
+    op->foo(ProtectedInst); // expected-error {{'foo' is a protected member}}
+    op->foo(PrivateInst); // expected-error {{'foo' is a private member}}
+
+    void (B::*a)(Public&) = &B::foo;
+    void (B::*b)(Protected&) = &B::foo; // expected-error {{'foo' is a 
protected member}}
+    void (B::*c)(Private&) = &B::foo; // expected-error {{'foo' is a private 
member}}
+  }
 }
 
 // Member operators.


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to