Check default arguments even if a function has no body (#18864)

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.
This commit is contained in:
Jordan Rose
2018-08-21 10:41:24 -07:00
committed by GitHub
parent 3b2c55fe69
commit 71a2adbdde
5 changed files with 36 additions and 43 deletions

View File

@@ -3123,12 +3123,12 @@ public:
}
}
if (FD->hasBody()) {
// Record the body.
TC.definedFunctions.push_back(FD);
} else if (requiresDefinition(FD)) {
if (requiresDefinition(FD) && !FD->hasBody()) {
// Complain if we should have a body.
TC.diagnose(FD->getLoc(), diag::func_decl_without_brace);
} else {
// Record the body.
TC.definedFunctions.push_back(FD);
}
}
@@ -3354,20 +3354,18 @@ public:
AccessControlChecker::checkAccessControl(TC, CD);
UsableFromInlineChecker::checkUsableFromInline(TC, CD);
if (CD->hasBody() && !CD->isMemberwiseInitializer()) {
TC.definedFunctions.push_back(CD);
} else if (requiresDefinition(CD)) {
if (requiresDefinition(CD) && !CD->hasBody()) {
// Complain if we should have a body.
TC.diagnose(CD->getLoc(), diag::missing_initializer_def);
} else {
TC.definedFunctions.push_back(CD);
}
}
void visitDestructorDecl(DestructorDecl *DD) {
TC.validateDecl(DD);
TC.checkDeclAttributes(DD);
if (DD->hasBody())
TC.definedFunctions.push_back(DD);
TC.definedFunctions.push_back(DD);
}
};
} // end anonymous namespace

View File

@@ -1537,6 +1537,7 @@ void TypeChecker::checkDefaultArguments(ParameterList *params,
bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
SourceLoc EndTypeCheckLoc) {
validateDecl(AFD);
checkDefaultArguments(AFD->getParameters(), AFD);
if (!AFD->getBody())
return false;
@@ -1558,9 +1559,6 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
if (AFD->isBodyTypeChecked())
return false;
if (!AFD->getBody())
return false;
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-fn", AFD);
PrettyStackTraceDecl StackEntry("type-checking", AFD);
@@ -1579,7 +1577,9 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
if (error)
return true;
performAbstractFuncDeclDiagnostics(*this, AFD);
if (AFD->getBody())
performAbstractFuncDeclDiagnostics(*this, AFD);
return false;
}
@@ -1587,9 +1587,6 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
// named function or an anonymous func expression.
bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
SourceLoc EndTypeCheckLoc) {
// Check the default argument definitions.
checkDefaultArguments(FD->getParameters(), FD);
// Clang imported inline functions do not have a Swift body to
// typecheck.
if (FD->getClangDecl())
@@ -1692,12 +1689,8 @@ static bool isKnownEndOfConstructor(ASTNode N) {
bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor,
SourceLoc EndTypeCheckLoc) {
// Check the default argument definitions.
checkDefaultArguments(ctor->getParameters(), ctor);
BraceStmt *body = ctor->getBody();
if (!body)
return true;
assert(body);
// For constructors, we make sure that the body ends with a "return" stmt,
// which we either implicitly synthesize, or the user can write. This
@@ -1826,8 +1819,7 @@ bool TypeChecker::typeCheckDestructorBodyUntil(DestructorDecl *DD,
StmtChecker SC(*this, static_cast<AbstractFunctionDecl *>(DD));
SC.EndTypeCheckLoc = EndTypeCheckLoc;
BraceStmt *Body = DD->getBody();
if (!Body)
return false;
assert(Body);
bool HadError = SC.typeCheckBody(Body);

View File

@@ -0,0 +1,22 @@
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
class SomeClass {
// Has defaults, but no body.
public func hasDefaults(a: Int = 4, b: Int = 1 + 2)
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_
// CHECK: integer_literal $Builtin.Int2048, 4
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA_'
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_
// CHECK: integer_literal $Builtin.Int2048, 1
// CHECK: integer_literal $Builtin.Int2048, 2
// CHECK: function_ref @$SSi1poiyS2i_SitFZ
// CHECK: end sil function '$S11DefaultArgs9SomeClassC11hasDefaults1a1bySi_SitFfA0_'
public init(a: Int = 5)
// CHECK-LABEL: sil hidden @$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_
// CHECK: integer_literal $Builtin.Int2048, 5
// CHECK: end sil function '$S11DefaultArgs9SomeClassC1aACSi_tcfcfA_'
}

View File

@@ -1,5 +0,0 @@
import MutualDependency
public protocol MyDelegate {
func doSomething(sender: MyClass)
}

View File

@@ -1,14 +0,0 @@
// RUN: %target-swift-frontend -typecheck %s -enable-source-import -I %S/Inputs -parse-as-library
// RUN: %target-swift-frontend -typecheck %s -enable-source-import -I %S/Inputs
// RUN: %target-swift-frontend -typecheck %S/Inputs/MutualDependencyHelper.swift -enable-source-import -I %S
// RUN: %target-swift-frontend -interpret -I %S/Inputs -enable-source-import %s -verify
import MutualDependencyHelper
public class MyClass {
public var delegate : MyDelegate // expected-note {{'self.delegate' not initialized}}
public init() {} // expected-error {{return from initializer without initializing all stored properties}}
}