Skip to content

Commit

Permalink
Re-apply "Fix linkage of 'static inline' Clang-imported definitions"
Browse files Browse the repository at this point in the history
This re-applies commit r31763 with a change to the predicate we
use for determining the linkage of a definition. It turns out we
could have definitions with a Clang body that were still public,
so instead of checking for a Clang body just check if the Clang
declaration is externally visible or not.

Swift SVN r31777
  • Loading branch information
slavapestov committed Sep 8, 2015
1 parent db4c6e4 commit 7cf7298
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 12 deletions.
6 changes: 5 additions & 1 deletion include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,14 @@ struct SILDeclRef {
/// True if the referenced entity is some kind of thunk.
bool isThunk() const;

/// True if the referenced entity is generated on behalf of the Clang
/// True if the referenced entity is emitted by Swift on behalf of the Clang
/// importer.
bool isClangImported() const;

/// True if the referenced entity is emitted by Clang on behalf of the Clang
/// importer.
bool isClangGenerated() const;

bool isImplicit() const {
if (hasDecl())
return getDecl()->isImplicit();
Expand Down
16 changes: 11 additions & 5 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,13 @@ class SILFunction
/// The linkage of the function.
unsigned Linkage : NumSILLinkageBits;

/// This flags indicates if a function can be
/// eliminated by dead function elimination.
/// If it is unset, DFE will preserve the function
/// and make it public.
unsigned KeepAsPublic: 1;
/// This flag indicates if a function can be eliminated by dead function
/// elimination. If it is unset, DFE will preserve the function and make
/// it public.
unsigned KeepAsPublic : 1;

/// This flag indicates if a function has a body generated by Clang.
unsigned ForeignBody : 1;

/// This is the number of uses of this SILFunction inside the SIL.
/// It does not include references from debug scopes.
Expand Down Expand Up @@ -421,6 +423,10 @@ class SILFunction
bool isKeepAsPublic() const { return KeepAsPublic; }
void setKeepAsPublic(bool keep) { KeepAsPublic = keep; }

/// Get this function's foreign body attribute.
HasForeignBody_t hasForeignBody() const { return HasForeignBody_t(ForeignBody); }
void setForeignBody(HasForeignBody_t foreign) { ForeignBody = foreign; }

/// Retrieve the generic parameter list containing the contextual archetypes
/// of the function.
///
Expand Down
10 changes: 8 additions & 2 deletions include/swift/SIL/SILLinkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,18 @@ enum {
NumSILLinkageBits = 3
};

/// Reslated to linkage: flag if a function or global variable is fragle.
/// Related to linkage: flag if a function or global variable is fragile.
enum IsFragile_t {
IsNotFragile,
IsFragile
};


/// True if we have an inline body generated by Clang.
enum HasForeignBody_t {
DoesNotHaveForeignBody,
HasForeignBody
};

/// Strip external from public_external, hidden_external. Otherwise just return
/// the linkage.
inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) {
Expand Down
16 changes: 16 additions & 0 deletions lib/SIL/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ bool SILDeclRef::isClangImported() const {
DeclContext *moduleContext = d->getDeclContext()->getModuleScopeContext();

if (isa<ClangModuleUnit>(moduleContext)) {
if (isClangGenerated())
return true;

if (isa<ConstructorDecl>(d) || isa<EnumElementDecl>(d))
return true;

Expand All @@ -226,6 +229,19 @@ bool SILDeclRef::isClangImported() const {
return false;
}

bool SILDeclRef::isClangGenerated() const {
if (!hasDecl())
return false;

auto clangNode = getDecl()->getClangNode().getAsDecl();
if (auto nd = dyn_cast_or_null<clang::NamedDecl>(clangNode)) {
if (!nd->isExternallyVisible())
return true;
}

return false;
}

SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
// Anonymous functions have local linkage.
if (auto closure = getAbstractClosureExpr())
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
InlineStrategy(inlineStrategy),
Linkage(unsigned(Linkage)),
KeepAsPublic(false),
ForeignBody(false),
EK(E) {
if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
Expand Down
6 changes: 5 additions & 1 deletion lib/SIL/SILModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,14 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
F->setDebugScope(new (*this) SILDebugScope(loc, *F));

F->setGlobalInit(constant.isGlobal());
if (constant.hasDecl())
if (constant.hasDecl()) {
if (constant.isForeign && constant.isClangGenerated())
F->setForeignBody(HasForeignBody);

if (auto SemanticsA =
constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>())
F->setSemanticsAttr(SemanticsA->Value);
}

F->setDeclContext(constant.hasDecl() ? constant.getDecl() : nullptr);

Expand Down
7 changes: 6 additions & 1 deletion lib/SIL/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2947,16 +2947,21 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
verifySILFunctionType(FTy);

if (F->isExternalDeclaration()) {
if (F->hasForeignBody())
return;

assert(F->isAvailableExternally() &&
"external declaration of internal SILFunction not allowed");
assert(!hasSharedVisibility(F->getLinkage()) &&
"external declarations of SILFunctions with shared visiblity is not "
"external declarations of SILFunctions with shared visibility is not "
"allowed");
// If F is an external declaration, there is nothing further to do,
// return.
return;
}

assert(!F->hasForeignBody());

// Make sure that our SILFunction only has context generic params if our
// SILFunctionType is non-polymorphic.
if (F->getContextGenericParams()) {
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/c_globals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import c_layout
func blackHole<T>(t: T) { }

// CHECK: @staticFloat = internal global float 1.700000e+01, align 4
// CHECK: define {{.*}}void @doubleTrouble() [[CLANG_FUNC_ATTR:#[0-9]+]] {
// CHECK: define internal void @doubleTrouble() [[CLANG_FUNC_ATTR:#[0-9]+]] {

public func testStaticGlobal() {
blackHole(c_layout.staticFloat)
Expand Down
8 changes: 7 additions & 1 deletion test/SILGen/Inputs/usr/include/Ansible.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
- (Ansible*)initWithBellsOn:(id)theBells;
@end

Ansible *NSAnse(Ansible *x) {
static Ansible *NSAnse(Ansible *x) {
return x;
}

Ansible *NSAnseExternal(Ansible *x) {
return x;
}

void hasNoPrototype();

static void staticForwardDeclaration(void);

0 comments on commit 7cf7298

Please sign in to comment.