@@ -5938,9 +5938,6 @@ makeBaseClassMemberAccessors(DeclContext *declContext,
5938
5938
bodyParams = ParameterList::createEmpty (ctx);
5939
5939
}
5940
5940
5941
- assert (baseClassVar->getFormalAccess () == AccessLevel::Public &&
5942
- " base class member must be public" );
5943
-
5944
5941
auto getterDecl = AccessorDecl::create (
5945
5942
ctx,
5946
5943
/* FuncLoc=*/ SourceLoc (),
@@ -5953,7 +5950,7 @@ makeBaseClassMemberAccessors(DeclContext *declContext,
5953
5950
: computedType,
5954
5951
declContext);
5955
5952
getterDecl->setIsTransparent (true );
5956
- getterDecl->setAccess (AccessLevel::Public );
5953
+ getterDecl->copyFormalAccessFrom (computedVar );
5957
5954
getterDecl->setBodySynthesizer (useAddress
5958
5955
? synthesizeBaseClassFieldAddressGetterBody
5959
5956
: synthesizeBaseClassFieldGetterBody,
@@ -5988,7 +5985,7 @@ makeBaseClassMemberAccessors(DeclContext *declContext,
5988
5985
: TupleType::getEmpty (ctx),
5989
5986
declContext);
5990
5987
setterDecl->setIsTransparent (true );
5991
- setterDecl->setAccess (AccessLevel::Public );
5988
+ setterDecl->copyFormalAccessFrom (computedVar );
5992
5989
setterDecl->setBodySynthesizer (useAddress
5993
5990
? synthesizeBaseClassFieldAddressSetterBody
5994
5991
: synthesizeBaseClassFieldSetterBody,
@@ -6041,8 +6038,17 @@ void cloneImportedAttributes(ValueDecl *fromDecl, ValueDecl* toDecl) {
6041
6038
}
6042
6039
}
6043
6040
6044
- static ValueDecl *
6045
- cloneBaseMemberDecl (ValueDecl *decl, DeclContext *newContext) {
6041
+ static ValueDecl *cloneBaseMemberDecl (ValueDecl *decl,
6042
+ DeclContext *newContext,
6043
+ clang::AccessSpecifier inheritance) {
6044
+ assert (inheritance != clang::AS_none &&
6045
+ " public/protected/private inheritance was not specified" );
6046
+ static_assert (AccessLevel::Private < AccessLevel::Public &&
6047
+ " std::min() relies on this ordering" );
6048
+ // Adjust access according to whichever is more restrictive, between what decl
6049
+ // was declared with (in its base class) or what it is being inherited with.
6050
+ AccessLevel access = std::min (decl->getFormalAccess (),
6051
+ importer::convertClangAccess (inheritance));
6046
6052
ASTContext &context = decl->getASTContext ();
6047
6053
6048
6054
if (auto fn = dyn_cast<FuncDecl>(decl)) {
@@ -6068,7 +6074,7 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
6068
6074
fn->getGenericParams (), fn->getParameters (),
6069
6075
fn->getResultInterfaceType (), newContext);
6070
6076
cloneImportedAttributes (decl, out);
6071
- out->copyFormalAccessFrom (fn );
6077
+ out->setAccess (access );
6072
6078
out->setBodySynthesizer (synthesizeBaseClassMethodBody, fn);
6073
6079
out->setSelfAccessKind (fn->getSelfAccessKind ());
6074
6080
return out;
@@ -6086,7 +6092,7 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
6086
6092
subscript->getStaticSpelling (), subscript->getSubscriptLoc (),
6087
6093
subscript->getIndices (), subscript->getNameLoc (), subscript->getElementInterfaceType (),
6088
6094
newContext, subscript->getGenericParams ());
6089
- out->copyFormalAccessFrom (subscript );
6095
+ out->setAccess (access );
6090
6096
out->setAccessors (SourceLoc (),
6091
6097
makeBaseClassMemberAccessors (newContext, out, subscript),
6092
6098
SourceLoc ());
@@ -6110,7 +6116,7 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
6110
6116
out->setInterfaceType (var->getInterfaceType ());
6111
6117
out->setIsObjC (var->isObjC ());
6112
6118
out->setIsDynamic (var->isDynamic ());
6113
- out->copyFormalAccessFrom (var );
6119
+ out->setAccess (access );
6114
6120
out->getASTContext ().evaluator .cacheOutput (HasStorageRequest{out}, false );
6115
6121
auto accessors = makeBaseClassMemberAccessors (newContext, out, var);
6116
6122
out->setAccessors (SourceLoc (), accessors, SourceLoc ());
@@ -6136,7 +6142,7 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
6136
6142
typeAlias->getName (), typeAlias->getNameLoc (),
6137
6143
typeAlias->getGenericParams (), newContext);
6138
6144
out->setUnderlyingType (typeAlias->getUnderlyingType ());
6139
- out->copyFormalAccessFrom (typeAlias );
6145
+ out->setAccess (access );
6140
6146
return out;
6141
6147
}
6142
6148
@@ -6147,7 +6153,7 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
6147
6153
typeDecl->getLoc (), typeDecl->getLoc (), typeDecl->getName (),
6148
6154
typeDecl->getLoc (), nullptr , newContext);
6149
6155
out->setUnderlyingType (typeDecl->getInterfaceType ());
6150
- out->copyFormalAccessFrom (typeDecl );
6156
+ out->setAccess (access );
6151
6157
return out;
6152
6158
}
6153
6159
@@ -6159,7 +6165,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6159
6165
NominalTypeDecl *recordDecl = desc.recordDecl ;
6160
6166
NominalTypeDecl *inheritingDecl = desc.inheritingDecl ;
6161
6167
DeclName name = desc.name ;
6162
-
6168
+ clang::AccessSpecifier inheritance = desc. inheritance ;
6163
6169
bool inheritedLookup = recordDecl != inheritingDecl;
6164
6170
6165
6171
auto &ctx = recordDecl->getASTContext ();
@@ -6181,6 +6187,14 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6181
6187
if (isa<clang::CXXConstructorDecl>(found) && isa<ClassDecl>(recordDecl))
6182
6188
continue ;
6183
6189
6190
+ // Skip this base class member if it is private.
6191
+ //
6192
+ // BUG: private base class members should be inherited but inaccessible.
6193
+ // Skipping them here may affect accurate overload resolution in cases of
6194
+ // multiple inheritance (which is currently buggy anyway).
6195
+ if (inheritedLookup && found->getAccess () == clang::AS_private)
6196
+ continue ;
6197
+
6184
6198
auto imported = clangModuleLoader->importDeclDirectly (found);
6185
6199
if (!imported)
6186
6200
continue ;
@@ -6189,7 +6203,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6189
6203
// by synthesizing getters and setters.
6190
6204
if (inheritedLookup) {
6191
6205
imported = clangModuleLoader->importBaseMemberDecl (
6192
- cast<ValueDecl>(imported), inheritingDecl);
6206
+ cast<ValueDecl>(imported), inheritingDecl, inheritance );
6193
6207
if (!imported)
6194
6208
continue ;
6195
6209
}
@@ -6207,8 +6221,18 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6207
6221
namedMember->getName ().getBaseName () != name)
6208
6222
continue ;
6209
6223
6224
+ auto memberClangDecl = namedMember->getClangDecl ();
6225
+
6226
+ // Skip this base class if this is a case of nested private inheritance.
6227
+ //
6228
+ // BUG: private base class members should be inherited but inaccessible.
6229
+ // Skipping them here may affect accurate overload resolution in cases of
6230
+ // multiple inheritance (which is currently buggy anyway).
6231
+ if (memberClangDecl->getAccess () == clang::AS_private)
6232
+ continue ;
6233
+
6210
6234
if (auto imported = clangModuleLoader->importBaseMemberDecl (
6211
- namedMember, inheritingDecl))
6235
+ namedMember, inheritingDecl, inheritance ))
6212
6236
result.push_back (cast<ValueDecl>(imported));
6213
6237
}
6214
6238
}
@@ -6226,7 +6250,15 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6226
6250
foundNameArities.insert (getArity (valueDecl));
6227
6251
6228
6252
for (auto base : cxxRecord->bases ()) {
6229
- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
6253
+ clang::AccessSpecifier baseInheritance = base.getAccessSpecifier ();
6254
+ // Skip this base class if this is a case of nested private inheritance.
6255
+ //
6256
+ // BUG: members of private base classes should actually be imported but
6257
+ // inaccessible. Skipping them here may affect accurate overload
6258
+ // resolution in cases of multiple inheritance (which is currently buggy
6259
+ // anyway).
6260
+ if (inheritance != clang::AS_none &&
6261
+ baseInheritance == clang::AS_private)
6230
6262
continue ;
6231
6263
6232
6264
clang::QualType baseType = base.getType ();
@@ -6242,12 +6274,19 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
6242
6274
if (cast<ValueDecl>(import )->getName () == name)
6243
6275
continue ;
6244
6276
6277
+ if (inheritance != clang::AS_none)
6278
+ // For nested inheritance, clamp inheritance to least permissive level
6279
+ // which is the largest numerical value for clang::AccessSpecifier
6280
+ baseInheritance = std::max (inheritance, baseInheritance);
6281
+ static_assert (clang::AS_private > clang::AS_protected &&
6282
+ clang::AS_protected > clang::AS_public &&
6283
+ " using std::max() relies on this ordering" );
6284
+
6245
6285
// Add Clang members that are imported lazily.
6246
6286
auto baseResults = evaluateOrDefault (
6247
6287
ctx.evaluator ,
6248
- ClangRecordMemberLookup (
6249
- {cast<NominalTypeDecl>(import ), name, inheritingDecl}),
6250
- {});
6288
+ ClangRecordMemberLookup ({cast<NominalTypeDecl>(import ), name,
6289
+ inheritingDecl, baseInheritance}), {});
6251
6290
6252
6291
for (auto foundInBase : baseResults) {
6253
6292
// Do not add duplicate entry with the same arity,
@@ -7507,18 +7546,13 @@ Decl *ClangImporter::importDeclDirectly(const clang::NamedDecl *decl) {
7507
7546
return Impl.importDecl (decl, Impl.CurrentVersion );
7508
7547
}
7509
7548
7510
- ValueDecl *ClangImporter::Implementation::importBaseMemberDecl (
7511
- ValueDecl *decl, DeclContext *newContext) {
7512
- // Do not clone private C++ decls.
7513
- if (decl->getFormalAccess () < AccessLevel::Public)
7514
- return nullptr ;
7515
-
7549
+ ValueDecl *ClangImporter::Implementation::importBaseMemberDecl (ValueDecl *decl, DeclContext *newContext, clang::AccessSpecifier inheritance) {
7516
7550
// Make sure we don't clone the decl again for this class, as that would
7517
7551
// result in multiple definitions of the same symbol.
7518
7552
std::pair<ValueDecl *, DeclContext *> key = {decl, newContext};
7519
7553
auto known = clonedBaseMembers.find (key);
7520
7554
if (known == clonedBaseMembers.end ()) {
7521
- ValueDecl *cloned = cloneBaseMemberDecl (decl, newContext);
7555
+ ValueDecl *cloned = cloneBaseMemberDecl (decl, newContext, inheritance );
7522
7556
known = clonedBaseMembers.insert ({key, cloned}).first ;
7523
7557
}
7524
7558
@@ -7536,8 +7570,9 @@ size_t ClangImporter::Implementation::getImportedBaseMemberDeclArity(
7536
7570
}
7537
7571
7538
7572
ValueDecl *ClangImporter::importBaseMemberDecl (ValueDecl *decl,
7539
- DeclContext *newContext) {
7540
- return Impl.importBaseMemberDecl (decl, newContext);
7573
+ DeclContext *newContext,
7574
+ clang::AccessSpecifier inheritance) {
7575
+ return Impl.importBaseMemberDecl (decl, newContext, inheritance);
7541
7576
}
7542
7577
7543
7578
void ClangImporter::diagnoseTopLevelValue (const DeclName &name) {
0 commit comments