Skip to content

Commit ce8cc17

Browse files
committed
Ignore bad @_hasStorage in module interfaces
An objcImpl bug previously caused `@_hasStorage` to be emitted inside some extensions in module interfaces. An earlier commit in this PR created an error for this, but for backwards compatibility, it would actually be better to simply ignore the attribute in module interfaces. Modify TypeCheckStorage to emit a warning, not an error, in this situation. Additionally, modify the module interface loader to show warnings when you verify a module interface, but not for other module interface uses (like compiling or importing one). The assumption here is that if you’re verifying a module interface, you’re either the author of the module that created it or you’re investigating a problem with it, and in either case you’d like to be told about minor defects in case they’re related. Fixes rdar://144811653 thoroughly.
1 parent 29a2d32 commit ce8cc17

File tree

4 files changed

+20
-11
lines changed

4 files changed

+20
-11
lines changed

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,8 @@ struct InterfaceSubContextDelegateImpl : InterfaceSubContextDelegate {
672672
return InterfaceSubContextDelegateImpl::diagnose(interfacePath, diagnosticLoc, SM, Diags, ID, std::move(Args)...);
673673
}
674674
void
675-
inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
675+
inheritOptionsForBuildingInterface(FrontendOptions::ActionType requestedAction,
676+
const SearchPathOptions &SearchPathOpts,
676677
const LangOptions &LangOpts,
677678
const ClangImporterOptions &clangImporterOpts,
678679
const CASOptions &casOpts,

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,7 @@ void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames(
16541654
}
16551655

16561656
void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
1657+
FrontendOptions::ActionType requestedAction,
16571658
const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts,
16581659
const ClangImporterOptions &clangImporterOpts, const CASOptions &casOpts,
16591660
bool suppressRemarks, RequireOSSAModules_t RequireOSSAModules) {
@@ -1741,9 +1742,12 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
17411742
}
17421743

17431744
// Inhibit warnings from the genericSubInvocation since we are assuming the user
1744-
// is not in a position to address them.
1745-
genericSubInvocation.getDiagnosticOptions().SuppressWarnings = true;
1746-
GenericArgs.push_back("-suppress-warnings");
1745+
// is not in a position to address them. (Unless we're verifying, in which
1746+
// case they might.)
1747+
if (requestedAction != FrontendOptions::ActionType::Typecheck) {
1748+
genericSubInvocation.getDiagnosticOptions().SuppressWarnings = true;
1749+
GenericArgs.push_back("-suppress-warnings");
1750+
}
17471751
// Inherit the parent invocation's setting on whether to suppress remarks
17481752
if (suppressRemarks) {
17491753
genericSubInvocation.getDiagnosticOptions().SuppressRemarks = true;
@@ -1871,8 +1875,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
18711875
RequireOSSAModules_t requireOSSAModules)
18721876
: SM(SM), Diags(Diags), ArgSaver(Allocator) {
18731877
genericSubInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
1874-
inheritOptionsForBuildingInterface(searchPathOpts, langOpts,
1875-
clangImporterOpts, casOpts,
1878+
inheritOptionsForBuildingInterface(LoaderOpts.requestedAction, searchPathOpts,
1879+
langOpts, clangImporterOpts, casOpts,
18761880
Diags->getSuppressRemarks(),
18771881
requireOSSAModules);
18781882
// Configure front-end input.

lib/Sema/TypeCheckStorage.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3748,8 +3748,12 @@ bool HasStorageRequest::evaluate(Evaluator &evaluator,
37483748
return false;
37493749

37503750
// @_hasStorage implies that it... has storage.
3751-
if (var->getAttrs().hasAttribute<HasStorageAttr>())
3752-
return true;
3751+
if (var->getAttrs().hasAttribute<HasStorageAttr>()) {
3752+
// Except in contexts where it would be invalid. This is diagnosed in
3753+
// StorageImplInfoRequest.
3754+
return !isa<ProtocolDecl, ExtensionDecl, EnumDecl>(
3755+
storage->getDeclContext()->getImplementedObjCContext());
3756+
}
37533757

37543758
// Protocol requirements never have storage.
37553759
if (isa<ProtocolDecl>(storage->getDeclContext()))
@@ -3852,7 +3856,8 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
38523856
// and ignore it.
38533857
if (isa<ExtensionDecl, EnumDecl, ProtocolDecl>(DC)) {
38543858
storage->diagnose(diag::attr_invalid_in_context, attr,
3855-
DC->getAsDecl()->getDescriptiveKind());
3859+
DC->getAsDecl()->getDescriptiveKind())
3860+
.warnInSwiftInterface(storage->getDeclContext());
38563861

38573862
// Allow the @_hasStorage attribute to override all the accessors we parsed
38583863
// when making the final classification.
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// swift-interface-format-version: 1.0
22
// swift-module-flags:
3-
// expected-error@-2 {{failed to verify module interface of 'Test' due to the errors above}}
43

54
// RUN: %target-swift-typecheck-module-from-interface(%s) -module-name Test -verify -verify-ignore-unknown
65
// REQUIRES: OS=macosx
76

87
extension Array {
9-
@_hasStorage public var foo: Int { get set } // expected-error {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
8+
@_hasStorage public var foo: Int { get set } // expected-warning {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
109
}

0 commit comments

Comments
 (0)