Skip to content

Commit aa86538

Browse files
committed
[Sema] Warn on @_spi imports of modules built from their public interface
This warning should help understand missing SPI diagnostics when the compiler loads a public module when a private one is expected. rdar://71859081
1 parent b0eafee commit aa86538

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,10 @@ ERROR(spi_attribute_on_protocol_requirement,none,
17841784
ERROR(spi_attribute_on_frozen_stored_properties,none,
17851785
"stored property %0 cannot be declared '@_spi' in a '@frozen' struct",
17861786
(DeclName))
1787+
WARNING(spi_attribute_on_import_of_public_module,none,
1788+
"importation of %0 has an ineffective '@_spi' attribute; "
1789+
"it was built from the public interface at %1",
1790+
(DeclName, StringRef))
17871791

17881792
// Opaque return types
17891793
ERROR(opaque_type_invalid_constraint,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,21 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
10301030
}
10311031
}
10321032
}
1033+
1034+
if (auto ID = dyn_cast<ImportDecl>(D)) {
1035+
auto importedModule = ID->getModule();
1036+
if (importedModule) {
1037+
auto path = importedModule->getModuleFilename();
1038+
if (llvm::sys::path::extension(path) == ".swiftinterface" &&
1039+
!path.endswith(".private.swiftinterface")) {
1040+
// If the module was built from the public swiftinterface, it can't
1041+
// have any SPI.
1042+
diagnose(attr->getLocation(),
1043+
diag::spi_attribute_on_import_of_public_module,
1044+
importedModule->getName(), path);
1045+
}
1046+
}
1047+
}
10331048
}
10341049

10351050
static bool checkObjCDeclContext(Decl *D) {

test/SPI/experimental_spi_imports_type_check.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
// RUN: %target-typecheck-verify-swift -DCLIENT -I %t
1717
// RUN: %target-swift-frontend -typecheck %s -DCLIENT -DCLIENT_LOAD_CORE -I %t
1818

19-
/// Test with the public swiftinterface file, the SPI is unknown.
20-
// RUN: rm %t/LibPublic.private.swiftinterface
21-
// RUN: %target-typecheck-verify-swift -DCLIENT -I %t
22-
// RUN: %target-typecheck-verify-swift -DCLIENT -DCLIENT_LOAD_CORE -I %t
23-
2419
#if LIB_CORE
2520

2621
public struct CoreStruct {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// Test the warning on an SPI import of the public interface of a module.
2+
3+
// RUN: %empty-directory(%t)
4+
5+
/// Compile the SPI lib.
6+
// RUN: %target-swift-frontend -enable-experimental-prespecialization -emit-module %S/Inputs/spi_helper.swift -module-name SPIHelper -emit-module-path %t/SPIHelper.swiftmodule -emit-module-interface-path %t/SPIHelper.swiftinterface -emit-private-module-interface-path %t/SPIHelper.private.swiftinterface -enable-library-evolution -swift-version 5 -parse-as-library
7+
8+
/// Reading from swiftmodule, no warning.
9+
// RUN: %target-swift-frontend -typecheck %s -I %t
10+
11+
/// Reading from .private.swiftinterface, no warning.
12+
// RUN: rm %t/SPIHelper.swiftmodule
13+
// RUN: %target-swift-frontend -typecheck %s -I %t
14+
15+
/// Reading from the public .swiftinterface should produce the warning.
16+
// RUN: rm %t/SPIHelper.private.swiftinterface
17+
// RUN: %target-typecheck-verify-swift -I %t
18+
19+
@_spi(SPIHelper) import SPIHelper // expected-warning {{importation of 'SPIHelper' has an ineffective '@_spi' attribute; it was built from the public interface at}}

0 commit comments

Comments
 (0)