Skip to content

Commit f16caf6

Browse files
committed
[Sema] InitAccessors: Implement validation of @storageRestrictions attribute
(cherry picked from commit 94522ff)
1 parent 0ea93cc commit f16caf6

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
@@ -1623,6 +1623,9 @@ class StorageRestrictionsAttr final
16231623
return {getTrailingObjects<Identifier>() + NumInitializes, NumAccesses};
16241624
}
16251625

1626+
ArrayRef<VarDecl *> getInitializesProperties(AccessorDecl *attachedTo) const;
1627+
ArrayRef<VarDecl *> getAccessesProperties(AccessorDecl *attachedTo) const;
1628+
16261629
static StorageRestrictionsAttr *create(ASTContext &ctx, SourceLoc atLoc,
16271630
SourceRange range,
16281631
ArrayRef<Identifier> initializes,

lib/AST/Attr.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,26 @@ AccessesAttr::getPropertyDecls(AccessorDecl *attachedTo) const {
25962596
{});
25972597
}
25982598

2599+
ArrayRef<VarDecl *> StorageRestrictionsAttr::getInitializesProperties(
2600+
AccessorDecl *attachedTo) const {
2601+
auto &ctx = attachedTo->getASTContext();
2602+
return evaluateOrDefault(ctx.evaluator,
2603+
InitAccessorReferencedVariablesRequest{
2604+
const_cast<StorageRestrictionsAttr *>(this),
2605+
attachedTo, getInitializesNames()},
2606+
{});
2607+
}
2608+
2609+
ArrayRef<VarDecl *>
2610+
StorageRestrictionsAttr::getAccessesProperties(AccessorDecl *attachedTo) const {
2611+
auto &ctx = attachedTo->getASTContext();
2612+
return evaluateOrDefault(ctx.evaluator,
2613+
InitAccessorReferencedVariablesRequest{
2614+
const_cast<StorageRestrictionsAttr *>(this),
2615+
attachedTo, getAccessesNames()},
2616+
{});
2617+
}
2618+
25992619
void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {
26002620
if (attr)
26012621
attr->print(out);

lib/Sema/TypeCheckAttr.cpp

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

35553555
void AttributeChecker::visitStorageRestrictionsAttr(StorageRestrictionsAttr *attr) {
3556+
auto *accessor = dyn_cast<AccessorDecl>(D);
3557+
if (!accessor || accessor->getAccessorKind() != AccessorKind::Init) {
3558+
diagnose(attr->getLocation(),
3559+
diag::storage_restrictions_attribute_not_on_init_accessor);
3560+
return;
3561+
}
3562+
3563+
auto initializesProperties = attr->getInitializesProperties(accessor);
3564+
for (auto *property : attr->getAccessesProperties(accessor)) {
3565+
if (llvm::is_contained(initializesProperties, property)) {
3566+
diagnose(attr->getLocation(),
3567+
diag::init_accessor_property_both_init_and_accessed,
3568+
property->getName());
3569+
}
3570+
}
35563571
}
35573572

35583573
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)