Skip to content

Commit a0e160e

Browse files
committed
AST: Refactor Decl::isWeakImported() API a little bit
First, remove the AvailabilityContext parameter; it was confusing because we actually always want to use the deployment target here. Then, split this method up into three methods: - isAlwaysWeakImported(): simply checks for a @_weakLinked attribute, either on the declaration itself or one of its parent contexts. - getAvailabilityForLinkage(): returns the OS version availability when this declaration was introduced, or if the declaration does not have explicit availability, check it's storage (if its an accessor), or its parent contexts. - isWeakImported(ModuleDecl *fromModule): combines these two checks to determine if the declaration should be weak linked when referenced from the given module, or if it might be weak referenced from some module (if the module parameter is null).
1 parent 0fd7cb8 commit a0e160e

File tree

12 files changed

+101
-61
lines changed

12 files changed

+101
-61
lines changed

include/swift/AST/Decl.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -940,9 +940,31 @@ class alignas(1 << DeclAlignInBits) Decl {
940940

941941
bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
942942

943-
/// Whether this declaration is weak-imported.
944-
bool isWeakImported(ModuleDecl *fromModule,
945-
AvailabilityContext fromContext) const;
943+
AvailabilityContext getAvailabilityForLinkage() const;
944+
945+
/// Whether this declaration or one of its outer contexts has the
946+
/// @_weakLinked attribute.
947+
bool isAlwaysWeakImported() const;
948+
949+
/// Whether this declaration is weak-imported from the given module,
950+
/// either because of the presence of the @_weakLinked attribute, or
951+
/// because of availability.
952+
///
953+
/// Note that \p fromModule should either be the "main module" or
954+
/// nullptr. (This is because when it is non-null, we query the
955+
/// current deployment target, and not the deployment target that
956+
/// the module was built with.)
957+
///
958+
/// If \p fromModule is the main module, this returns false when the
959+
/// declaration is part of the main module, or if the declaration is
960+
/// at least as available as the current deployment target.
961+
///
962+
/// If \p fromModule is null, we instead return true if the
963+
/// declaration is meant to be weak linked with _some_ deployment
964+
/// target; that is, the presence of the @_weakLinked attribute or
965+
/// any kind of availability is enough, irrespective of the current
966+
/// deployment target.
967+
bool isWeakImported(ModuleDecl *fromModule) const;
946968

947969
/// Returns true if the nature of this declaration allows overrides.
948970
/// Note that this does not consider whether it is final or whether

include/swift/AST/ProtocolConformance.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,7 @@ class RootProtocolConformance : public ProtocolConformance {
343343
bool isInvalid() const;
344344

345345
/// Whether this conformance is weak-imported.
346-
bool isWeakImported(ModuleDecl *fromModule,
347-
AvailabilityContext fromContext) const;
346+
bool isWeakImported(ModuleDecl *fromModule) const;
348347

349348
bool hasWitness(ValueDecl *requirement) const;
350349
Witness getWitness(ValueDecl *requirement) const;

include/swift/IRGen/Linking.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,8 +1111,7 @@ class LinkEntity {
11111111
}
11121112

11131113
/// Determine whether this entity will be weak-imported.
1114-
bool isWeakImported(ModuleDecl *module,
1115-
AvailabilityContext fromContext) const;
1114+
bool isWeakImported(ModuleDecl *module) const;
11161115

11171116
/// Return the source file whose codegen should trigger emission of this
11181117
/// link entity, if one can be identified.
@@ -1182,7 +1181,6 @@ class LinkInfo {
11821181

11831182
static LinkInfo get(const UniversalLinkageInfo &linkInfo,
11841183
ModuleDecl *swiftModule,
1185-
AvailabilityContext availabilityContext,
11861184
const LinkEntity &entity,
11871185
ForDefinition_t forDefinition);
11881186

lib/AST/Decl.cpp

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -617,42 +617,66 @@ bool Decl::isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic) const {
617617
return false;
618618
}
619619

620-
bool Decl::isWeakImported(ModuleDecl *fromModule,
621-
AvailabilityContext fromContext) const {
620+
AvailabilityContext Decl::getAvailabilityForLinkage() const {
621+
auto containingContext =
622+
AvailabilityInference::annotatedAvailableRange(this, getASTContext());
623+
if (containingContext.hasValue())
624+
return *containingContext;
625+
626+
if (auto *accessor = dyn_cast<AccessorDecl>(this))
627+
return accessor->getStorage()->getAvailabilityForLinkage();
628+
629+
auto *dc = getDeclContext();
630+
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
631+
return ext->getAvailabilityForLinkage();
632+
else if (auto *nominal = dyn_cast<NominalTypeDecl>(dc))
633+
return nominal->getAvailabilityForLinkage();
634+
635+
return AvailabilityContext::alwaysAvailable();
636+
}
637+
638+
bool Decl::isAlwaysWeakImported() const {
622639
// For a Clang declaration, trust Clang.
623640
if (auto clangDecl = getClangDecl()) {
624641
return clangDecl->isWeakImported();
625642
}
626643

627-
auto *containingModule = getModuleContext();
628-
if (containingModule == fromModule)
629-
return false;
630-
631-
auto containingContext =
632-
AvailabilityInference::availableRange(this,
633-
containingModule->getASTContext());
634-
if (!fromContext.isContainedIn(containingContext))
635-
return true;
636-
637644
if (getAttrs().hasAttribute<WeakLinkedAttr>())
638645
return true;
639646

640647
if (auto *accessor = dyn_cast<AccessorDecl>(this))
641-
return accessor->getStorage()->isWeakImported(fromModule, fromContext);
642-
643-
if (auto *dtor = dyn_cast<DestructorDecl>(this))
644-
return cast<ClassDecl>(dtor->getDeclContext())->isWeakImported(
645-
fromModule, fromContext);
648+
return accessor->getStorage()->isAlwaysWeakImported();
646649

647650
auto *dc = getDeclContext();
648651
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
649-
return ext->isWeakImported(fromModule, fromContext);
650-
if (auto *ntd = dyn_cast<NominalTypeDecl>(dc))
651-
return ntd->isWeakImported(fromModule, fromContext);
652+
return ext->isAlwaysWeakImported();
653+
if (auto *nominal = dyn_cast<NominalTypeDecl>(dc))
654+
return nominal->isAlwaysWeakImported();
652655

653656
return false;
654657
}
655658

659+
bool Decl::isWeakImported(ModuleDecl *fromModule) const {
660+
if (fromModule == nullptr) {
661+
return (isAlwaysWeakImported() ||
662+
!getAvailabilityForLinkage().isAlwaysAvailable());
663+
}
664+
665+
if (getModuleContext() == fromModule)
666+
return false;
667+
668+
if (isAlwaysWeakImported())
669+
return true;
670+
671+
auto containingContext = getAvailabilityForLinkage();
672+
if (containingContext.isAlwaysAvailable())
673+
return false;
674+
675+
auto fromContext = AvailabilityContext::forDeploymentTarget(
676+
fromModule->getASTContext());
677+
return !fromContext.isContainedIn(containingContext);
678+
}
679+
656680
GenericParamList::GenericParamList(SourceLoc LAngleLoc,
657681
ArrayRef<GenericTypeParamDecl *> Params,
658682
SourceLoc WhereLoc,

lib/AST/ProtocolConformance.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,25 +400,24 @@ SourceLoc RootProtocolConformance::getLoc() const {
400400
}
401401

402402
bool
403-
RootProtocolConformance::isWeakImported(ModuleDecl *fromModule,
404-
AvailabilityContext fromContext) const {
403+
RootProtocolConformance::isWeakImported(ModuleDecl *fromModule) const {
405404
auto *dc = getDeclContext();
406405
if (dc->getParentModule() == fromModule)
407406
return false;
408407

409408
// If the protocol is weak imported, so are any conformances to it.
410-
if (getProtocol()->isWeakImported(fromModule, fromContext))
409+
if (getProtocol()->isWeakImported(fromModule))
411410
return true;
412411

413412
// If the conforming type is weak imported, so are any of its conformances.
414413
if (auto *nominal = getType()->getAnyNominal())
415-
if (nominal->isWeakImported(fromModule, fromContext))
414+
if (nominal->isWeakImported(fromModule))
416415
return true;
417416

418417
// If the conformance is declared in an extension with the @_weakLinked
419418
// attribute, it is weak imported.
420419
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
421-
if (ext->isWeakImported(fromModule, fromContext))
420+
if (ext->isWeakImported(fromModule))
422421
return true;
423422

424423
return false;

lib/IRGen/AllocStackHoisting.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ static bool isHoistable(AllocStackInst *Inst, irgen::IRGenModule &Mod) {
6262
bool foundWeaklyImported =
6363
SILTy.getASTType().findIf([&Mod](CanType type) -> bool {
6464
if (auto nominal = type->getNominalOrBoundGenericNominal())
65-
if (nominal->isWeakImported(Mod.getSwiftModule(),
66-
Mod.getAvailabilityContext())) {
65+
if (nominal->isWeakImported(Mod.getSwiftModule())) {
6766
return true;
6867
}
6968
return false;

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,8 +1728,7 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,
17281728
// TODO: there are probably cases where we can avoid redoing the
17291729
// entire linkage computation.
17301730
UniversalLinkageInfo linkInfo(IGM);
1731-
bool weakImported = entity.isWeakImported(IGM.getSwiftModule(),
1732-
IGM.getAvailabilityContext());
1731+
bool weakImported = entity.isWeakImported(IGM.getSwiftModule());
17331732
auto IRL =
17341733
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
17351734
ForDefinition, weakImported);
@@ -1749,13 +1748,11 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
17491748
ForDefinition_t isDefinition) {
17501749
return LinkInfo::get(UniversalLinkageInfo(IGM),
17511750
IGM.getSwiftModule(),
1752-
IGM.getAvailabilityContext(),
17531751
entity, isDefinition);
17541752
}
17551753

17561754
LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
17571755
ModuleDecl *swiftModule,
1758-
AvailabilityContext availabilityContext,
17591756
const LinkEntity &entity,
17601757
ForDefinition_t isDefinition) {
17611758
LinkInfo result;
@@ -1771,7 +1768,7 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
17711768
ForDefinition_t(swiftModule->isStdlibModule() || isDefinition);
17721769

17731770
entity.mangle(result.Name);
1774-
bool weakImported = entity.isWeakImported(swiftModule, availabilityContext);
1771+
bool weakImported = entity.isWeakImported(swiftModule);
17751772
result.IRL = getIRLinkage(linkInfo, entity.getLinkage(isStdlibOrDefinition),
17761773
isDefinition, weakImported);
17771774
result.ForDefinition = isDefinition;

lib/IRGen/GenEnum.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5395,8 +5395,7 @@ namespace {
53955395
llvm::BasicBlock *conditionalBlock = nullptr;
53965396
llvm::BasicBlock *afterConditionalBlock = nullptr;
53975397
llvm::BasicBlock *beforeNullPtrCheck = nullptr;
5398-
if (Case->isWeakImported(IGM.getSwiftModule(),
5399-
IGM.getAvailabilityContext())) {
5398+
if (Case->isWeakImported(IGM.getSwiftModule())) {
54005399
beforeNullPtrCheck = IGF.Builder.GetInsertBlock();
54015400
auto address = IGM.getAddrOfEnumCase(Case, NotForDefinition);
54025401
conditionalBlock = llvm::BasicBlock::Create(C);

lib/IRGen/Linking.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -962,21 +962,20 @@ Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
962962
}
963963
}
964964

965-
bool LinkEntity::isWeakImported(ModuleDecl *module,
966-
AvailabilityContext context) const {
965+
bool LinkEntity::isWeakImported(ModuleDecl *module) const {
967966
switch (getKind()) {
968967
case Kind::SILGlobalVariable:
969968
if (getSILGlobalVariable()->getDecl()) {
970969
return getSILGlobalVariable()->getDecl()
971-
->isWeakImported(module, context);
970+
->isWeakImported(module);
972971
}
973972
return false;
974973
case Kind::DynamicallyReplaceableFunctionKey:
975974
case Kind::DynamicallyReplaceableFunctionVariable:
976975
case Kind::SILFunction: {
977976
// For imported functions check the Clang declaration.
978977
if (auto clangOwner = getSILFunction()->getClangNodeOwner())
979-
return clangOwner->isWeakImported(module, context);
978+
return clangOwner->isWeakImported(module);
980979

981980
// For native functions check a flag on the SILFunction
982981
// itself.
@@ -992,16 +991,16 @@ bool LinkEntity::isWeakImported(ModuleDecl *module,
992991
// type stored in extra storage area is weak linked.
993992
auto assocConformance = getAssociatedConformance();
994993
auto *depMemTy = assocConformance.first->castTo<DependentMemberType>();
995-
return depMemTy->getAssocType()->isWeakImported(module, context);
994+
return depMemTy->getAssocType()->isWeakImported(module);
996995
}
997996

998997
case Kind::BaseConformanceDescriptor:
999-
return cast<ProtocolDecl>(getDecl())->isWeakImported(module, context);
998+
return cast<ProtocolDecl>(getDecl())->isWeakImported(module);
1000999

10011000
case Kind::TypeMetadata:
10021001
case Kind::TypeMetadataAccessFunction: {
10031002
if (auto *nominalDecl = getType()->getAnyNominal())
1004-
return nominalDecl->isWeakImported(module, context);
1003+
return nominalDecl->isWeakImported(module);
10051004
return false;
10061005
}
10071006

@@ -1033,12 +1032,12 @@ bool LinkEntity::isWeakImported(ModuleDecl *module,
10331032
case Kind::OpaqueTypeDescriptorAccessorImpl:
10341033
case Kind::OpaqueTypeDescriptorAccessorKey:
10351034
case Kind::OpaqueTypeDescriptorAccessorVar:
1036-
return getDecl()->isWeakImported(module, context);
1035+
return getDecl()->isWeakImported(module);
10371036

10381037
case Kind::ProtocolWitnessTable:
10391038
case Kind::ProtocolConformanceDescriptor:
10401039
return getProtocolConformance()->getRootConformance()
1041-
->isWeakImported(module, context);
1040+
->isWeakImported(module);
10421041

10431042
// TODO: Revisit some of the below, for weak conformances.
10441043
case Kind::ObjCMetadataUpdateFunction:

lib/SIL/SILFunctionBuilder.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,17 @@ SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant,
162162
if (constant.isForeign && decl->hasClangNode())
163163
F->setClangNodeOwner(decl);
164164

165-
if (decl->isWeakImported(/*forModule=*/nullptr, availCtx))
165+
if (decl->isAlwaysWeakImported())
166166
F->setWeakLinked();
167+
else {
168+
auto containingContext = decl->getAvailabilityForLinkage();
169+
if (!containingContext.isAlwaysAvailable()) {
170+
auto fromContext = AvailabilityContext::forDeploymentTarget(
171+
decl->getASTContext());
172+
if (!fromContext.isContainedIn(containingContext))
173+
F->setWeakLinked();
174+
}
175+
}
167176

168177
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
169178
auto *storage = accessor->getStorage();

0 commit comments

Comments
 (0)