Files
carbon-lang/toolchain/check/cpp/access.cpp
T
Boaz Brickner 840562feb3 C++ Interop: Fix access calculation to handle private member of base classes correctly (#6238)
Always take into account both the lookup access specifier and the
declaration. When set, lookup access specifier takes precedence. When
not set, we have two use cases:
1. This is not a record member, so no access is specified at all. Treat
this as public.
2. This is a record member of a base class. Treat this as private.
[Reference](https://github.com/llvm/llvm-project/blob/4b1d7827c07381610ad4fa7bd9d1a9659008b963/clang/include/clang/AST/DeclCXX.h#L1724).

Also, deduplicate access mapping between import and overload resolution.

Background:
https://github.com/carbon-language/carbon-lang/pull/6221#issuecomment-3407981790

Part of #5859.
2025-10-21 08:12:57 +00:00

48 lines
1.9 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/cpp/access.h"
namespace Carbon::Check {
static auto CalculateEffectiveAccess(clang::DeclAccessPair access_pair)
-> clang::AccessSpecifier {
// Note that we use `.getAccess()` here, not `->getAccess()`, which is
// equivalent to `.getDecl()->getAccess()`, because we want to consider the
// lookup access and not the lexical access.
switch (access_pair.getAccess()) {
// Lookup access takes precedence.
case clang::AS_public:
case clang::AS_protected:
case clang::AS_private:
return access_pair.getAccess();
case clang::AS_none:
// No access specified meaning depends on the declaration. For non class
// members, it means there's no access associated with this function so we
// treat it as public. For class members it means we lost access along the
// inheritance path, and the difference between `none` and `private` only
// matters when the access check is performed within a friend or member of
// the naming class. Because the naming class is a C++ class, and we don't
// yet have a mechanism for a C++ class to befriend a Carbon class, we can
// safely map `none` to `private` for now.
return access_pair->isCXXClassMember() ? clang::AS_private
: clang::AS_public;
}
}
auto MapCppAccess(clang::DeclAccessPair access_pair) -> SemIR::AccessKind {
switch (CalculateEffectiveAccess(access_pair)) {
case clang::AS_public:
return SemIR::AccessKind::Public;
case clang::AS_protected:
return SemIR::AccessKind::Protected;
case clang::AS_private:
return SemIR::AccessKind::Private;
case clang::AS_none:
CARBON_FATAL("Couldn't convert access");
}
}
} // namespace Carbon::Check