mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -2216,6 +2216,9 @@ ERROR(invalid_decl_attribute,none,
|
||||
ERROR(attr_invalid_on_decl_kind,none,
|
||||
"'%0' attribute cannot be applied to %1 declarations",
|
||||
(DeclAttribute, DescriptiveDeclKind))
|
||||
ERROR(attr_invalid_in_context,none,
|
||||
"'%0' attribute cannot be applied to declaration in %1",
|
||||
(DeclAttribute, DescriptiveDeclKind))
|
||||
ERROR(invalid_decl_modifier,none,
|
||||
"%0 modifier cannot be applied to this declaration", (DeclAttribute))
|
||||
ERROR(attribute_does_not_apply_to_type,none,
|
||||
|
||||
@@ -3843,10 +3843,20 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
|
||||
: StorageIsMutable);
|
||||
}
|
||||
|
||||
if (auto *var = dyn_cast<VarDecl>(storage)) {
|
||||
// If we're in an @implementation extension, we care about the semantics of
|
||||
// the decl it implements.
|
||||
auto *DC = storage->getDeclContext()->getImplementedObjCContext();
|
||||
|
||||
if (auto attr = storage->getParsedAttrs().getAttribute<HasStorageAttr>()) {
|
||||
// If we see `@_hasStorage` in a context with no stored properties, diagnose
|
||||
// and ignore it.
|
||||
if (isa<ExtensionDecl, EnumDecl, ProtocolDecl>(DC)) {
|
||||
storage->diagnose(diag::attr_invalid_in_context, attr,
|
||||
DC->getAsDecl()->getDescriptiveKind());
|
||||
|
||||
// Allow the @_hasStorage attribute to override all the accessors we parsed
|
||||
// when making the final classification.
|
||||
if (var->getParsedAttrs().hasAttribute<HasStorageAttr>()) {
|
||||
} else if (auto *var = dyn_cast<VarDecl>(storage)) {
|
||||
// The SIL rules for @_hasStorage are slightly different from the non-SIL
|
||||
// rules. In SIL mode, @_hasStorage marks that the type is simply stored,
|
||||
// and the only thing that determines mutability is the existence of the
|
||||
@@ -3941,7 +3951,6 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
|
||||
bool hasMutableAddress = storage->getParsedAccessor(AccessorKind::MutableAddress);
|
||||
bool hasInit = storage->getParsedAccessor(AccessorKind::Init);
|
||||
|
||||
auto *DC = storage->getDeclContext();
|
||||
// 'get', 'read', and a non-mutable addressor are all exclusive.
|
||||
ReadImplKind readImpl;
|
||||
if (storage->getParsedAccessor(AccessorKind::Get)) {
|
||||
|
||||
10
test/ModuleInterface/has_storage_attr_bad.swiftinterface
Normal file
10
test/ModuleInterface/has_storage_attr_bad.swiftinterface
Normal file
@@ -0,0 +1,10 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-module-flags:
|
||||
// expected-error@-2 {{failed to verify module interface of 'Test' due to the errors above}}
|
||||
|
||||
// RUN: %target-swift-typecheck-module-from-interface(%s) -module-name Test -verify -verify-ignore-unknown
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
extension Array {
|
||||
@_hasStorage public var foo: Int { get set } // expected-error {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import SwiftShims
|
||||
import Builtin
|
||||
import CModule
|
||||
|
||||
extension ObjClass {
|
||||
@objc @implementation extension ObjClass {
|
||||
@objc @_hasStorage dynamic var o: NSObject { get set }
|
||||
}
|
||||
|
||||
|
||||
@@ -308,6 +308,9 @@ class ExclusivityAttrClass {
|
||||
class HasStorage {
|
||||
@_hasStorage var x : Int = 42 // ok, _hasStorage is allowed here
|
||||
}
|
||||
extension HasStorage {
|
||||
@_hasStorage var y : Int { 24 } // expected-error {{'@_hasStorage' attribute cannot be applied to declaration in extension}}
|
||||
}
|
||||
|
||||
@_show_in_interface protocol _underscored {}
|
||||
@_show_in_interface class _notapplicable {} // expected-error {{may only be used on 'protocol' declarations}}
|
||||
|
||||
Reference in New Issue
Block a user