Skip to content

Commit a54765b

Browse files
authored
Merge pull request #33781 from hamishknight/is-this-odr
2 parents bec6a8f + ef5335a commit a54765b

File tree

5 files changed

+195
-200
lines changed

5 files changed

+195
-200
lines changed

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,11 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
233233
return forDefinition ? linkage : addExternalToLinkage(linkage);
234234
};
235235

236-
// Native function-local declarations have shared linkage.
237-
// FIXME: @objc declarations should be too, but we currently have no way
238-
// of marking them "used" other than making them external.
236+
// Function-local declarations have private linkage, unless serialized.
239237
ValueDecl *d = getDecl();
240238
DeclContext *moduleContext = d->getDeclContext();
241239
while (!moduleContext->isModuleScopeContext()) {
242-
if (!isForeign && moduleContext->isLocalContext()) {
240+
if (moduleContext->isLocalContext()) {
243241
return isSerialized() ? SILLinkage::Shared : SILLinkage::Private;
244242
}
245243
moduleContext = moduleContext->getParent();
@@ -249,11 +247,6 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
249247
if (isForeignToNativeThunk())
250248
return SILLinkage::Shared;
251249

252-
// If a function declares a @_cdecl name, its native-to-foreign thunk
253-
// is exported with the visibility of the function.
254-
if (isNativeToForeignThunk() && !d->getAttrs().hasAttribute<CDeclAttr>())
255-
return SILLinkage::Shared;
256-
257250
// Declarations imported from Clang modules have shared linkage.
258251
if (isClangImported())
259252
return SILLinkage::Shared;
@@ -329,12 +322,20 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
329322
}
330323
}
331324

332-
// Forced-static-dispatch functions are created on-demand and have
333-
// at best shared linkage.
334325
if (auto fn = dyn_cast<FuncDecl>(d)) {
326+
// Forced-static-dispatch functions are created on-demand and have
327+
// at best shared linkage.
335328
if (fn->hasForcedStaticDispatch()) {
336329
limit = Limit::OnDemand;
337330
}
331+
332+
// Native-to-foreign thunks for top-level decls are created on-demand,
333+
// unless they are marked @_cdecl, in which case they expose a dedicated
334+
// entry-point with the visibility of the function.
335+
if (isNativeToForeignThunk() && !fn->getAttrs().hasAttribute<CDeclAttr>()) {
336+
if (fn->getDeclContext()->isModuleScopeContext())
337+
limit = Limit::OnDemand;
338+
}
338339
}
339340

340341
if (isEnumElement()) {
@@ -613,34 +614,42 @@ EffectsKind SILDeclRef::getEffectsAttribute() const {
613614
}
614615

615616
bool SILDeclRef::isForeignToNativeThunk() const {
617+
// If this isn't a native entry-point, it's not a foreign-to-native thunk.
618+
if (isForeign)
619+
return false;
620+
616621
// Non-decl entry points are never natively foreign, so they would never
617622
// have a foreign-to-native thunk.
618623
if (!hasDecl())
619624
return false;
620625
if (requiresForeignToNativeThunk(getDecl()))
621-
return !isForeign;
626+
return true;
622627
// ObjC initializing constructors and factories are foreign.
623628
// We emit a special native allocating constructor though.
624629
if (isa<ConstructorDecl>(getDecl())
625630
&& (kind == Kind::Initializer
626631
|| cast<ConstructorDecl>(getDecl())->isFactoryInit())
627632
&& getDecl()->hasClangNode())
628-
return !isForeign;
633+
return true;
629634
return false;
630635
}
631636

632637
bool SILDeclRef::isNativeToForeignThunk() const {
638+
// If this isn't a foreign entry-point, it's not a native-to-foreign thunk.
639+
if (!isForeign)
640+
return false;
641+
633642
// We can have native-to-foreign thunks over closures.
634643
if (!hasDecl())
635-
return isForeign;
636-
// We can have native-to-foreign thunks over global or local native functions.
637-
// TODO: Static functions too.
638-
if (auto func = dyn_cast<FuncDecl>(getDecl())) {
639-
if (!func->getDeclContext()->isTypeContext()
640-
&& !func->hasClangNode())
641-
return isForeign;
642-
}
643-
return false;
644+
return true;
645+
646+
// A decl with a clang node doesn't have a native entry-point to forward onto.
647+
if (getDecl()->hasClangNode())
648+
return false;
649+
650+
// Only certain kinds of SILDeclRef can expose native-to-foreign thunks.
651+
return kind == Kind::Func || kind == Kind::Initializer ||
652+
kind == Kind::Deallocator;
644653
}
645654

646655
/// Use the Clang importer to mangle a Clang declaration.

0 commit comments

Comments
 (0)