Skip to content

Commit fe257d5

Browse files
committed
[semantics] Add support for annotating VarDecls with @_semantics.
This is just for prototyping purposes. I also had to loosen a small restriction where semantics functions were not allowed in local contexts. There really is no reason to enforce this and I think since it came in the first commit that introduced semanitcs it was most likely NadavR just being conservative and careful.
1 parent 412a0f1 commit fe257d5

File tree

4 files changed

+48
-11
lines changed

4 files changed

+48
-11
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ DECL_ATTR(inline, Inline,
203203
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
204204
20)
205205
DECL_ATTR(_semantics, Semantics,
206-
OnAbstractFunction | OnSubscript | OnNominalType |
206+
OnAbstractFunction | OnSubscript | OnNominalType | OnVar |
207207
AllowMultipleAttributes | UserInaccessible |
208208
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
209209
21)

include/swift/AST/Decl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5179,6 +5179,20 @@ class VarDecl : public AbstractStorageDecl {
51795179
/// backing property will be treated as the member-initialized property.
51805180
bool isMemberwiseInitialized(bool preferDeclaredProperties) const;
51815181

5182+
/// Return the range of semantics attributes attached to this VarDecl.
5183+
auto getSemanticsAttrs() const
5184+
-> decltype(getAttrs().getAttributes<SemanticsAttr>()) {
5185+
return getAttrs().getAttributes<SemanticsAttr>();
5186+
}
5187+
5188+
/// Returns true if this VarDelc has the string \p attrValue as a semantics
5189+
/// attribute.
5190+
bool hasSemanticsAttr(StringRef attrValue) const {
5191+
return llvm::any_of(getSemanticsAttrs(), [&](const SemanticsAttr *attr) {
5192+
return attrValue.equals(attr->Value);
5193+
});
5194+
}
5195+
51825196
// Implement isa/cast/dyncast/etc.
51835197
static bool classof(const Decl *D) {
51845198
return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param;

lib/Parse/ParseDecl.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,14 +1263,6 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
12631263
return false;
12641264
}
12651265

1266-
// Diagnose using @_semantics in a local scope. These don't
1267-
// actually work.
1268-
if (CurDeclContext->isLocalContext()) {
1269-
// Emit an error, but do not discard the attribute. This enables
1270-
// better recovery in the parser.
1271-
diagnose(Loc, diag::attr_only_at_non_local_scope, AttrName);
1272-
}
1273-
12741266
if (!DiscardAttribute)
12751267
Attributes.add(new (Context) SemanticsAttr(Value.getValue(), AtLoc,
12761268
AttrRange,

test/attr/attr_semantics.swift

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
func duplicatesemantics() {}
66

77
func func_with_nested_semantics_1() {
8-
@_semantics("exit") // expected-error {{attribute '_semantics' can only be used in a non-local scope}}
8+
@_semantics("exit")
99
func exit(_ code : UInt32) -> Void
1010
exit(0)
1111
}
@@ -15,7 +15,7 @@ func func_with_nested_semantics_1() {
1515
func somethingThatShouldParseFine() {}
1616

1717
func func_with_nested_semantics_2() {
18-
@_semantics("exit") // expected-error {{attribute '_semantics' can only be used in a non-local scope}}
18+
@_semantics("exit")
1919
func exit(_ code : UInt32) -> Void
2020
exit(0)
2121
}
@@ -32,3 +32,34 @@ enum EnumWithSemantics {}
3232
@_semantics("struct1")
3333
@_semantics("struct2")
3434
struct StructWithDuplicateSemantics {}
35+
36+
@_semantics("globalVar1")
37+
@_semantics("globalVar2")
38+
var globalVarWithSemantics : Int = 5
39+
40+
@_semantics("globalLet1")
41+
@_semantics("globalLet2")
42+
let globalLetWithSemantics : Int = 5
43+
44+
func varDeclLocalVars() {
45+
@_semantics("localVar1")
46+
@_semantics("localVar2")
47+
var localVarWithSemantics : Int = 5
48+
localVarWithSemantics = 6
49+
let _ = localVarWithSemantics
50+
51+
@_semantics("localLet1")
52+
@_semantics("localLet2")
53+
let localLetWithSemantics : Int = 5
54+
let _ = localLetWithSemantics
55+
}
56+
57+
struct IVarTest {
58+
@_semantics("localVar1")
59+
@_semantics("localVar2")
60+
var localVarWithSemantics : Int = 5
61+
62+
@_semantics("localLet1")
63+
@_semantics("localLet2")
64+
let localLetWithSemantics : Int = 5
65+
}

0 commit comments

Comments
 (0)