Skip to content

Commit 5fed479

Browse files
authored
Merge pull request #69192 from kubamracek/attr-section-on-static-vars
Allow attributes @_used and @_section on static variables and member functions
2 parents 11b8549 + 9e58514 commit 5fed479

File tree

7 files changed

+164
-54
lines changed

7 files changed

+164
-54
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,9 +1541,6 @@ ERROR(attr_expected_colon_after_label,none,
15411541
ERROR(alignment_must_be_positive_integer,none,
15421542
"alignment value must be a positive integer literal", ())
15431543

1544-
ERROR(attr_only_at_non_local_scope, none,
1545-
"attribute '%0' can only be used in a non-local scope", (StringRef))
1546-
15471544
// Access control
15481545
ERROR(attr_access_expected_set,none,
15491546
"expected 'set' as subject of '%0' modifier", (StringRef))

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,13 @@ ERROR(attr_methods_only,none,
19221922
ERROR(attr_decl_async,none,
19231923
"@%0 %1 cannot be asynchronous", (StringRef, DescriptiveDeclKind))
19241924

1925+
ERROR(attr_only_at_non_local_scope, none,
1926+
"attribute '%0' can only be used in a non-local scope", (StringRef))
1927+
ERROR(attr_only_at_non_generic_scope, none,
1928+
"attribute '%0' cannot be used in a generic context", (StringRef))
1929+
ERROR(attr_only_on_static_properties, none,
1930+
"properties with attribute '_section' must be static", (StringRef))
1931+
19251932
ERROR(access_control_in_protocol,none,
19261933
"%0 modifier cannot be used in protocols", (DeclAttribute))
19271934
NOTE(access_control_in_protocol_detail,none,
@@ -3760,6 +3767,8 @@ ERROR(attr_not_on_variadic_parameters,none,
37603767
"'%0' must not be used on variadic parameters", (StringRef))
37613768
ERROR(attr_not_on_stored_properties,none,
37623769
"'%0' must not be used on stored properties", (DeclAttribute))
3770+
ERROR(attr_not_on_computed_properties,none,
3771+
"'%0' must not be used on computed properties", (DeclAttribute))
37633772

37643773
WARNING(attr_has_no_effect_on_decl_with_access_level,none,
37653774
"'%0' does not have any effect on "

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/DebuggerClient.h"
2121
#include "swift/AST/Decl.h"
2222
#include "swift/AST/DiagnosticsParse.h"
23+
#include "swift/AST/DiagnosticsSema.h"
2324
#include "swift/AST/GenericParamList.h"
2425
#include "swift/AST/Initializer.h"
2526
#include "swift/AST/LazyResolver.h"

lib/Sema/TypeCheckAttr.cpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,10 +2080,22 @@ void AttributeChecker::visitUsedAttr(UsedAttr *attr) {
20802080
diagnoseAndRemoveAttr(attr, diag::section_linkage_markers_disabled);
20812081
return;
20822082
}
2083-
2084-
// Only top-level func/var decls are currently supported.
2085-
if (D->getDeclContext()->isTypeContext())
2086-
diagnose(attr->getLocation(), diag::used_not_at_top_level);
2083+
2084+
if (D->getDeclContext()->isLocalContext())
2085+
diagnose(attr->getLocation(), diag::attr_only_at_non_local_scope,
2086+
attr->getAttrName());
2087+
else if (D->getDeclContext()->isGenericContext())
2088+
diagnose(attr->getLocation(), diag::attr_only_at_non_generic_scope,
2089+
attr->getAttrName());
2090+
else if (auto *VarD = dyn_cast<VarDecl>(D)) {
2091+
if (!VarD->isStatic() && !D->getDeclContext()->isModuleScopeContext()) {
2092+
diagnose(attr->getLocation(), diag::attr_only_on_static_properties,
2093+
attr->getAttrName());
2094+
} else if (!VarD->hasStorageOrWrapsStorage()) {
2095+
diagnose(attr->getLocation(), diag::attr_not_on_computed_properties,
2096+
attr);
2097+
}
2098+
}
20872099
}
20882100

20892101
void AttributeChecker::visitSectionAttr(SectionAttr *attr) {
@@ -2092,13 +2104,25 @@ void AttributeChecker::visitSectionAttr(SectionAttr *attr) {
20922104
return;
20932105
}
20942106

2095-
// Only top-level func/var decls are currently supported.
2096-
if (D->getDeclContext()->isTypeContext())
2097-
diagnose(attr->getLocation(), diag::section_not_at_top_level);
2098-
20992107
// The name must not be empty.
21002108
if (attr->Name.empty())
21012109
diagnose(attr->getLocation(), diag::section_empty_name);
2110+
2111+
if (D->getDeclContext()->isLocalContext())
2112+
return; // already diagnosed
2113+
2114+
if (D->getDeclContext()->isGenericContext())
2115+
diagnose(attr->getLocation(), diag::attr_only_at_non_generic_scope,
2116+
attr->getAttrName());
2117+
else if (auto *VarD = dyn_cast<VarDecl>(D)) {
2118+
if (!VarD->isStatic() && !D->getDeclContext()->isModuleScopeContext()) {
2119+
diagnose(attr->getLocation(), diag::attr_only_on_static_properties,
2120+
attr->getAttrName());
2121+
} else if (!VarD->hasStorageOrWrapsStorage()) {
2122+
diagnose(attr->getLocation(), diag::attr_not_on_computed_properties,
2123+
attr);
2124+
}
2125+
}
21022126
}
21032127

21042128
void AttributeChecker::visitUnsafeNoObjCTaggedPointerAttr(

test/IRGen/section.swift

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,30 @@
33

44
// REQUIRES: swift_in_compiler
55

6-
@_section("__TEXT,__mysection") var g0: Int = 1
7-
@_section("__TEXT,__mysection") var g1: (Int, Int) = (42, 43)
8-
@_section("__TEXT,__mysection") var g2: Bool = true
9-
@_section("__TEXT,__mysection") public var g3: Bool = true
10-
@_section("__TEXT,__mysection") var g4: UnsafeMutablePointer<Int>? = nil
11-
@_section("__TEXT,__mysection") var g5: UnsafeMutablePointer<Int>? = UnsafeMutablePointer(bitPattern: 0x42424242)
6+
@_section("__DATA,__mysection") var g0: Int = 1
7+
@_section("__DATA,__mysection") var g1: (Int, Int) = (42, 43)
8+
@_section("__DATA,__mysection") var g2: Bool = true
9+
@_section("__DATA,__mysection") public var g3: Bool = true
10+
@_section("__DATA,__mysection") var g4: UnsafeMutablePointer<Int>? = nil
11+
@_section("__DATA,__mysection") var g5: UnsafeMutablePointer<Int>? = UnsafeMutablePointer(bitPattern: 0x42424242)
1212
@_section("__TEXT,__mysection") func foo() {}
1313

14-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g0: Int { get set }
15-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g1: (Int, Int) { get set }
16-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g2: Bool { get set }
17-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue public var g3: Bool { get set }
18-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g4: UnsafeMutablePointer<Int>? { get set }
19-
// SIL: @_section("__TEXT,__mysection") @_hasStorage @_hasInitialValue var g5: UnsafeMutablePointer<Int>? { get set }
14+
struct MyStruct {
15+
@_section("__DATA,__mysection") static var static0: Int = 1
16+
@_section("__TEXT,__mysection") func foo() {}
17+
}
18+
19+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g0: Int { get set }
20+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g1: (Int, Int) { get set }
21+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g2: Bool { get set }
22+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue public var g3: Bool { get set }
23+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g4: UnsafeMutablePointer<Int>? { get set }
24+
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g5: UnsafeMutablePointer<Int>? { get set }
2025
// SIL: @_section("__TEXT,__mysection") func foo()
26+
// SIL: struct MyStruct {
27+
// SIL: @_section("__DATA,__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
36-
// IR: @"$s7section2g0Sivp" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__TEXT,__mysection"
37-
// IR: @"$s7section2g1_Wz" = internal global {{(i64|i32)}} 0
38-
// 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
40-
// IR: @"$s7section2g2Sbvp" = hidden global %TSb <{ i1 true }>, section "__TEXT,__mysection"
41-
// IR: @"$s7section2g3_Wz" = internal global {{(i64|i32)}} 0
42-
// IR: @"$s7section2g3Sbvp" = {{.*}}global %TSb <{ i1 true }>, section "__TEXT,__mysection"
43-
// IR: @"$s7section2g4_Wz" = internal global {{i64|i32}} 0
44-
// IR: @"$s7section2g4SpySiGSgvp" = hidden global {{i64|i32}} 0, section "__TEXT,__mysection"
45-
// IR: @"$s7section2g5_Wz" = internal global {{i64|i32}} 0
46-
// IR: @"$s7section2g5SpySiGSgvp" = hidden global {{i64|i32}} 1111638594, section "__TEXT,__mysection"
47+
// IR: @"$s7section2g0Sivp" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__DATA,__mysection"
48+
// IR: @"$s7section2g1Si_Sitvp" = hidden global <{ %TSi, %TSi }> <{ %TSi <{ {{(i64|i32)}} 42 }>, %TSi <{ {{(i64|i32)}} 43 }> }>, section "__DATA,__mysection"
49+
// IR: @"$s7section2g2Sbvp" = hidden global %TSb <{ i1 true }>, section "__DATA,__mysection"
50+
// IR: @"$s7section2g3Sbvp" = {{.*}}global %TSb <{ i1 true }>, section "__DATA,__mysection"
51+
// IR: @"$s7section2g4SpySiGSgvp" = hidden global {{i64|i32}} 0, section "__DATA,__mysection"
52+
// IR: @"$s7section2g5SpySiGSgvp" = hidden global {{i64|i32}} 1111638594, section "__DATA,__mysection"
53+
// IR: @"$s7section8MyStructV7static0SivpZ" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__DATA,__mysection"
4754
// IR: define {{.*}}@"$s7section3fooyyF"(){{.*}} section "__TEXT,__mysection"
55+
// IR: define {{.*}}@"$s7section8MyStructV3fooyyF"() #0 section "__TEXT,__mysection"

test/IRGen/section_asm.swift

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -primary-file %S/section.swift -S -parse-as-library | %FileCheck %s --check-prefix=ASM --check-prefix ASM-%target-os
1+
// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -primary-file %S/section.swift -S -parse-as-library | %FileCheck %s
22
// REQUIRES: swift_in_compiler
33
// UNSUPPORTED: CPU=wasm32
44

5-
// ASM: .section{{.*}}__TEXT,__mysection
6-
// ASM-NOT: .section
7-
// ASM: $s7section3fooyyF:
8-
// ASM-linux-gnu: .section{{.*}}__TEXT,__mysection
9-
// ASM-linux-android: .section{{.*}}__TEXT,__mysection
10-
// ASM-linux-androideabi: .section{{.*}}__TEXT,__mysection
11-
// ASM-NOT: .section
12-
// ASM: $s7section2g0Sivp:
13-
// ASM-NOT: .section
14-
// ASM: $s7section2g1Si_Sitvp:
15-
// ASM-NOT: .section
16-
// ASM: $s7section2g2Sbvp:
17-
// ASM-NOT: .section
18-
// ASM: $s7section2g3Sbvp:
19-
// ASM-NOT: .section
20-
// ASM: $s7section2g4SpySiGSgvp:
21-
// ASM-NOT: .section
22-
// ASM: $s7section2g5SpySiGSgvp:
5+
// CHECK: .section{{.*}}__TEXT,__mysection
6+
// CHECK-NOT: .section
7+
// CHECK: $s7section3fooyyF:
8+
9+
// CHECK: .section{{.*}}__TEXT,__mysection
10+
// CHECK-NOT: .section
11+
// CHECK: $s7section8MyStructV3fooyyF:
12+
13+
// CHECK: .section{{.*}}__DATA,__mysection
14+
// CHECK-NOT: .section
15+
// CHECK: $s7section2g0Sivp:
16+
// CHECK-NOT: .section
17+
// CHECK: $s7section2g1Si_Sitvp:
18+
// CHECK-NOT: .section
19+
// CHECK: $s7section2g2Sbvp:
20+
// CHECK-NOT: .section
21+
// CHECK: $s7section2g3Sbvp:
22+
// CHECK-NOT: .section
23+
// CHECK: $s7section2g4SpySiGSgvp:
24+
// CHECK-NOT: .section
25+
// CHECK: $s7section2g5SpySiGSgvp:
26+
// CHECK-NOT: .section
27+
// CHECK: $s7section8MyStructV7static0SivpZ:

test/IRGen/section_errors.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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 // ok
6+
7+
struct MyStruct {
8+
@_used @_section("__TEXT,__mysection") static var static0: Int = 1 // ok
9+
}
10+
11+
struct MyStruct2 {
12+
@_section("__TEXT,__mysection") var member0: Int = 1 // expected-error {{properties with attribute '_section' must be static}}
13+
14+
@_section("__TEXT,__mysection") static var static1: Int { return 1 } // expected-error {{'@_section' must not be used on computed properties}}
15+
}
16+
17+
struct MyStruct3<T> {
18+
static var member1: Int = 1 // expected-error {{static stored properties not supported in generic types}}
19+
20+
@_section("__TEXT,__mysection") func foo() {} // expected-error {{attribute '_section' cannot be used in a generic context}}
21+
}
22+
23+
struct MyStruct4<T> {
24+
struct InnerStruct {
25+
static var member2: Int = 1 // expected-error {{static stored properties not supported in generic types}}
26+
27+
@_section("__TEXT,__mysection") static var member3: Int = 1 // expected-error {{static stored properties not supported in generic types}}
28+
// expected-error@-1 {{attribute '_section' cannot be used in a generic context}}
29+
30+
@_section("__TEXT,__mysection") func foo() {} // expected-error {{attribute '_section' cannot be used in a generic context}}
31+
}
32+
}
33+
34+
@_section("__TEXT,__mysection") // expected-error {{'@_section' attribute cannot be applied to this declaration}}
35+
struct SomeStruct {}
36+
37+
@_section("") var g1: Int = 1 // expected-error {{@_section section name cannot be empty}}
38+
39+
func function() {
40+
@_section("__TEXT,__mysection") var l0: Int = 1 // expected-error {{attribute '_section' can only be used in a non-local scope}}
41+
l0 += 1
42+
_ = l0
43+
44+
@_used var l1: Int = 1 // expected-error {{attribute '_used' can only be used in a non-local scope}}
45+
l1 += 1
46+
_ = l1
47+
}
48+
49+
func function_with_type() {
50+
class MyClass {
51+
@_section("__TEXT,__mysection") static var member: Int = 1 // ok
52+
}
53+
54+
do {
55+
class MyClass {
56+
@_section("__TEXT,__mysection") static var member: Int = 1 // ok
57+
}
58+
}
59+
}
60+
61+
func function_with_type_generic<T>() -> T {
62+
class MyClass { // expected-error {{type 'MyClass' cannot be nested in generic function}}
63+
@_section("__TEXT,__mysection") static var member: Int = 1 // expected-error {{static stored properties not supported in generic types}}
64+
// expected-error@-1 {{attribute '_section' cannot be used in a generic context}}
65+
}
66+
}

0 commit comments

Comments
 (0)