Skip to content

Commit b248d2d

Browse files
committed
Sema: Restrict use of SPI operators to files importing the SPI group
Ensure that calls to SPI operators are only accepted in source files importing the corresponding SPI group. This applies the same logic to operators as we do for functions. rdar://137713966
1 parent 8e7fdb2 commit b248d2d

File tree

4 files changed

+29
-2
lines changed

4 files changed

+29
-2
lines changed

lib/AST/Decl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5536,9 +5536,17 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
55365536
return srcPkg && usePkg && usePkg->isSamePackageAs(srcPkg);
55375537
}
55385538
case AccessLevel::Public:
5539-
case AccessLevel::Open:
5539+
case AccessLevel::Open: {
5540+
if (VD->isOperator() && VD->isSPI()) {
5541+
const DeclContext *useFile = useDC->getModuleScopeContext();
5542+
if (useFile->getParentModule() == sourceDC->getParentModule())
5543+
return true;
5544+
auto *useSF = dyn_cast<SourceFile>(useFile);
5545+
return !useSF || useSF->isImportedAsSPI(VD);
5546+
}
55405547
return true;
55415548
}
5549+
}
55425550
llvm_unreachable("bad access level");
55435551
}
55445552

test/SPI/Inputs/spi_helper.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ public protocol PublicProto {
44
associatedtype Assoc
55
}
66

7+
public struct PublicType {
8+
public init() { }
9+
}
10+
711
public func publicFunc() { print("publicFunc") }
812

913
func internalFunc() {}
@@ -94,3 +98,6 @@ public enum PublicEnum {
9498
case publicCase
9599
@_spi(HelperSPI) case spiCase
96100
}
101+
102+
@_spi(HelperSPI) public func -(_ s1: PublicType, _ s2: PublicType) -> PublicType { s1 }
103+
@_spi(HelperSPI) public func +(_ s1: PublicType, _ s2: PublicType) -> PublicType { s1 }

test/SPI/public_client.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ otherApiFunc() // expected-error {{cannot find 'otherApiFunc' in scope}}
4040
public func publicUseOfSPI(param: SPIClass) -> SPIClass {} // expected-error 2{{cannot find type 'SPIClass' in scope}}
4141
public func publicUseOfSPI2() -> [SPIClass] {} // expected-error {{cannot find type 'SPIClass' in scope}}
4242

43+
public let o1 = PublicType()
44+
public let o2 = PublicType()
45+
4346
@inlinable
44-
func inlinable() -> SPIClass { // expected-error {{cannot find type 'SPIClass' in scope}}
47+
public func inlinable() -> SPIClass { // expected-error {{cannot find type 'SPIClass' in scope}}
4548
spiFunc() // expected-error {{cannot find 'spiFunc' in scope}}
4649
_ = SPIClass() // expected-error {{cannot find 'SPIClass' in scope}}
50+
let _ = o1 - o2 // expected-error {{binary operator '-' cannot be applied to two 'PublicType' operands}}
4751
}
52+
53+
let _ = o1 - o2 // expected-error {{binary operator '-' cannot be applied to two 'PublicType' operands}}

test/SPI/spi_client.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,16 @@ public func inlinable1() -> SPIClass { // expected-error {{class 'SPIClass' cann
6161
_ = [SPIClass]() // expected-error {{class 'SPIClass' cannot be used in an '@inlinable' function because it is an SPI imported from 'SPIHelper'}}
6262
}
6363

64+
public let o1 = PublicType()
65+
public let o2 = PublicType()
66+
6467
@_spi(S)
6568
@inlinable
6669
public func inlinable2() -> SPIClass {
6770
spiFunc()
6871
_ = SPIClass()
6972
_ = [SPIClass]()
73+
let _ = o1 - o2
7074
}
75+
76+
let _ = o1 - o2

0 commit comments

Comments
 (0)