From edb71db1c6df03eb5415ca86921b3b676874467c Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 4 May 2020 15:36:41 -0400 Subject: [PATCH 1/2] AST: Diagnose references to non-public declarations from default arguments of inlinable local functions Part of . --- lib/AST/DeclContext.cpp | 7 +++++++ test/attr/attr_inlinable.swift | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index b561b1e22718b..e4f21d07caa6e 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -348,6 +348,13 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator, auto *VD = cast(dc->getAsDecl()); assert(VD->hasParameterList()); + if (VD->getDeclContext()->isLocalContext()) { + auto kind = VD->getDeclContext()->getFragileFunctionKind(); + if (kind.kind != FragileFunctionKind::None) + return {FragileFunctionKind::DefaultArgument, + kind.allowUsableFromInline}; + } + auto effectiveAccess = VD->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); diff --git a/test/attr/attr_inlinable.swift b/test/attr/attr_inlinable.swift index 034a19ed56d81..ade8d9e7278c1 100644 --- a/test/attr/attr_inlinable.swift +++ b/test/attr/attr_inlinable.swift @@ -9,11 +9,11 @@ // expected-warning@-1 {{'@inlinable' declaration is already '@usableFromInline'}} private func privateFunction() {} -// expected-note@-1{{global function 'privateFunction()' is not '@usableFromInline' or public}} +// expected-note@-1 2{{global function 'privateFunction()' is not '@usableFromInline' or public}} fileprivate func fileprivateFunction() {} // expected-note@-1{{global function 'fileprivateFunction()' is not '@usableFromInline' or public}} func internalFunction() {} -// expected-note@-1{{global function 'internalFunction()' is not '@usableFromInline' or public}} +// expected-note@-1 2{{global function 'internalFunction()' is not '@usableFromInline' or public}} @usableFromInline func versionedFunction() {} public func publicFunction() {} @@ -306,3 +306,16 @@ public struct PrivateInlinableCrash { value ? "YES" : "NO" } } + +// https://bugs.swift.org/browse/SR-12404 +@inlinable public func inlinableOuterFunction() { + func innerFunction1(x: () = privateFunction()) {} + // expected-error@-1 {{global function 'privateFunction()' is private and cannot be referenced from a default argument value}} + + func innerFunction2(x: () = internalFunction()) {} + // expected-error@-1 {{global function 'internalFunction()' is internal and cannot be referenced from a default argument value}} + + func innerFunction3(x: () = versionedFunction()) {} + + func innerFunction4(x: () = publicFunction()) {} +} \ No newline at end of file From 001534cfef64304744439809b5df0dc85884f805 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 4 May 2020 15:37:23 -0400 Subject: [PATCH 2/2] SIL: Serialize default arguments of inlinable local functions Fixes . --- lib/SIL/IR/SILDeclRef.cpp | 16 ++++++++++------ test/SILGen/default_arguments_local.swift | 13 +++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 5abf3a81364be..a05a1a15f4b22 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -442,12 +442,9 @@ bool SILDeclRef::isTransparent() const { /// True if the function should have its body serialized. IsSerialized_t SILDeclRef::isSerialized() const { - DeclContext *dc; if (auto closure = getAbstractClosureExpr()) { - dc = closure->getLocalContext(); - - // Otherwise, ask the AST if we're inside an @inlinable context. - if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) { + // Ask the AST if we're inside an @inlinable context. + if (closure->getResilienceExpansion() == ResilienceExpansion::Minimal) { if (isForeign) return IsSerializable; @@ -465,6 +462,13 @@ IsSerialized_t SILDeclRef::isSerialized() const { // Default argument generators are serialized if the containing // declaration is public. if (isDefaultArgGenerator()) { + // Ask the AST if we're inside an @inlinable context. + if (d->getDeclContext()->getResilienceExpansion() + == ResilienceExpansion::Minimal) { + return IsSerialized; + } + + // Otherwise, check if the owning declaration is public. auto scope = d->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); @@ -490,7 +494,7 @@ IsSerialized_t SILDeclRef::isSerialized() const { // Note: if 'd' is a function, then 'dc' is the function itself, not // its parent context. - dc = d->getInnermostDeclContext(); + auto *dc = d->getInnermostDeclContext(); // Local functions are serializable if their parent function is // serializable. diff --git a/test/SILGen/default_arguments_local.swift b/test/SILGen/default_arguments_local.swift index faf8df999103c..d2d804f1e8a6a 100644 --- a/test/SILGen/default_arguments_local.swift +++ b/test/SILGen/default_arguments_local.swift @@ -57,3 +57,16 @@ class ArtClass { return 0 } } + +// Default arguments of local functions inside @inlinable contexts should be serialized. +// https://bugs.swift.org/browse/SR-12404 + +// CHECK-LABEL: sil [serialized] [ossa] @$s23default_arguments_local5outeryyF : $@convention(thin) () -> () { +@inlinable public func outer() { + // CHECK-LABEL: sil shared [serialized] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tFfA_ : $@convention(thin) () -> Int { + + // CHECK-LABEL: sil shared [serializable] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tF : $@convention(thin) (Int) -> () { + func inner(x: Int = 0) {} + + inner() +}