@@ -1454,47 +1454,40 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
14541454 }
14551455};
14561456
1457+ // / Returns the kind of origin, implementation-only import or SPI declaration,
1458+ // / that restricts exporting \p decl from the given file and context.
1459+ // /
1460+ // / Local variant to swift::getDisallowedOriginKind for downgrade to warnings.
1461+ DisallowedOriginKind
1462+ getDisallowedOriginKind (const Decl *decl,
1463+ const SourceFile &userSF,
1464+ const Decl *userContext,
1465+ DowngradeToWarning &downgradeToWarning) {
1466+ downgradeToWarning = DowngradeToWarning::No;
1467+ ModuleDecl *M = decl->getModuleContext ();
1468+ if (userSF.isImportedImplementationOnly (M)) {
1469+ // Temporarily downgrade implementation-only exportability in SPI to
1470+ // a warning.
1471+ if (userContext->isSPI ())
1472+ downgradeToWarning = DowngradeToWarning::Yes;
1473+
1474+ // Implementation-only imported, cannot be reexported.
1475+ return DisallowedOriginKind::ImplementationOnly;
1476+ } else if (decl->isSPI () && !userContext->isSPI ()) {
1477+ // SPI can only be exported in SPI.
1478+ return userContext->getModuleContext () == M ?
1479+ DisallowedOriginKind::SPILocal :
1480+ DisallowedOriginKind::SPIImported;
1481+ }
1482+
1483+ return DisallowedOriginKind::None;
1484+ };
1485+
14571486// Diagnose public APIs exposing types that are either imported as
14581487// implementation-only or declared as SPI.
14591488class ExportabilityChecker : public DeclVisitor <ExportabilityChecker> {
14601489 class Diagnoser ;
14611490
1462- // Problematic origin of an exported type.
1463- //
1464- // This enum must be kept in sync with
1465- // diag::decl_from_hidden_module and
1466- // diag::conformance_from_implementation_only_module.
1467- enum class DisallowedOriginKind : uint8_t {
1468- ImplementationOnly,
1469- SPIImported,
1470- SPILocal,
1471- None
1472- };
1473-
1474- // If there's an exportability problem with \p typeDecl, get its origin kind.
1475- static DisallowedOriginKind getDisallowedOriginKind (
1476- const TypeDecl *typeDecl, const SourceFile &SF, const Decl *context,
1477- DowngradeToWarning &downgradeToWarning) {
1478- downgradeToWarning = DowngradeToWarning::No;
1479- ModuleDecl *M = typeDecl->getModuleContext ();
1480- if (SF.isImportedImplementationOnly (M)) {
1481- // Temporarily downgrade implementation-only exportability in SPI to
1482- // a warning.
1483- if (context->isSPI ())
1484- downgradeToWarning = DowngradeToWarning::Yes;
1485-
1486- // Implementation-only imported, cannot be reexported.
1487- return DisallowedOriginKind::ImplementationOnly;
1488- } else if (typeDecl->isSPI () && !context->isSPI ()) {
1489- // SPI can only be exported in SPI.
1490- return context->getModuleContext () == M ?
1491- DisallowedOriginKind::SPILocal :
1492- DisallowedOriginKind::SPIImported;
1493- }
1494-
1495- return DisallowedOriginKind::None;
1496- };
1497-
14981491 void checkTypeImpl (
14991492 Type type, const TypeRepr *typeRepr, const SourceFile &SF,
15001493 const Decl *context,
@@ -1560,10 +1553,12 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
15601553
15611554 const RootProtocolConformance *rootConf =
15621555 concreteConf->getRootConformance ();
1563- ModuleDecl *M = rootConf->getDeclContext ()->getParentModule ();
1564- if (!SF.isImportedImplementationOnly (M))
1556+ auto originKind = getDisallowedOriginKind (
1557+ rootConf->getDeclContext ()->getAsDecl (),
1558+ SF, context);
1559+ if (originKind == DisallowedOriginKind::None)
15651560 continue ;
1566- diagnoser.diagnoseConformance (rootConf);
1561+ diagnoser.diagnoseConformance (rootConf, originKind );
15671562 }
15681563 }
15691564
@@ -1674,12 +1669,14 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
16741669 highlightOffendingType (diag, complainRepr);
16751670 }
16761671
1677- void diagnoseConformance (const ProtocolConformance *offendingConformance) const {
1672+ void diagnoseConformance (const ProtocolConformance *offendingConformance,
1673+ DisallowedOriginKind originKind) const {
16781674 ModuleDecl *M = offendingConformance->getDeclContext ()->getParentModule ();
16791675 D->diagnose (diag::conformance_from_implementation_only_module,
16801676 offendingConformance->getType (),
16811677 offendingConformance->getProtocol ()->getName (),
1682- static_cast <unsigned >(reason), M->getName ());
1678+ static_cast <unsigned >(reason), M->getName (),
1679+ static_cast <unsigned >(originKind));
16831680 }
16841681
16851682 void diagnoseClangFunctionType (Type fnType, const clang::Type *type) const {
@@ -2067,6 +2064,13 @@ static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) {
20672064 ED, ED, desiredAccessScope, userSpecifiedAccess);
20682065}
20692066
2067+ DisallowedOriginKind swift::getDisallowedOriginKind (const Decl *decl,
2068+ const SourceFile &userSF,
2069+ const Decl *declContext) {
2070+ auto downgradeToWarning = DowngradeToWarning::No;
2071+ return getDisallowedOriginKind (decl, userSF, declContext, downgradeToWarning);
2072+ }
2073+
20702074void swift::checkAccessControl (Decl *D) {
20712075 if (isa<ValueDecl>(D) || isa<PatternBindingDecl>(D)) {
20722076 AccessControlChecker ().visit (D);
0 commit comments