Skip to content

Commit c44284d

Browse files
committed
Diagnose invalid @_hasStorage attributes
A bug in `@objc @implementation` is causing incorrect `@_hasStorage` attributes to be printed into module interfaces. As an initial step towards fixing this, diagnose bad `@_hasStorage` attributes and treat them as computed properties so that these malformed interfaces don’t cause compiler crashes. Partially fixes rdar://144811653.
1 parent 51face1 commit c44284d

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
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,

lib/Sema/TypeCheckStorage.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3843,10 +3843,20 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
38433843
: StorageIsMutable);
38443844
}
38453845

3846-
if (auto *var = dyn_cast<VarDecl>(storage)) {
3846+
// If we're in an @implementation extension, we care about the semantics of
3847+
// the decl it implements.
3848+
auto *DC = storage->getDeclContext()->getImplementedObjCContext();
3849+
3850+
if (auto attr = storage->getParsedAttrs().getAttribute<HasStorageAttr>()) {
3851+
// If we see `@_hasStorage` in a context with no stored properties, diagnose
3852+
// and ignore it.
3853+
if (isa<ExtensionDecl, EnumDecl, ProtocolDecl>(DC)) {
3854+
storage->diagnose(diag::attr_invalid_in_context, attr,
3855+
DC->getAsDecl()->getDescriptiveKind());
3856+
38473857
// Allow the @_hasStorage attribute to override all the accessors we parsed
38483858
// when making the final classification.
3849-
if (var->getParsedAttrs().hasAttribute<HasStorageAttr>()) {
3859+
} else if (auto *var = dyn_cast<VarDecl>(storage)) {
38503860
// The SIL rules for @_hasStorage are slightly different from the non-SIL
38513861
// rules. In SIL mode, @_hasStorage marks that the type is simply stored,
38523862
// and the only thing that determines mutability is the existence of the
@@ -3941,7 +3951,6 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
39413951
bool hasMutableAddress = storage->getParsedAccessor(AccessorKind::MutableAddress);
39423952
bool hasInit = storage->getParsedAccessor(AccessorKind::Init);
39433953

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

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)