Skip to content

Commit 777b0e9

Browse files
committed
Allow attributes @_used and @_section on static variables and member functions
- Drop the current requirement that these attributes can only apply to top-level declarations - Diagnose if they are used in local contexts - Diagnose if they are used in generic contexts - Add tests
1 parent bfb95f3 commit 777b0e9

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,8 @@ ERROR(alignment_must_be_positive_integer,none,
15431543

15441544
ERROR(attr_only_at_non_local_scope, none,
15451545
"attribute '%0' can only be used in a non-local scope", (StringRef))
1546+
ERROR(attr_only_at_non_generic_scope, none,
1547+
"attribute '%0' cannot be used in a generic context", (StringRef))
15461548

15471549
// Access control
15481550
ERROR(attr_access_expected_set,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,10 +2077,14 @@ void AttributeChecker::visitUsedAttr(UsedAttr *attr) {
20772077
diagnoseAndRemoveAttr(attr, diag::section_linkage_markers_disabled);
20782078
return;
20792079
}
2080-
2081-
// Only top-level func/var decls are currently supported.
2082-
if (D->getDeclContext()->isTypeContext())
2083-
diagnose(attr->getLocation(), diag::used_not_at_top_level);
2080+
2081+
if (D->getDeclContext()->isLocalContext())
2082+
diagnose(attr->getLocation(), diag::attr_only_at_non_local_scope,
2083+
attr->getAttrName());
2084+
2085+
if (D->getDeclContext()->isGenericContext())
2086+
diagnose(attr->getLocation(), diag::attr_only_at_non_generic_scope,
2087+
attr->getAttrName());
20842088
}
20852089

20862090
void AttributeChecker::visitSectionAttr(SectionAttr *attr) {
@@ -2089,13 +2093,13 @@ void AttributeChecker::visitSectionAttr(SectionAttr *attr) {
20892093
return;
20902094
}
20912095

2092-
// Only top-level func/var decls are currently supported.
2093-
if (D->getDeclContext()->isTypeContext())
2094-
diagnose(attr->getLocation(), diag::section_not_at_top_level);
2095-
20962096
// The name must not be empty.
20972097
if (attr->Name.empty())
20982098
diagnose(attr->getLocation(), diag::section_empty_name);
2099+
2100+
if (D->getDeclContext()->isGenericContext())
2101+
diagnose(attr->getLocation(), diag::attr_only_at_non_generic_scope,
2102+
attr->getAttrName());
20992103
}
21002104

21012105
void AttributeChecker::visitUnsafeNoObjCTaggedPointerAttr(

test/IRGen/section.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,22 @@
1111
@_section("__TEXT,__mysection") var g5: UnsafeMutablePointer<Int>? = UnsafeMutablePointer(bitPattern: 0x42424242)
1212
@_section("__TEXT,__mysection") func foo() {}
1313

14+
struct MyStruct {
15+
@_section("__TEXT,__mysection") static var static0: Int = 1
16+
@_section("__TEXT,__mysection") func foo() {}
17+
}
18+
1419
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g0: Int { get set }
1520
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g1: (Int, Int) { get set }
1621
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g2: Bool { get set }
1722
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue public var g3: Bool { get set }
1823
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g4: UnsafeMutablePointer<Int>? { get set }
1924
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g5: UnsafeMutablePointer<Int>? { get set }
2025
// SIL: @_section("__TEXT,__mysection") func foo()
26+
// SIL: struct MyStruct {
27+
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue static var static0: Int { get set }
28+
// SIL: @_section("__TEXT,__mysection") func foo()
29+
2130
// SIL: sil private [global_init_once_fn] @$s7section2g0_WZ : $@convention(c)
2231
// SIL: sil hidden [global_init] @$s7section2g0Sivau : $@convention(thin)
2332
// SIL: sil private [global_init_once_fn] @$s7section2g1_WZ : $@convention(c)
@@ -31,17 +40,16 @@
3140
// SIL: sil private [global_init_once_fn] @$s7section2g5_WZ : $@convention(c)
3241
// SIL: sil hidden [global_init] @$s7section2g5SpySiGSgvau : $@convention(thin)
3342
// SIL: sil hidden [section "__TEXT,__mysection"] @$s7section3fooyyF : $@convention(thin)
43+
// SIL: sil private [global_init_once_fn] @$s7section8MyStructV7static0_WZ : $@convention(c)
44+
// SIL: sil hidden [global_init] @$s7section8MyStructV7static0Sivau : $@convention(thin)
45+
// SIL: sil hidden [section "__TEXT,__mysection"] @$s7section8MyStructV3fooyyF : $@convention(method)
3446

35-
// IR: @"$s7section2g0_Wz" = internal global {{(i64|i32)}} 0
3647
// IR: @"$s7section2g0Sivp" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__TEXT,__mysection"
37-
// IR: @"$s7section2g1_Wz" = internal global {{(i64|i32)}} 0
3848
// IR: @"$s7section2g1Si_Sitvp" = hidden global <{ %TSi, %TSi }> <{ %TSi <{ {{(i64|i32)}} 42 }>, %TSi <{ {{(i64|i32)}} 43 }> }>, section "__TEXT,__mysection"
39-
// IR: @"$s7section2g2_Wz" = internal global {{(i64|i32)}} 0
4049
// IR: @"$s7section2g2Sbvp" = hidden global %TSb <{ i1 true }>, section "__TEXT,__mysection"
41-
// IR: @"$s7section2g3_Wz" = internal global {{(i64|i32)}} 0
4250
// IR: @"$s7section2g3Sbvp" = {{.*}}global %TSb <{ i1 true }>, section "__TEXT,__mysection"
43-
// IR: @"$s7section2g4_Wz" = internal global {{i64|i32}} 0
4451
// IR: @"$s7section2g4SpySiGSgvp" = hidden global {{i64|i32}} 0, section "__TEXT,__mysection"
45-
// IR: @"$s7section2g5_Wz" = internal global {{i64|i32}} 0
4652
// IR: @"$s7section2g5SpySiGSgvp" = hidden global {{i64|i32}} 1111638594, section "__TEXT,__mysection"
53+
// IR: @"$s7section8MyStructV7static0SivpZ" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__TEXT,__mysection"
4754
// IR: define {{.*}}@"$s7section3fooyyF"(){{.*}} section "__TEXT,__mysection"
55+
// IR: define {{.*}}@"$s7section8MyStructV3fooyyF"() #0 section "__TEXT,__mysection"

test/IRGen/section_errors.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -parse-as-library -emit-sil %s -o /dev/null -verify
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
@_used @_section("__TEXT,__mysection") var g0: Int = 1
6+
7+
struct MyStruct {
8+
@_used @_section("__TEXT,__mysection") static var static0: Int = 1
9+
}
10+
11+
struct MyStruct2 {
12+
@_section("__TEXT,__mysection") var member0: Int = 1
13+
}
14+
15+
struct MyStruct3<T> {
16+
static var member0: Int = 1 // expected-error {{static stored properties not supported in generic types}}
17+
18+
@_section("__TEXT,__mysection") func foo() {} // expected-error {{attribute '_section' cannot be used in a generic context}}
19+
}
20+
21+
struct MyStruct4<T> {
22+
struct InnerStruct {
23+
static var member0: Int = 1 // expected-error {{static stored properties not supported in generic types}}
24+
25+
@_section("__TEXT,__mysection") func foo() {} // expected-error {{attribute '_section' cannot be used in a generic context}}
26+
}
27+
}
28+
29+
@_section("__TEXT,__mysection") // expected-error {{'@_section' attribute cannot be applied to this declaration}}
30+
struct SomeStruct {}
31+
32+
@_section("") var g1: Int = 1 // expected-error {{@_section section name cannot be empty}}
33+
34+
func function() {
35+
@_section("__TEXT,__mysection") var l0: Int = 1 // expected-error {{attribute '_section' can only be used in a non-local scope}}
36+
l0 += 1
37+
_ = l0
38+
39+
@_used var l1: Int = 1 // expected-error {{attribute '_used' can only be used in a non-local scope}}
40+
l1 += 1
41+
_ = l1
42+
}

0 commit comments

Comments
 (0)