Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,10 @@ SWIFT_NAME("BridgedDeclAttributes.add(self:_:)")
void BridgedDeclAttributes_add(BridgedDeclAttributes *_Nonnull attrs,
BridgedDeclAttribute add);

SWIFT_NAME("BridgedDeclAttributes.hasAttribute(self:_:)")
bool BridgedDeclAttributes_hasAttribute(
const BridgedDeclAttributes *_Nonnull attrs, swift::DeclAttrKind kind);

SWIFT_NAME("BridgedDeclAttribute.createSimple(_:kind:atLoc:nameLoc:)")
BridgedDeclAttribute BridgedDeclAttribute_createSimple(
BridgedASTContext cContext, swift::DeclAttrKind kind,
Expand Down
5 changes: 5 additions & 0 deletions lib/AST/Bridging/DeclAttributeBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ void BridgedDeclAttributes_add(BridgedDeclAttributes *cAttrs,
*cAttrs = attrs;
}

bool BridgedDeclAttributes_hasAttribute(
const BridgedDeclAttributes *_Nonnull attrs, swift::DeclAttrKind kind) {
return attrs->unbridged().getAttribute(kind) != nullptr;
}

static AvailableAttr::Kind unbridge(BridgedAvailableAttrKind value) {
switch (value) {
case BridgedAvailableAttrKindDefault:
Expand Down
6 changes: 5 additions & 1 deletion lib/ASTGen/Sources/ASTGen/Decls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,12 @@ extension ASTGenVisitor {
// TODO: Diagnostics
fatalError("invalid pattern binding introducer")
}

// @const/@section globals are not top-level, per SE-0492.
let isConst = attrs.attributes.hasAttribute(.Section) || attrs.attributes.hasAttribute(.ConstVal)

let topLevelDecl: BridgedTopLevelCodeDecl?
if self.declContext.isModuleScopeContext, self.declContext.parentSourceFile.isScriptMode {
if self.declContext.isModuleScopeContext, self.declContext.parentSourceFile.isScriptMode, !isConst {
topLevelDecl = BridgedTopLevelCodeDecl.create(self.ctx, declContext: self.declContext)
} else {
topLevelDecl = nil
Expand Down
9 changes: 6 additions & 3 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8749,13 +8749,16 @@ Parser::parseDeclVar(ParseDeclOptions Flags,

SourceLoc VarLoc = newBindingContext.getIntroducer() ? consumeToken() : Tok.getLoc();

bool IsConst = Attributes.hasAttribute<SectionAttr>() ||
Attributes.hasAttribute<ConstValAttr>();

// If this is a var in the top-level of script/repl source file, wrap the
// PatternBindingDecl in a TopLevelCodeDecl, since it represents executable
// code. The VarDecl and any accessor decls (for computed properties) go in
// CurDeclContext.
//
// CurDeclContext. @const/@section globals are not top-level, per SE-0492.
TopLevelCodeDecl *topLevelDecl = nullptr;
if (allowTopLevelCode() && CurDeclContext->isModuleScopeContext()) {
if (allowTopLevelCode() && CurDeclContext->isModuleScopeContext() &&
!IsConst) {
// The body of topLevelDecl will get set later.
topLevelDecl = new (Context) TopLevelCodeDecl(CurDeclContext);
}
Expand Down
45 changes: 21 additions & 24 deletions test/ConstValues/SectionTopLevel.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Constant globals using @section
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature ParserASTGen | %FileCheck %s

// TODO
// XFAIL: *
// REQUIRES: swift_feature_ParserASTGen

// integer literals
@section("mysection") let intLiteral1 = 42 // ok
Expand Down Expand Up @@ -31,30 +31,27 @@ func bar(x: Int) -> String { return "test" }
@section("mysection") let funcRef1 = foo // ok
@section("mysection") let funcRef2 = bar // ok

// metatypes - TODO
//@section("mysection") let metatype1 = Int.self

// tuples
@section("mysection") let tuple1 = (1, 2, 3, 2.718, true) // ok
@section("mysection") let tuple2: (Int, Float, Bool) = (42, 3.14, false) // ok
@section("mysection") let tuple3 = (foo, bar) // ok (function references in tuple)

// CHECK: @"$s9SectionIR11intLiteral1Sivp" = {{.*}}constant %TSi <{ i64 42 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral2s4Int8Vvp" = {{.*}}constant %Ts4Int8V <{ i8 127 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral3s5Int16Vvp" = {{.*}}constant %Ts5Int16V <{ i16 32767 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral4s5Int32Vvp" = {{.*}}constant %Ts5Int32V <{ i32 2147483647 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral5s5Int64Vvp" = {{.*}}constant %Ts5Int64V <{ i64 9223372036854775807 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral6Suvp" = {{.*}}constant %TSu <{ i64 42 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral7s5UInt8Vvp" = {{.*}}constant %Ts5UInt8V <{ i8 -1 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral8s6UInt16Vvp" = {{.*}}constant %Ts6UInt16V <{ i16 -1 }>, section "mysection"
// CHECK: @"$s9SectionIR11intLiteral9s6UInt32Vvp" = {{.*}}constant %Ts6UInt32V <{ i32 -1 }>, section "mysection"
// CHECK: @"$s9SectionIR12intLiteral10s6UInt64Vvp" = {{.*}}constant %Ts6UInt64V <{ i64 -1 }>, section "mysection"
// CHECK: @"$s9SectionIR13floatLiteral1Sfvp" = {{.*}}constant %TSf <{ float 0x40091EB860000000 }>, section "mysection"
// CHECK: @"$s9SectionIR13floatLiteral2Sdvp" = {{.*}}constant %TSd <{ double 2.718000e+00 }>, section "mysection"
// CHECK: @"$s9SectionIR12boolLiteral1Sbvp" = {{.*}}constant %TSb <{ i1 true }>, section "mysection"
// CHECK: @"$s9SectionIR12boolLiteral2Sbvp" = {{.*}}constant %TSb zeroinitializer, section "mysection"
// CHECK: @"$s9SectionIR8funcRef1Siycvp" = {{.*}}constant %swift.function { ptr @"$s9SectionIR3fooSiyF", ptr null }, section "mysection"
// CHECK: @"$s9SectionIR8funcRef2ySSSicvp" = {{.*}}constant %swift.function { ptr @"$s9SectionIR3bar1xSSSi_tF", ptr null }, section "mysection"
// CHECK: @"$s9SectionIR6tuple1Si_S2iSdSbtvp" = {{.*}}constant <{ %TSi, %TSi, %TSi, %TSd, %TSb }> <{ %TSi <{ i64 1 }>, %TSi <{ i64 2 }>, %TSi <{ i64 3 }>, %TSd <{ double 2.718000e+00 }>, %TSb <{ i1 true }> }>, section "mysection"
// CHECK: @"$s9SectionIR6tuple2Si_SfSbtvp" = {{.*}}constant <{ %TSi, %TSf, %TSb }> <{ %TSi <{ i64 42 }>, %TSf <{ float 0x40091EB860000000 }>, %TSb zeroinitializer }>, section "mysection"
// CHECK: @"$s9SectionIR6tuple3Siyc_SSSictvp" = {{.*}}constant <{ %swift.function, %swift.function }> <{ %swift.function { ptr @"$s9SectionIR3fooSiyF", ptr null }, %swift.function { ptr @"$s9SectionIR3bar1xSSSi_tF", ptr null } }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral1Sivp" = {{.*}}constant %TSi <{ i64 42 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral2s4Int8Vvp" = {{.*}}constant %Ts4Int8V <{ i8 127 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral3s5Int16Vvp" = {{.*}}constant %Ts5Int16V <{ i16 32767 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral4s5Int32Vvp" = {{.*}}constant %Ts5Int32V <{ i32 2147483647 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral5s5Int64Vvp" = {{.*}}constant %Ts5Int64V <{ i64 9223372036854775807 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral6Suvp" = {{.*}}constant %TSu <{ i64 42 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral7s5UInt8Vvp" = {{.*}}constant %Ts5UInt8V <{ i8 -1 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral8s6UInt16Vvp" = {{.*}}constant %Ts6UInt16V <{ i16 -1 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel11intLiteral9s6UInt32Vvp" = {{.*}}constant %Ts6UInt32V <{ i32 -1 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel12intLiteral10s6UInt64Vvp" = {{.*}}constant %Ts6UInt64V <{ i64 -1 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel13floatLiteral1Sfvp" = {{.*}}constant %TSf <{ float 0x40091EB860000000 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel13floatLiteral2Sdvp" = {{.*}}constant %TSd <{ double 2.718000e+00 }>, section "mysection"
// CHECK: @"$s15SectionTopLevel12boolLiteral1Sbvp" = {{.*}}constant %TSb <{ i1 true }>, section "mysection"
// CHECK: @"$s15SectionTopLevel12boolLiteral2Sbvp" = {{.*}}constant %TSb zeroinitializer, section "mysection"
// CHECK: @"$s15SectionTopLevel8funcRef1Siycvp" = {{.*}}constant %swift.function { ptr @"$s15SectionTopLevel3fooSiyF", ptr null }, section "mysection"
// CHECK: @"$s15SectionTopLevel8funcRef2ySSSicvp" = {{.*}}constant %swift.function { ptr @"$s15SectionTopLevel3bar1xSSSi_tF", ptr null }, section "mysection"
// CHECK: @"$s15SectionTopLevel6tuple1Si_S2iSdSbtvp" = {{.*}}constant <{ %TSi, %TSi, %TSi, %TSd, %TSb }> <{ %TSi <{ i64 1 }>, %TSi <{ i64 2 }>, %TSi <{ i64 3 }>, %TSd <{ double 2.718000e+00 }>, %TSb <{ i1 true }> }>, section "mysection"
// CHECK: @"$s15SectionTopLevel6tuple2Si_SfSbtvp" = {{.*}}constant <{ %TSi, %TSf, %TSb }> <{ %TSi <{ i64 42 }>, %TSf <{ float 0x40091EB860000000 }>, %TSb zeroinitializer }>, section "mysection"
// CHECK: @"$s15SectionTopLevel6tuple3Siyc_SSSictvp" = {{.*}}constant <{ %swift.function, %swift.function }> <{ %swift.function { ptr @"$s15SectionTopLevel3fooSiyF", ptr null }, %swift.function { ptr @"$s15SectionTopLevel3bar1xSSSi_tF", ptr null } }>, section "mysection"
2 changes: 1 addition & 1 deletion test/ConstValues/TopLevel.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Constant globals should "work" even in top-level code mode.
// REQUIRES: swift_feature_CompileTimeValues
// REQUIRES: swift_feature_CompileTimeValuesPreview
// REQUIRES: rdar146954355

// RUN: %target-swift-frontend -emit-ir -primary-file %s -enable-experimental-feature CompileTimeValues -enable-experimental-feature CompileTimeValuesPreview
// RUN: %target-swift-frontend -emit-ir -primary-file %s -parse-as-library -enable-experimental-feature CompileTimeValues -enable-experimental-feature CompileTimeValuesPreview

Expand Down