Skip to content

Commit 65dc578

Browse files
authored
Merge pull request #80360 from beccadax/rdar144811653
2 parents 50e4cc7 + ce8cc17 commit 65dc578

File tree

9 files changed

+56
-14
lines changed

9 files changed

+56
-14
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,6 +2216,9 @@ ERROR(invalid_decl_attribute,none,
22162216
ERROR(attr_invalid_on_decl_kind,none,
22172217
"'%0' attribute cannot be applied to %1 declarations",
22182218
(DeclAttribute, DescriptiveDeclKind))
2219+
ERROR(attr_invalid_in_context,none,
2220+
"'%0' attribute cannot be applied to declaration in %1",
2221+
(DeclAttribute, DescriptiveDeclKind))
22192222
ERROR(invalid_decl_modifier,none,
22202223
"%0 modifier cannot be applied to this declaration", (DeclAttribute))
22212224
ERROR(attribute_does_not_apply_to_type,none,

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/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,8 +1332,8 @@ void PrintAST::printAttributes(const Decl *D) {
13321332

13331333
if (!Options.PrintForSIL) {
13341334
// Don't print @_hasStorage if the value is simply stored, or the
1335-
// decl is resilient.
1336-
if (vd->isResilient() ||
1335+
// decl is resilient or in an `@objc @implementation` extension.
1336+
if (vd->isResilient() || isInObjCImpl(vd) ||
13371337
(vd->getImplInfo().isSimpleStored() &&
13381338
!hasLessAccessibleSetter(vd)))
13391339
Options.ExcludeAttrList.push_back(DeclAttrKind::HasStorage);

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: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3752,8 +3752,12 @@ bool HasStorageRequest::evaluate(Evaluator &evaluator,
37523752
return false;
37533753

37543754
// @_hasStorage implies that it... has storage.
3755-
if (var->getAttrs().hasAttribute<HasStorageAttr>())
3756-
return true;
3755+
if (var->getAttrs().hasAttribute<HasStorageAttr>()) {
3756+
// Except in contexts where it would be invalid. This is diagnosed in
3757+
// StorageImplInfoRequest.
3758+
return !isa<ProtocolDecl, ExtensionDecl, EnumDecl>(
3759+
storage->getDeclContext()->getImplementedObjCContext());
3760+
}
37573761

37583762
// Protocol requirements never have storage.
37593763
if (isa<ProtocolDecl>(storage->getDeclContext()))
@@ -3847,10 +3851,21 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
38473851
: StorageIsMutable);
38483852
}
38493853

3850-
if (auto *var = dyn_cast<VarDecl>(storage)) {
3854+
// If we're in an @implementation extension, we care about the semantics of
3855+
// the decl it implements.
3856+
auto *DC = storage->getDeclContext()->getImplementedObjCContext();
3857+
3858+
if (auto attr = storage->getParsedAttrs().getAttribute<HasStorageAttr>()) {
3859+
// If we see `@_hasStorage` in a context with no stored properties, diagnose
3860+
// and ignore it.
3861+
if (isa<ExtensionDecl, EnumDecl, ProtocolDecl>(DC)) {
3862+
storage->diagnose(diag::attr_invalid_in_context, attr,
3863+
DC->getAsDecl()->getDescriptiveKind())
3864+
.warnInSwiftInterface(storage->getDeclContext());
3865+
38513866
// Allow the @_hasStorage attribute to override all the accessors we parsed
38523867
// when making the final classification.
3853-
if (var->getParsedAttrs().hasAttribute<HasStorageAttr>()) {
3868+
} else if (auto *var = dyn_cast<VarDecl>(storage)) {
38543869
// The SIL rules for @_hasStorage are slightly different from the non-SIL
38553870
// rules. In SIL mode, @_hasStorage marks that the type is simply stored,
38563871
// and the only thing that determines mutability is the existence of the
@@ -3945,7 +3960,6 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
39453960
bool hasMutableAddress = storage->getParsedAccessor(AccessorKind::MutableAddress);
39463961
bool hasInit = storage->getParsedAccessor(AccessorKind::Init);
39473962

3948-
auto *DC = storage->getDeclContext();
39493963
// 'get', 'read', and a non-mutable addressor are all exclusive.
39503964
ReadImplKind readImpl;
39513965
if (storage->getParsedAccessor(AccessorKind::Get)) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags:
3+
4+
// RUN: %target-swift-typecheck-module-from-interface(%s) -module-name Test -verify -verify-ignore-unknown
5+
// REQUIRES: OS=macosx
6+
7+
extension Array {
8+
@_hasStorage public var foo: Int { get set } // expected-warning {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
9+
}

test/ModuleInterface/objc_implementation.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import Foundation
2121
// @objc should be omitted on extensions
2222
// NEGATIVE-NOT: @objc{{.*}} extension
2323

24+
// Stored properties in objcImpl extensions shouldn't have @_hasStorage
25+
// NEGATIVE-NOT: @_hasStorage
26+
2427
//
2528
// @_objcImplementation class
2629
//
@@ -42,6 +45,11 @@ import Foundation
4245
// CHECK-DAG: final public var implProperty2: ObjectiveC.NSObject? { get set }
4346
public final var implProperty2: NSObject?
4447

48+
// CHECK-DAG: final public var implProperty3: ObjectiveC.NSObject? {
49+
public final var implProperty3: NSObject? {
50+
didSet { }
51+
}
52+
4553
// CHECK-NOT: func mainMethod
4654
@objc public func mainMethod(_: Int32) { print(implProperty) }
4755

test/SILOptimizer/keypath-folding-crash.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import SwiftShims
3030
import Builtin
3131
import CModule
3232

33-
extension ObjClass {
33+
@objc @implementation extension ObjClass {
3434
@objc @_hasStorage dynamic var o: NSObject { get set }
3535
}
3636

test/attr/attributes.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ class ExclusivityAttrClass {
308308
class HasStorage {
309309
@_hasStorage var x : Int = 42 // ok, _hasStorage is allowed here
310310
}
311+
extension HasStorage {
312+
@_hasStorage var y : Int { 24 } // expected-error {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
313+
}
311314

312315
@_show_in_interface protocol _underscored {}
313316
@_show_in_interface class _notapplicable {} // expected-error {{may only be used on 'protocol' declarations}}

0 commit comments

Comments
 (0)