mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
sema: diagnose importation from disallowed modules
This commit is contained in:
@@ -984,6 +984,10 @@ WARNING(module_not_compiled_with_library_evolution,none,
|
|||||||
"using it means binary compatibility for %1 can't be guaranteed",
|
"using it means binary compatibility for %1 can't be guaranteed",
|
||||||
(Identifier, Identifier))
|
(Identifier, Identifier))
|
||||||
|
|
||||||
|
ERROR(module_allowable_client_violation,none,
|
||||||
|
"module %0 doesn't allow importation from module %1",
|
||||||
|
(Identifier, Identifier))
|
||||||
|
|
||||||
REMARK(cross_import_added,none,
|
REMARK(cross_import_added,none,
|
||||||
"import of %0 and %1 triggered a cross-import of %2",
|
"import of %0 and %1 triggered a cross-import of %2",
|
||||||
(Identifier, Identifier, Identifier))
|
(Identifier, Identifier, Identifier))
|
||||||
|
|||||||
@@ -424,6 +424,7 @@ public:
|
|||||||
ArrayRef<Identifier> getAllowableClientNames() const {
|
ArrayRef<Identifier> getAllowableClientNames() const {
|
||||||
return allowableClientNames;
|
return allowableClientNames;
|
||||||
}
|
}
|
||||||
|
bool allowImportedBy(ModuleDecl *importer) const;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// An array of module names that are allowed to import this one.
|
/// An array of module names that are allowed to import this one.
|
||||||
|
|||||||
@@ -1923,6 +1923,18 @@ Identifier ModuleDecl::getRealName() const {
|
|||||||
return getASTContext().getRealModuleName(getName());
|
return getASTContext().getRealModuleName(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModuleDecl::allowImportedBy(ModuleDecl *importer) const {
|
||||||
|
if (allowableClientNames.empty())
|
||||||
|
return true;
|
||||||
|
for (auto id: allowableClientNames) {
|
||||||
|
if (importer->getRealName() == id)
|
||||||
|
return true;
|
||||||
|
if (importer->getABIName() == id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Identifier ModuleDecl::getABIName() const {
|
Identifier ModuleDecl::getABIName() const {
|
||||||
if (!ModuleABIName.empty())
|
if (!ModuleABIName.empty())
|
||||||
return ModuleABIName;
|
return ModuleABIName;
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ private:
|
|||||||
void validateTestable(ModuleDecl *topLevelModule);
|
void validateTestable(ModuleDecl *topLevelModule);
|
||||||
void validateResilience(NullablePtr<ModuleDecl> topLevelModule,
|
void validateResilience(NullablePtr<ModuleDecl> topLevelModule,
|
||||||
SourceFile &SF);
|
SourceFile &SF);
|
||||||
|
void validateAllowableClient(ModuleDecl *topLevelModule, SourceFile &SF);
|
||||||
|
|
||||||
/// Diagnoses an inability to import \p modulePath in this situation and, if
|
/// Diagnoses an inability to import \p modulePath in this situation and, if
|
||||||
/// \p attrs is provided and has an \p attrKind, invalidates the attribute and
|
/// \p attrs is provided and has an \p attrKind, invalidates the attribute and
|
||||||
@@ -621,6 +622,7 @@ void UnboundImport::validateOptions(NullablePtr<ModuleDecl> topLevelModule,
|
|||||||
// changing behavior, but it smells funny.
|
// changing behavior, but it smells funny.
|
||||||
validateTestable(top);
|
validateTestable(top);
|
||||||
validatePrivate(top);
|
validatePrivate(top);
|
||||||
|
validateAllowableClient(top, SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateResilience(topLevelModule, SF);
|
validateResilience(topLevelModule, SF);
|
||||||
@@ -712,6 +714,19 @@ void UnboundImport::validateTestable(ModuleDecl *topLevelModule) {
|
|||||||
diagnoseInvalidAttr(DAK_Testable, ctx.Diags, diag::module_not_testable);
|
diagnoseInvalidAttr(DAK_Testable, ctx.Diags, diag::module_not_testable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnboundImport::validateAllowableClient(ModuleDecl *importee,
|
||||||
|
SourceFile &SF) {
|
||||||
|
assert(importee);
|
||||||
|
auto *importer = SF.getParentModule();
|
||||||
|
if (!importee->allowImportedBy(importer)) {
|
||||||
|
ASTContext &ctx = SF.getASTContext();
|
||||||
|
ctx.Diags.diagnose(import.module.getModulePath().front().Loc,
|
||||||
|
diag::module_allowable_client_violation,
|
||||||
|
importee->getName(),
|
||||||
|
importer->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
|
void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
|
||||||
SourceFile &SF) {
|
SourceFile &SF) {
|
||||||
if (import.options.contains(ImportFlags::ImplementationOnly))
|
if (import.options.contains(ImportFlags::ImplementationOnly))
|
||||||
|
|||||||
22
test/Sema/allowable-client-import.swift
Normal file
22
test/Sema/allowable-client-import.swift
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/binary)
|
||||||
|
// RUN: %empty-directory(%t/textual)
|
||||||
|
// RUN: %empty-directory(%t/module-cache)
|
||||||
|
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/binary/Foo.swiftmodule -parse-as-library %s -enable-library-evolution -allowable-client Bar -allowable-client FooBar -module-name Foo -DFOO -emit-module-interface-path %t/textual/Foo.swiftinterface
|
||||||
|
|
||||||
|
// RUN: %target-swift-frontend -typecheck %s -I %t/binary -module-name Bar
|
||||||
|
// RUN: %target-swift-frontend -typecheck %s -I %t/binary -module-name FooBar
|
||||||
|
// RUN: %target-typecheck-verify-swift -I %t/binary -module-name Blocked
|
||||||
|
// RUN: %target-typecheck-verify-swift -I %t/textual -module-name Blocked -module-cache-path %t/module-cache
|
||||||
|
|
||||||
|
#if FOO
|
||||||
|
|
||||||
|
public func foo() {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import Foo // expected-error {{module 'Foo' doesn't allow importation from module 'Blocked'}}
|
||||||
|
|
||||||
|
func bar() { foo() }
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user