Skip to content

Commit 1a88fbf

Browse files
committed
Check default arguments even if a function has no body
This is needed for textual interfaces, but the behavior doesn't have to be specific to that, since functions without bodies don't come up in other situations.
1 parent d3bd01e commit 1a88fbf

File tree

5 files changed

+36
-43
lines changed

5 files changed

+36
-43
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,12 +3131,12 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31313131
}
31323132
}
31333133

3134-
if (FD->hasBody()) {
3135-
// Record the body.
3136-
TC.definedFunctions.push_back(FD);
3137-
} else if (requiresDefinition(FD)) {
3134+
if (requiresDefinition(FD) && !FD->hasBody()) {
31383135
// Complain if we should have a body.
31393136
TC.diagnose(FD->getLoc(), diag::func_decl_without_brace);
3137+
} else {
3138+
// Record the body.
3139+
TC.definedFunctions.push_back(FD);
31403140
}
31413141
}
31423142

@@ -3362,20 +3362,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
33623362
AccessControlChecker::checkAccessControl(TC, CD);
33633363
UsableFromInlineChecker::checkUsableFromInline(TC, CD);
33643364

3365-
if (CD->hasBody() && !CD->isMemberwiseInitializer()) {
3366-
TC.definedFunctions.push_back(CD);
3367-
} else if (requiresDefinition(CD)) {
3365+
if (requiresDefinition(CD) && !CD->hasBody()) {
33683366
// Complain if we should have a body.
33693367
TC.diagnose(CD->getLoc(), diag::missing_initializer_def);
3368+
} else {
3369+
TC.definedFunctions.push_back(CD);
33703370
}
33713371
}
33723372

33733373
void visitDestructorDecl(DestructorDecl *DD) {
33743374
TC.validateDecl(DD);
33753375
TC.checkDeclAttributes(DD);
3376-
3377-
if (DD->hasBody())
3378-
TC.definedFunctions.push_back(DD);
3376+
TC.definedFunctions.push_back(DD);
33793377
}
33803378
};
33813379
} // end anonymous namespace

lib/Sema/TypeCheckStmt.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,7 @@ void TypeChecker::checkDefaultArguments(ParameterList *params,
15331533
bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
15341534
SourceLoc EndTypeCheckLoc) {
15351535
validateDecl(AFD);
1536+
checkDefaultArguments(AFD->getParameters(), AFD);
15361537

15371538
if (!AFD->getBody())
15381539
return false;
@@ -1554,9 +1555,6 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
15541555
if (AFD->isBodyTypeChecked())
15551556
return false;
15561557

1557-
if (!AFD->getBody())
1558-
return false;
1559-
15601558
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-fn", AFD);
15611559
PrettyStackTraceDecl StackEntry("type-checking", AFD);
15621560

@@ -1575,17 +1573,16 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
15751573
if (error)
15761574
return true;
15771575

1578-
performAbstractFuncDeclDiagnostics(*this, AFD);
1576+
if (AFD->getBody())
1577+
performAbstractFuncDeclDiagnostics(*this, AFD);
1578+
15791579
return false;
15801580
}
15811581

15821582
// Type check a function body (defined with the func keyword) that is either a
15831583
// named function or an anonymous func expression.
15841584
bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
15851585
SourceLoc EndTypeCheckLoc) {
1586-
// Check the default argument definitions.
1587-
checkDefaultArguments(FD->getParameters(), FD);
1588-
15891586
// Clang imported inline functions do not have a Swift body to
15901587
// typecheck.
15911588
if (FD->getClangDecl())
@@ -1688,12 +1685,8 @@ static bool isKnownEndOfConstructor(ASTNode N) {
16881685

16891686
bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor,
16901687
SourceLoc EndTypeCheckLoc) {
1691-
// Check the default argument definitions.
1692-
checkDefaultArguments(ctor->getParameters(), ctor);
1693-
16941688
BraceStmt *body = ctor->getBody();
1695-
if (!body)
1696-
return true;
1689+
assert(body);
16971690

16981691
// For constructors, we make sure that the body ends with a "return" stmt,
16991692
// which we either implicitly synthesize, or the user can write. This
@@ -1822,8 +1815,7 @@ bool TypeChecker::typeCheckDestructorBodyUntil(DestructorDecl *DD,
18221815
StmtChecker SC(*this, static_cast<AbstractFunctionDecl *>(DD));
18231816
SC.EndTypeCheckLoc = EndTypeCheckLoc;
18241817
BraceStmt *Body = DD->getBody();
1825-
if (!Body)
1826-
return false;
1818+
assert(Body);
18271819

18281820
bool HadError = SC.typeCheckBody(Body);
18291821

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
class SomeClass {
4+
// Has defaults, but no body.
5+
public func hasDefaults(a: Int = 4, b: Int = 1 + 2)
6+
7+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_
8+
// CHECK: integer_literal $Builtin.Int2048, 4
9+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_'
10+
11+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_
12+
// CHECK: integer_literal $Builtin.Int2048, 1
13+
// CHECK: integer_literal $Builtin.Int2048, 2
14+
// CHECK: function_ref @$SSi1poiyS2i_SitFZ
15+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_'
16+
17+
public init(a: Int = 5)
18+
19+
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_
20+
// CHECK: integer_literal $Builtin.Int2048, 5
21+
// CHECK: end sil function '$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_'
22+
}

test/NameBinding/Inputs/MutualDependencyHelper.swift

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/NameBinding/MutualDependency.swift

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)