@@ -1546,13 +1546,21 @@ swift::getDisallowedOriginKind(const Decl *decl,
15461546 // Implementation-only imported, cannot be reexported.
15471547 return DisallowedOriginKind::ImplementationOnly;
15481548 } else if ((decl->isSPI () || decl->isAvailableAsSPI ()) && !where.isSPI ()) {
1549- // Allowing unavailable context to use @_spi_available decls.
1550- // Decls with @_spi_available aren't hidden entirely from public interfaces,
1551- // thus public interfaces may still refer them. Be forgiving here so public
1552- // interfaces can compile.
1553- if (where.getUnavailablePlatformKind ().hasValue () &&
1554- decl->isAvailableAsSPI () && !decl->isSPI ()) {
1555- return DisallowedOriginKind::None;
1549+ if (decl->isAvailableAsSPI () && !decl->isSPI ()) {
1550+ // Allowing unavailable context to use @_spi_available decls.
1551+ // Decls with @_spi_available aren't hidden entirely from public interfaces,
1552+ // thus public interfaces may still refer them. Be forgiving here so public
1553+ // interfaces can compile.
1554+ if (where.getUnavailablePlatformKind ().hasValue ())
1555+ return DisallowedOriginKind::None;
1556+ // We should only diagnose SPI_AVAILABLE usage when the library level is API.
1557+ // Using SPI_AVAILABLE symbols in private frameworks or executable targets
1558+ // should be allowed.
1559+ if (auto *mod = where.getDeclContext ()->getParentModule ()) {
1560+ if (mod->getLibraryLevel () != LibraryLevel::API) {
1561+ return DisallowedOriginKind::None;
1562+ }
1563+ }
15561564 }
15571565 // SPI can only be exported in SPI.
15581566 return where.getDeclContext ()->getParentModule () == M ?
0 commit comments