@@ -508,18 +508,6 @@ static auto GetDeclContext(Context& context, SemIR::NameScopeId scope_id)
508
508
context.clang_decls ().Get (scope_clang_decl_context_id).key .decl );
509
509
}
510
510
511
- // Looks up for constructors in the class scope and returns the lookup result.
512
- static auto ClangConstructorLookup (Context& context,
513
- SemIR::NameScopeId scope_id)
514
- -> clang::DeclContextLookupResult {
515
- const SemIR::NameScope& scope = context.name_scopes ().Get (scope_id);
516
-
517
- clang::Sema& sema = context.clang_sema ();
518
- clang::Decl* decl =
519
- context.clang_decls ().Get (scope.clang_decl_context_id ()).key .decl ;
520
- return sema.LookupConstructors (cast<clang::CXXRecordDecl>(decl));
521
- }
522
-
523
511
// Returns true if the given Clang declaration is the implicit injected class
524
512
// name within the class.
525
513
static auto IsDeclInjectedClassName (Context& context,
@@ -2074,12 +2062,14 @@ static auto LookupBuiltinTypes(Context& context, SemIR::LocId loc_id,
2074
2062
2075
2063
auto ImportCppOverloadSet (Context& context, SemIR::NameScopeId scope_id,
2076
2064
SemIR::NameId name_id,
2077
- const clang::UnresolvedSet<4 >& overload_set)
2065
+ clang::CXXRecordDecl* naming_class,
2066
+ clang::UnresolvedSet<4 >&& overload_set)
2078
2067
-> SemIR::InstId {
2079
2068
SemIR::CppOverloadSetId overload_set_id = context.cpp_overload_sets ().Add (
2080
2069
SemIR::CppOverloadSet{.name_id = name_id,
2081
2070
.parent_scope_id = scope_id,
2082
- .candidate_functions = overload_set});
2071
+ .naming_class = naming_class,
2072
+ .candidate_functions = std::move (overload_set)});
2083
2073
2084
2074
auto overload_set_inst_id =
2085
2075
// TODO: Add a location.
@@ -2093,65 +2083,65 @@ auto ImportCppOverloadSet(Context& context, SemIR::NameScopeId scope_id,
2093
2083
return overload_set_inst_id;
2094
2084
}
2095
2085
2096
- // Gets the access for an overloaded function set. Returns std::nullopt
2097
- // if the access is not the same for all functions in the overload set.
2098
- // TODO: Fix to support functions with different access levels.
2099
- static auto GetOverloadSetAccess (Context& context, SemIR::LocId loc_id,
2100
- const clang::UnresolvedSet<4 >& overload_set)
2101
- -> std::optional<SemIR::AccessKind> {
2086
+ // Gets the best access for an overloaded function set. This is the access that
2087
+ // we use for the overload set as a whole. More fine-grained checking is done
2088
+ // after overload resolution.
2089
+ static auto GetOverloadSetAccess (const clang::UnresolvedSet<4 >& overload_set)
2090
+ -> SemIR::AccessKind {
2102
2091
clang::AccessSpecifier access = overload_set.begin ().getAccess ();
2103
2092
for (auto it = overload_set.begin () + 1 ; it != overload_set.end (); ++it) {
2104
- if (it.getAccess () != access) {
2105
- context.TODO (loc_id, " Unsupported: Overloaded set with mixed access" );
2106
- return std::nullopt ;
2093
+ CARBON_CHECK (
2094
+ (it.getAccess () == clang::AS_none) == (access == clang::AS_none),
2095
+ " Unexpected mixture of members and non-members" );
2096
+ if (it.getAccess () < access) {
2097
+ access = it->getAccess ();
2107
2098
}
2108
2099
}
2109
2100
return MapAccess (access);
2110
2101
}
2111
2102
2112
2103
// Imports an overload set from Clang to Carbon and adds the name into the
2113
2104
// `NameScope`.
2114
- static auto ImportOverloadSetIntoScope (
2115
- Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,
2116
- SemIR::NameId name_id, const clang::UnresolvedSet<4 >& overload_set)
2105
+ static auto ImportOverloadSetIntoScope (Context& context,
2106
+ SemIR::NameScopeId scope_id,
2107
+ SemIR::NameId name_id,
2108
+ clang::CXXRecordDecl* naming_class,
2109
+ clang::UnresolvedSet<4 >&& overload_set)
2117
2110
-> SemIR::ScopeLookupResult {
2118
- std::optional<SemIR::AccessKind> access_kind =
2119
- GetOverloadSetAccess (context, loc_id, overload_set);
2120
- if (!access_kind.has_value ()) {
2121
- return SemIR::ScopeLookupResult::MakeError ();
2122
- }
2123
-
2124
- SemIR::InstId inst_id =
2125
- ImportCppOverloadSet (context, scope_id, name_id, overload_set);
2126
- AddNameToScope (context, scope_id, name_id, access_kind.value (), inst_id);
2111
+ SemIR::AccessKind access_kind = GetOverloadSetAccess (overload_set);
2112
+ SemIR::InstId inst_id = ImportCppOverloadSet (
2113
+ context, scope_id, name_id, naming_class, std::move (overload_set));
2114
+ AddNameToScope (context, scope_id, name_id, access_kind, inst_id);
2127
2115
return SemIR::ScopeLookupResult::MakeWrappedLookupResult (inst_id,
2128
- access_kind. value () );
2116
+ access_kind);
2129
2117
}
2130
2118
2131
2119
// Imports the constructors for a given class name. The found constructors are
2132
2120
// imported as part of an overload set into the scope. Currently copy/move
2133
2121
// constructors are not imported.
2134
- static auto ImportConstructorsIntoScope (Context& context, SemIR::LocId loc_id,
2122
+ static auto ImportConstructorsIntoScope (Context& context,
2135
2123
SemIR::NameScopeId scope_id,
2136
2124
SemIR::NameId name_id)
2137
2125
-> SemIR::ScopeLookupResult {
2126
+ auto * naming_class =
2127
+ cast<clang::CXXRecordDecl>(GetDeclContext (context, scope_id));
2138
2128
clang::DeclContextLookupResult constructors_lookup =
2139
- ClangConstructorLookup ( context, scope_id );
2129
+ context. clang_sema (). LookupConstructors (naming_class );
2140
2130
2141
2131
clang::UnresolvedSet<4 > overload_set;
2142
2132
for (auto * decl : constructors_lookup) {
2143
2133
auto info = clang::getConstructorInfo (decl);
2144
2134
if (!info.Constructor || info.Constructor ->isCopyOrMoveConstructor ()) {
2145
2135
continue ;
2146
2136
}
2147
- overload_set.addDecl (info.FoundDecl , info.FoundDecl -> getAccess ());
2137
+ overload_set.addDecl (info.FoundDecl , info.FoundDecl . getAccess ());
2148
2138
}
2149
2139
if (overload_set.empty ()) {
2150
2140
return SemIR::ScopeLookupResult::MakeNotFound ();
2151
2141
}
2152
2142
2153
- return ImportOverloadSetIntoScope (context, loc_id, scope_id, name_id,
2154
- overload_set);
2143
+ return ImportOverloadSetIntoScope (context, scope_id, name_id, naming_class ,
2144
+ std::move ( overload_set) );
2155
2145
}
2156
2146
2157
2147
// Imports a builtin type from Clang to Carbon and adds the name into the
@@ -2207,8 +2197,9 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
2207
2197
lookup->getFoundDecl ()->isFunctionOrFunctionTemplate ())) {
2208
2198
clang::UnresolvedSet<4 > overload_set;
2209
2199
overload_set.append (lookup->begin (), lookup->end ());
2210
- return ImportOverloadSetIntoScope (context, loc_id, scope_id, name_id,
2211
- overload_set);
2200
+ return ImportOverloadSetIntoScope (context, scope_id, name_id,
2201
+ lookup->getNamingClass (),
2202
+ std::move (overload_set));
2212
2203
}
2213
2204
if (!lookup->isSingleResult ()) {
2214
2205
// Clang will diagnose ambiguous lookup results for us.
@@ -2224,7 +2215,7 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
2224
2215
}
2225
2216
if (IsDeclInjectedClassName (context, scope_id, name_id,
2226
2217
lookup->getFoundDecl ())) {
2227
- return ImportConstructorsIntoScope (context, loc_id, scope_id, name_id);
2218
+ return ImportConstructorsIntoScope (context, scope_id, name_id);
2228
2219
}
2229
2220
auto key = SemIR::ClangDeclKey::ForNonFunctionDecl (lookup->getFoundDecl ());
2230
2221
return ImportNameDeclIntoScope (context, loc_id, scope_id, name_id, key,
0 commit comments