Skip to content

Commit 3ff7047

Browse files
author
ematejska
authored
Merge pull request #10216 from slavapestov/default-arguments-versus-effective-access-4.0-02-06-2017
Sema: Targeted fix for bad interaction between resilience checks and -enable-testing [4.0 06-02-2017]
2 parents 5e9c736 + ee24ce0 commit 3ff7047

File tree

9 files changed

+53
-36
lines changed

9 files changed

+53
-36
lines changed

include/swift/AST/Decl.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,8 @@ class ValueDecl : public Decl {
21692169
/// \see getFormalAccess
21702170
Accessibility getFormalAccessImpl(const DeclContext *useDC) const;
21712171

2172+
bool isVersionedInternalDecl() const;
2173+
21722174
/// Returns the access level specified explicitly by the user, or provided by
21732175
/// default according to language rules.
21742176
///
@@ -2178,9 +2180,16 @@ class ValueDecl : public Decl {
21782180
/// taken into account.
21792181
///
21802182
/// \sa getFormalAccessScope
2181-
Accessibility getFormalAccess(const DeclContext *useDC = nullptr) const {
2183+
Accessibility getFormalAccess(const DeclContext *useDC = nullptr,
2184+
bool respectVersionedAttr = false) const {
21822185
assert(hasAccessibility() && "accessibility not computed yet");
21832186
Accessibility result = TypeAndAccess.getInt().getValue();
2187+
if (respectVersionedAttr &&
2188+
result == Accessibility::Internal &&
2189+
isVersionedInternalDecl()) {
2190+
assert(!useDC);
2191+
return Accessibility::Public;
2192+
}
21842193
if (useDC && (result == Accessibility::Internal ||
21852194
result == Accessibility::Public))
21862195
return getFormalAccessImpl(useDC);
@@ -2201,7 +2210,8 @@ class ValueDecl : public Decl {
22012210
/// \sa getFormalAccess
22022211
/// \sa isAccessibleFrom
22032212
AccessScope
2204-
getFormalAccessScope(const DeclContext *useDC = nullptr) const;
2213+
getFormalAccessScope(const DeclContext *useDC = nullptr,
2214+
bool respectVersionedAttr = false) const;
22052215

22062216
/// Returns the access level that actually controls how a declaration should
22072217
/// be emitted and may be used.

lib/AST/Decl.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,8 @@ bool AbstractStorageDecl::hasFixedLayout() const {
13331333

13341334
// Private and (unversioned) internal variables always have a
13351335
// fixed layout.
1336-
if (getEffectiveAccess() < Accessibility::Public)
1336+
if (!getFormalAccessScope(/*useDC=*/nullptr,
1337+
/*respectVersionedAttr=*/true).isPublic())
13371338
return true;
13381339

13391340
// Check for an explicit @_fixed_layout attribute.
@@ -1889,18 +1890,18 @@ SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
18891890

18901891
/// Returns true if \p VD needs to be treated as publicly-accessible
18911892
/// at the SIL, LLVM, and machine levels due to being versioned.
1892-
static bool isVersionedInternalDecl(const ValueDecl *VD) {
1893-
assert(VD->getFormalAccess() == Accessibility::Internal);
1893+
bool ValueDecl::isVersionedInternalDecl() const {
1894+
assert(getFormalAccess() == Accessibility::Internal);
18941895

1895-
if (VD->getAttrs().hasAttribute<VersionedAttr>())
1896+
if (getAttrs().hasAttribute<VersionedAttr>())
18961897
return true;
18971898

1898-
if (auto *FD = dyn_cast<FuncDecl>(VD))
1899+
if (auto *FD = dyn_cast<FuncDecl>(this))
18991900
if (auto *ASD = FD->getAccessorStorageDecl())
19001901
if (ASD->getAttrs().hasAttribute<VersionedAttr>())
19011902
return true;
19021903

1903-
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
1904+
if (auto *EED = dyn_cast<EnumElementDecl>(this))
19041905
if (EED->getParentEnum()->getAttrs().hasAttribute<VersionedAttr>())
19051906
return true;
19061907

@@ -1927,21 +1928,17 @@ static Accessibility getTestableAccess(const ValueDecl *decl) {
19271928
}
19281929

19291930
Accessibility ValueDecl::getEffectiveAccess() const {
1930-
Accessibility effectiveAccess = getFormalAccess();
1931+
auto effectiveAccess = getFormalAccess(/*useDC=*/nullptr,
1932+
/*respectVersionedAttr=*/true);
19311933

19321934
// Handle @testable.
19331935
switch (effectiveAccess) {
1934-
case Accessibility::Public:
1935-
if (getModuleContext()->isTestingEnabled())
1936-
effectiveAccess = getTestableAccess(this);
1937-
break;
19381936
case Accessibility::Open:
19391937
break;
1938+
case Accessibility::Public:
19401939
case Accessibility::Internal:
19411940
if (getModuleContext()->isTestingEnabled())
19421941
effectiveAccess = getTestableAccess(this);
1943-
else if (isVersionedInternalDecl(this))
1944-
effectiveAccess = Accessibility::Public;
19451942
break;
19461943
case Accessibility::FilePrivate:
19471944
break;
@@ -1982,23 +1979,28 @@ Accessibility ValueDecl::getFormalAccessImpl(const DeclContext *useDC) const {
19821979
return getFormalAccess();
19831980
}
19841981

1985-
AccessScope ValueDecl::getFormalAccessScope(const DeclContext *useDC) const {
1982+
AccessScope ValueDecl::getFormalAccessScope(const DeclContext *useDC,
1983+
bool respectVersionedAttr) const {
19861984
const DeclContext *result = getDeclContext();
1987-
Accessibility access = getFormalAccess(useDC);
1985+
Accessibility access = getFormalAccess(useDC, respectVersionedAttr);
19881986

19891987
while (!result->isModuleScopeContext()) {
19901988
if (result->isLocalContext() || access == Accessibility::Private)
19911989
return AccessScope(result, true);
19921990

19931991
if (auto enclosingNominal = dyn_cast<NominalTypeDecl>(result)) {
1994-
access = std::min(access, enclosingNominal->getFormalAccess(useDC));
1992+
access = std::min(access,
1993+
enclosingNominal->getFormalAccess(useDC,
1994+
respectVersionedAttr));
19951995

19961996
} else if (auto enclosingExt = dyn_cast<ExtensionDecl>(result)) {
19971997
// Just check the base type. If it's a constrained extension, Sema should
19981998
// have already enforced access more strictly.
19991999
if (auto extendedTy = enclosingExt->getExtendedType()) {
20002000
if (auto nominal = extendedTy->getAnyNominal()) {
2001-
access = std::min(access, nominal->getFormalAccess(useDC));
2001+
access = std::min(access,
2002+
nominal->getFormalAccess(useDC,
2003+
respectVersionedAttr));
20022004
}
20032005
}
20042006

@@ -2050,7 +2052,8 @@ Type TypeDecl::getDeclaredInterfaceType() const {
20502052
bool NominalTypeDecl::hasFixedLayout() const {
20512053
// Private and (unversioned) internal types always have a
20522054
// fixed layout.
2053-
if (getEffectiveAccess() < Accessibility::Public)
2055+
if (!getFormalAccessScope(/*useDC=*/nullptr,
2056+
/*respectVersionedAttr=*/true).isPublic())
20542057
return true;
20552058

20562059
// Check for an explicit @_fixed_layout attribute.

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
533533

534534
// If the function is not externally visible, we will not be serializing
535535
// its body.
536-
if (AFD->getEffectiveAccess() < Accessibility::Public)
536+
if (!AFD->getFormalAccessScope(/*useDC=*/nullptr,
537+
/*respectVersionedAttr=*/true).isPublic())
537538
break;
538539

539540
// Bodies of public transparent and always-inline functions are

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ bool TypeChecker::diagnoseInlineableDeclRef(SourceLoc loc,
9191
return false;
9292

9393
// Public declarations are OK.
94-
if (D->getEffectiveAccess() >= Accessibility::Public)
94+
if (D->getFormalAccessScope(/*useDC=*/nullptr,
95+
/*respectVersionedAttr=*/true).isPublic())
9596
return false;
9697

9798
// Enum cases are handled as part of their containing enum.
@@ -110,7 +111,8 @@ bool TypeChecker::diagnoseInlineableDeclRef(SourceLoc loc,
110111

111112
diagnose(loc, diag::resilience_decl_unavailable,
112113
D->getDescriptiveKind(), D->getFullName(),
113-
D->getFormalAccess(), getFragileFunctionKind(DC));
114+
D->getFormalAccessScope().accessibilityForDiagnostics(),
115+
getFragileFunctionKind(DC));
114116
diagnose(D, diag::resilience_decl_declared_here,
115117
D->getDescriptiveKind(), D->getFullName());
116118
return true;

lib/Sema/TypeCheckAttr.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,19 +1826,16 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
18261826
/*allowConcreteGenericParams=*/true);
18271827
}
18281828

1829-
static Accessibility getAccessForDiagnostics(const ValueDecl *D) {
1830-
return std::min(D->getFormalAccess(),
1831-
D->getEffectiveAccess());
1832-
}
1833-
18341829
void AttributeChecker::visitFixedLayoutAttr(FixedLayoutAttr *attr) {
18351830
auto *VD = cast<ValueDecl>(D);
18361831

1837-
if (VD->getEffectiveAccess() < Accessibility::Public) {
1832+
auto access = VD->getFormalAccess(/*useDC=*/nullptr,
1833+
/*respectVersionedAttr=*/true);
1834+
if (access < Accessibility::Public) {
18381835
TC.diagnose(attr->getLocation(),
18391836
diag::fixed_layout_attr_on_internal_type,
18401837
VD->getName(),
1841-
getAccessForDiagnostics(VD))
1838+
access)
18421839
.fixItRemove(attr->getRangeWithAt());
18431840
attr->setInvalid();
18441841
}
@@ -1888,13 +1885,13 @@ void AttributeChecker::visitInlineableAttr(InlineableAttr *attr) {
18881885

18891886
// @_inlineable can only be applied to public or @_versioned
18901887
// declarations.
1891-
if (VD->getFormalAccess() < Accessibility::Internal ||
1892-
(!VD->getAttrs().hasAttribute<VersionedAttr>() &&
1893-
VD->getFormalAccess() < Accessibility::Public)) {
1888+
auto access = VD->getFormalAccess(/*useDC=*/nullptr,
1889+
/*respectVersionedAttr=*/true);
1890+
if (access < Accessibility::Public) {
18941891
TC.diagnose(attr->getLocation(),
18951892
diag::inlineable_decl_not_public,
18961893
VD->getName(),
1897-
getAccessForDiagnostics(VD))
1894+
access)
18981895
.fixItRemove(attr->getRangeWithAt());
18991896
attr->setInvalid();
19001897
return;

lib/Sema/TypeCheckStmt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,8 @@ static void checkDefaultArguments(TypeChecker &tc,
13121312
// caller.
13131313
auto expansion = func->getResilienceExpansion();
13141314
if (!tc.Context.isSwiftVersion3() &&
1315-
func->getEffectiveAccess() == Accessibility::Public)
1315+
func->getFormalAccessScope(/*useDC=*/nullptr,
1316+
/*respectVersionedAttr=*/true).isPublic())
13161317
expansion = ResilienceExpansion::Minimal;
13171318

13181319
for (auto &param : *params) {

test/attr/attr_fixed_layout.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %target-swift-frontend -typecheck -verify -dump-ast -enable-resilience %s 2>&1 | %FileCheck --check-prefix=RESILIENCE-ON %s
2+
// RUN: %target-swift-frontend -typecheck -verify -dump-ast -enable-resilience -enable-testing %s 2>&1 | %FileCheck --check-prefix=RESILIENCE-ON %s
23
// RUN: %target-swift-frontend -typecheck -verify -dump-ast %s 2>&1 | %FileCheck --check-prefix=RESILIENCE-OFF %s
4+
// RUN: %target-swift-frontend -typecheck -verify -dump-ast %s -enable-testing 2>&1 | %FileCheck --check-prefix=RESILIENCE-OFF %s
35

46
//
57
// Public types with @_fixed_layout are always fixed layout
@@ -54,7 +56,6 @@ struct Rectangle {
5456
// expected-error@-1 {{'@_fixed_layout' attribute can only be applied to '@_versioned' or public declarations, but 'InternalStruct' is internal}}
5557

5658
@_fixed_layout public struct NestedStruct {}
57-
// expected-error@-1 {{'@_fixed_layout' attribute can only be applied to '@_versioned' or public declarations, but 'NestedStruct' is internal}}
5859
}
5960

6061
@_fixed_layout fileprivate struct FileprivateStruct {}

test/attr/attr_inlineable.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-typecheck-verify-swift -swift-version 4
2+
// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-testing
23

34
@_inlineable struct TestInlineableStruct {}
45
// expected-error@-1 {{@_inlineable cannot be applied to this declaration}}

test/attr/attr_versioned.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-typecheck-verify-swift -enable-testing
23

34
@_versioned private func privateVersioned() {}
45
// expected-error@-1 {{'@_versioned' attribute can only be applied to internal declarations, but 'privateVersioned' is private}}

0 commit comments

Comments
 (0)