Skip to content

Commit 38e88d8

Browse files
authored
Merge pull request #18764 from jrose-apple/smoke-rings
Tweak Parse and SILGen to support loading swiftinterface files
2 parents 2f1b464 + 1a3cb5b commit 38e88d8

File tree

4 files changed

+117
-32
lines changed

4 files changed

+117
-32
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,11 +4086,23 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
40864086
SourceLoc &LastValidLoc, SourceLoc StaticLoc,
40874087
SourceLoc VarLBLoc) {
40884088
// Properties in protocols use a very limited syntax.
4089-
// SIL mode uses the same syntax.
4089+
// SIL mode and textual interfaces use the same syntax.
40904090
// Otherwise, we have a normal var or subscript declaration and we need
40914091
// parse the full complement of specifiers, along with their bodies.
4092-
bool parsingLimitedSyntax =
4093-
Flags.contains(PD_InProtocol) || isInSILMode();
4092+
bool parsingLimitedSyntax = Flags.contains(PD_InProtocol);
4093+
if (!parsingLimitedSyntax) {
4094+
switch (SF.Kind) {
4095+
case SourceFileKind::Interface:
4096+
// FIXME: Textual interfaces /can/ have inlinable code but don't have to.
4097+
case SourceFileKind::SIL:
4098+
parsingLimitedSyntax = true;
4099+
break;
4100+
case SourceFileKind::Library:
4101+
case SourceFileKind::Main:
4102+
case SourceFileKind::REPL:
4103+
break;
4104+
}
4105+
}
40944106

40954107
// If the body is completely empty, preserve it. This is at best a getter with
40964108
// an implicit fallthrough off the end.
@@ -6305,34 +6317,42 @@ parseDeclDeinit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
63056317
SourceLoc DestructorLoc = consumeToken(tok::kw_deinit);
63066318

63076319
// Parse extraneous parentheses and remove them with a fixit.
6308-
if (Tok.is(tok::l_paren)) {
6309-
SourceRange ParenRange;
6310-
SourceLoc LParenLoc = consumeToken();
6320+
auto skipParameterListIfPresent = [this] {
6321+
SourceLoc LParenLoc;
6322+
if (!consumeIf(tok::l_paren, LParenLoc))
6323+
return;
63116324
SourceLoc RParenLoc;
63126325
skipUntil(tok::r_paren);
63136326

63146327
if (Tok.is(tok::r_paren)) {
63156328
SourceLoc RParenLoc = consumeToken();
6316-
ParenRange = SourceRange(LParenLoc, RParenLoc);
6317-
6318-
diagnose(ParenRange.Start, diag::destructor_params)
6319-
.fixItRemoveChars(Lexer::getLocForEndOfToken(Context.SourceMgr,
6320-
DestructorLoc),
6321-
Lexer::getLocForEndOfToken(Context.SourceMgr,
6322-
ParenRange.End));
6329+
diagnose(LParenLoc, diag::destructor_params)
6330+
.fixItRemove(SourceRange(LParenLoc, RParenLoc));
63236331
} else {
63246332
diagnose(Tok, diag::opened_destructor_expected_rparen);
63256333
diagnose(LParenLoc, diag::opening_paren);
63266334
}
6327-
}
6335+
};
63286336

63296337
// '{'
63306338
if (!Tok.is(tok::l_brace)) {
6331-
if (!Tok.is(tok::l_brace) && !isInSILMode()) {
6339+
switch (SF.Kind) {
6340+
case SourceFileKind::Interface:
6341+
case SourceFileKind::SIL:
6342+
// It's okay to have no body for SIL code or textual interfaces.
6343+
break;
6344+
case SourceFileKind::Library:
6345+
case SourceFileKind::Main:
6346+
case SourceFileKind::REPL:
63326347
if (Tok.is(tok::identifier)) {
63336348
diagnose(Tok, diag::destructor_has_name).fixItRemove(Tok.getLoc());
6334-
} else
6335-
diagnose(Tok, diag::expected_lbrace_destructor);
6349+
consumeToken();
6350+
}
6351+
skipParameterListIfPresent();
6352+
if (Tok.is(tok::l_brace))
6353+
break;
6354+
6355+
diagnose(Tok, diag::expected_lbrace_destructor);
63366356
return nullptr;
63376357
}
63386358
}

lib/SILGen/SILGen.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,9 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) {
776776
postEmitFunction(constant, f);
777777
});
778778

779-
// If this constructor was imported, we don't need the initializing
780-
// constructor to be emitted.
781-
if (!decl->hasClangNode()) {
779+
// Constructors may not have bodies if they've been imported, or if they've
780+
// been parsed from a textual interface.
781+
if (decl->hasBody()) {
782782
SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer);
783783
emitOrDelayFunction(
784784
*this, initConstant,
@@ -796,14 +796,16 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) {
796796
}
797797
} else {
798798
// Struct and enum constructors do everything in a single function.
799-
emitOrDelayFunction(
800-
*this, constant, [this, constant, decl, declCtx](SILFunction *f) {
801-
preEmitFunction(constant, decl, f, decl);
802-
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
803-
f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
804-
SILGenFunction(*this, *f, decl).emitValueConstructor(decl);
805-
postEmitFunction(constant, f);
806-
});
799+
if (decl->hasBody()) {
800+
emitOrDelayFunction(
801+
*this, constant, [this, constant, decl, declCtx](SILFunction *f) {
802+
preEmitFunction(constant, decl, f, decl);
803+
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
804+
f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
805+
SILGenFunction(*this, *f, decl).emitValueConstructor(decl);
806+
postEmitFunction(constant, f);
807+
});
808+
}
807809
}
808810
}
809811

