From a6f5143f22fd638de8c49689a11669c44a8ea580 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 30 Jul 2025 10:17:09 -0700 Subject: [PATCH] Fix diagnostic for access of protected/private base member. (#5874) When importing the member, import the access level for the lookup result, not the declared access of the member declaration. --- toolchain/check/import_cpp.cpp | 8 +++-- .../testdata/interop/cpp/class/access.carbon | 29 +++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index d98db54c5532..334293352032 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -1407,14 +1407,15 @@ static auto MapAccess(clang::AccessSpecifier access_specifier) static auto ImportNameDeclIntoScope(Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, SemIR::NameId name_id, - clang::NamedDecl* clang_decl) + clang::NamedDecl* clang_decl, + clang::AccessSpecifier access) -> SemIR::ScopeLookupResult { SemIR::InstId inst_id = ImportDeclAndDependencies(context, loc_id, clang_decl); if (!inst_id.has_value()) { return SemIR::ScopeLookupResult::MakeNotFound(); } - SemIR::AccessKind access_kind = MapAccess(clang_decl->getAccess()); + SemIR::AccessKind access_kind = MapAccess(access); AddNameToScope(context, scope_id, name_id, access_kind, inst_id); return SemIR::ScopeLookupResult::MakeWrappedLookupResult(inst_id, access_kind); @@ -1447,7 +1448,8 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id, } return ImportNameDeclIntoScope(context, loc_id, scope_id, name_id, - lookup->getFoundDecl()); + lookup->getFoundDecl(), + lookup->begin().getAccess()); } } // namespace Carbon::Check diff --git a/toolchain/check/testdata/interop/cpp/class/access.carbon b/toolchain/check/testdata/interop/cpp/class/access.carbon index 926460803f53..186d58c46f99 100644 --- a/toolchain/check/testdata/interop/cpp/class/access.carbon +++ b/toolchain/check/testdata/interop/cpp/class/access.carbon @@ -253,23 +253,48 @@ fn F() { //@dump-sem-ir-end } -// --- todo_fail_import_base_class_protected.carbon +// --- fail_import_base_class_protected.carbon library "[[@TEST_NAME]]"; import Cpp library "base_class.h"; fn F() { + // CHECK:STDERR: fail_import_base_class_protected.carbon:[[@LINE+5]]:3: error: cannot access protected member `foo` of type `Cpp.DerivedProtected` [ClassInvalidMemberAccess] + // CHECK:STDERR: Cpp.DerivedProtected.foo(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_import_base_class_protected.carbon: note: declared here [ClassMemberDeclaration] + // CHECK:STDERR: Cpp.DerivedProtected.foo(); } -// --- todo_fail_import_base_class_private.carbon +// --- use_base_class_protected_from_derived.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "base_class.h"; + +class Derived { + extend base: Cpp.DerivedProtected; + + fn F() { + // OK, we can access a protected member of our base class. + Cpp.DerivedProtected.foo(); + } +} + +// --- fail_import_base_class_private.carbon library "[[@TEST_NAME]]"; import Cpp library "base_class.h"; fn F() { + // CHECK:STDERR: fail_import_base_class_private.carbon:[[@LINE+5]]:3: error: cannot access private member `foo` of type `Cpp.DerivedPrivate` [ClassInvalidMemberAccess] + // CHECK:STDERR: Cpp.DerivedPrivate.foo(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_import_base_class_private.carbon: note: declared here [ClassMemberDeclaration] + // CHECK:STDERR: Cpp.DerivedPrivate.foo(); }