Fix accessing protected members from templates derived classes (#7780)

When evaluating a deferred member access action, the scope stack cannot
be relied on, so `LookupUnqualifiedName` cannot be used in
`GetHighestAllowedAccess` to get the `Self` type.

Instead, store the `Self` type in the `Context` when evaluating a
method, and use that in `GetHighestAllowedAccess`.
This commit is contained in:
Nicholas Bishop
2026-09-18 19:12:05 +00:00
committed by GitHub
parent 413ac55d4f
commit dbf79d5229
10 changed files with 323 additions and 80 deletions
+18
View File
@@ -13,6 +13,7 @@
#include "toolchain/check/merge.h"
#include "toolchain/check/name_component.h"
#include "toolchain/check/name_lookup.h"
#include "toolchain/check/type.h"
#include "toolchain/check/type_completion.h"
#include "toolchain/check/unused.h"
#include "toolchain/diagnostics/diagnostic.h"
@@ -65,6 +66,8 @@ auto DeclNameStack::PushScopeAndStartName() -> void {
// Create a scope for any parameters introduced in this name.
context_->scope_stack().PushForDeclName();
UpdateAccessContext();
}
auto DeclNameStack::FinishName(const NameComponent& name) -> NameContext {
@@ -93,6 +96,8 @@ auto DeclNameStack::PopScope(bool check_unused) -> void {
context_->scope_stack().PopTo(decl_name_stack_.back().initial_scope_index,
check_unused);
decl_name_stack_.pop_back();
UpdateAccessContext();
}
auto DeclNameStack::Suspend() -> SuspendedName {
@@ -108,6 +113,9 @@ auto DeclNameStack::Suspend() -> SuspendedName {
CARBON_CHECK(scope_stack.PeekIndex() == scope_index,
"Scope index {0} does not enclose the current scope {1}",
scope_index, scope_stack.PeekIndex());
UpdateAccessContext();
return result;
}
@@ -131,6 +139,8 @@ auto DeclNameStack::Restore(SuspendedName&& sus) -> void {
context_->scope_stack().Restore(std::move(suspended_scope));
}
UpdateAccessContext();
}
auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id,
@@ -523,4 +533,12 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
}
}
auto DeclNameStack::UpdateAccessContext() const -> void {
if (decl_name_stack_.empty()) {
context_->access_context() = SemIR::NameScopeId::None;
} else {
context_->access_context() = decl_name_stack_.back().parent_scope_id;
}
}
} // namespace Carbon::Check