@@ -941,7 +943,7 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
941943

942944
// Emit the destroying destructor.
943945
// Destructors are a necessary part of class metadata, so can't be delayed.
944-
{
946+
if (dd->hasBody()) {
945947
SILDeclRef destroyer(dd, SILDeclRef::Kind::Destroyer);
946948
SILFunction *f = getFunction(destroyer, ForDefinition);
947949
preEmitFunction(destroyer, dd, f, dd);

test/ModuleInterface/SmokeTest.swiftinterface

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,66 @@
44
// ...and then make sure parse-and-typecheck-and-serialize works.
55
// RUN: %empty-directory(%t)
66
// RUN: %target-swift-frontend -emit-module -o %t/SmokeTest.swiftmodule %s
7-
// RUN: %target-swift-ide-test -print-module -module-to-print SmokeTest -I %t -source-filename x -print-access | %FileCheck %s
7+
// RUN: %target-swift-ide-test -print-module -module-to-print SmokeTest -I %t -source-filename x -print-interface > %t/SmokeTest.txt
8+
// RUN: %FileCheck %s < %t/SmokeTest.txt
9+
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t/SmokeTest.txt
10+
11+
// CHECK-LABEL: public class TestClass
12+
public class TestClass {
13+
// CHECK: public init(){{$}}
14+
public init()
15+
16+
// CHECK: public func method(){{$}}
17+
public func method()
18+
19+
// CHECK: public subscript(_: Int) -> Void{{$}}
20+
public subscript(_: Int) -> Void { get set }
21+
22+
// CHECK: public var prop: Int{{$}}
23+
public var prop: Int { get set }
24+
25+
// NEGATIVE-NOT: deinit
26+
deinit
27+
} // CHECK: {{^}$}}
28+
29+
// CHECK-LABEL: public enum TestEnum
30+
public enum TestEnum {
31+
// CHECK: case a
32+
case a
33+
34+
// CHECK: public init(){{$}}
35+
public init()
36+
37+
// CHECK: public func method(){{$}}
38+
public func method()
39+
40+
// CHECK: public subscript(_: Int) -> Void{{$}}
41+
public subscript(_: Int) -> Void { get set }
42+
43+
// CHECK: public var prop: Int{{$}}
44+
public var prop: Int { get set }
45+
} // CHECK: {{^}$}}
46+
47+
// CHECK-LABEL: public struct TestStruct
48+
public struct TestStruct {
49+
// CHECK: public init(){{$}}
50+
public init()
51+
52+
// CHECK: public func method(){{$}}
53+
public func method()
54+
55+
// CHECK: public subscript(_: Int) -> Void{{$}}
56+
public subscript(_: Int) -> Void { get set }
57+
58+
// CHECK: public var prop: Int{{$}}
59+
public var prop: Int { get set }
60+
} // CHECK: {{^}$}}
61+
62+
// CHECK: public var readOnlyVar: Int { get }{{$}}
63+
public var readOnlyVar: Int { get }
64+
65+
// CHECK: public var readWriteVar: Int{{$}}
66+
public var readWriteVar: Int { get set }
867

968
// CHECK: public func verySimpleFunction(){{$}}
1069
public func verySimpleFunction()

test/Parse/init_deinit.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ struct FooStructConstructorC {
1717

1818
struct FooStructDeinitializerA {
1919
deinit // expected-error {{expected '{' for deinitializer}}
20-
deinit x // expected-error {{deinitializers cannot have a name}} {{10-12=}}
21-
deinit x() // expected-error {{deinitializers cannot have a name}} {{10-11=}}
20+
deinit x // expected-error {{deinitializers cannot have a name}} {{10-12=}} expected-error {{expected '{' for deinitializer}}
21+
deinit x() // expected-error {{deinitializers cannot have a name}} {{10-11=}} expected-error {{no parameter clause allowed on deinitializer}} {{11-13=}} expected-error {{expected '{' for deinitializer}}
2222
}
2323

2424
struct FooStructDeinitializerB {
@@ -37,6 +37,10 @@ class FooClassDeinitializerB {
3737
deinit { }
3838
}
3939

40+
class FooClassDeinitializerC {
41+
deinit x (a : Int) {} // expected-error {{deinitializers cannot have a name}} {{10-12=}} expected-error{{no parameter clause allowed on deinitializer}}{{12-22=}}
42+
}
43+
4044
init {} // expected-error {{initializers may only be declared within a type}} expected-error {{expected '('}} {{5-5=()}}
4145
init() // expected-error {{initializers may only be declared within a type}}
4246
init() {} // expected-error {{initializers may only be declared within a type}}

0 commit comments

Comments
 (0)