Skip to content

Commit 94522ff

Browse files
committed
[Sema] InitAccessors: Implement validation of @storageRestrictions attribute
1 parent 9992af5 commit 94522ff

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

include/swift/AST/Attr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,9 @@ class StorageRestrictionsAttr final
16461646
return {getTrailingObjects<Identifier>() + NumInitializes, NumAccesses};
16471647
}
16481648

1649+
ArrayRef<VarDecl *> getInitializesProperties(AccessorDecl *attachedTo) const;
1650+
ArrayRef<VarDecl *> getAccessesProperties(AccessorDecl *attachedTo) const;
1651+
16491652
static StorageRestrictionsAttr *create(ASTContext &ctx, SourceLoc atLoc,
16501653
SourceRange range,
16511654
ArrayRef<Identifier> initializes,

lib/AST/Attr.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,6 +2608,26 @@ AccessesAttr::getPropertyDecls(AccessorDecl *attachedTo) const {
26082608
{});
26092609
}
26102610

2611+
ArrayRef<VarDecl *> StorageRestrictionsAttr::getInitializesProperties(
2612+
AccessorDecl *attachedTo) const {
2613+
auto &ctx = attachedTo->getASTContext();
2614+
return evaluateOrDefault(ctx.evaluator,
2615+
InitAccessorReferencedVariablesRequest{
2616+
const_cast<StorageRestrictionsAttr *>(this),
2617+
attachedTo, getInitializesNames()},
2618+
{});
2619+
}
2620+
2621+
ArrayRef<VarDecl *>
2622+
StorageRestrictionsAttr::getAccessesProperties(AccessorDecl *attachedTo) const {
2623+
auto &ctx = attachedTo->getASTContext();
2624+
return evaluateOrDefault(ctx.evaluator,
2625+
InitAccessorReferencedVariablesRequest{
2626+
const_cast<StorageRestrictionsAttr *>(this),
2627+
attachedTo, getAccessesNames()},
2628+
{});
2629+
}
2630+
26112631
void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {
26122632
if (attr)
26132633
attr->print(out);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3591,6 +3591,21 @@ void AttributeChecker::visitAccessesAttr(AccessesAttr *attr) {
35913591
}
35923592

35933593
void AttributeChecker::visitStorageRestrictionsAttr(StorageRestrictionsAttr *attr) {
3594+
auto *accessor = dyn_cast<AccessorDecl>(D);
3595+
if (!accessor || accessor->getAccessorKind() != AccessorKind::Init) {
3596+
diagnose(attr->getLocation(),
3597+
diag::storage_restrictions_attribute_not_on_init_accessor);
3598+
return;
3599+
}
3600+
3601+
auto initializesProperties = attr->getInitializesProperties(accessor);
3602+
for (auto *property : attr->getAccessesProperties(accessor)) {
3603+
if (llvm::is_contained(initializesProperties, property)) {
3604+
diagnose(attr->getLocation(),
3605+
diag::init_accessor_property_both_init_and_accessed,
3606+
property->getName());
3607+
}
3608+
}
35943609
}
35953610

35963611
void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {

test/decl/var/init_accessors.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ do {
524524

525525
func test_invalid_storage_restrictions() {
526526
struct Test {
527+
var _a: Int
528+
var _b: Int
529+
527530
var a: Int {
528531
@storageRestrictions()
529532
// expected-error@-1 {{missing label in @storageRestrictions attribute}}
@@ -553,5 +556,17 @@ func test_invalid_storage_restrictions() {
553556
// expected-error@-1 {{unexpected label 'initialize' in @storageRestrictions attribute}}
554557
init {}
555558
}
559+
560+
var f: Int {
561+
@storageRestrictions(initializes: _a, accesses: _b, _a)
562+
// expected-error@-1 {{property '_a' cannot be both initialized and accessed}}
563+
init {}
564+
}
565+
566+
var g: Int {
567+
@storageRestrictions(initializes: _a)
568+
// expected-error@-1 {{@storageRestrictions attribute could only be used with init accessors}}
569+
get { 0 }
570+
}
556571
}
557572
}

0 commit comments

Comments
 (0)