[Sema] Requestify memberwise init synthesis

This commit adds two requests, one to compute
whether or not a decl should have a memberwise
initializer, and another to synthesize it.
This commit is contained in:
Hamish Knight
2019-10-22 15:26:39 -07:00
parent d8477d51f2
commit ffd5a9cfd6
7 changed files with 112 additions and 24 deletions

View File

@@ -871,36 +871,14 @@ static void addImplicitConstructorsToStruct(StructDecl *decl) {
"User-defined structs cannot have unreferenceable storage");
decl->setAddedImplicitInitializers();
// Check whether there is a user-declared constructor or an instance
// variable.
bool FoundMemberwiseInitializedProperty = false;
(void)decl->getMemberwiseInitializer();
// If the user has already defined a designated initializer, then don't
// synthesize an initializer.
// synthesize a default initializer.
auto &ctx = decl->getASTContext();
if (hasUserDefinedDesignatedInit(ctx.evaluator, decl))
return;
for (auto member : decl->getMembers()) {
if (auto var = dyn_cast<VarDecl>(member)) {
// If this is a backing storage property for a property wrapper,
// skip it.
if (var->getOriginalWrappedProperty())
continue;
if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
FoundMemberwiseInitializedProperty = true;
}
}
if (FoundMemberwiseInitializedProperty) {
// Create the implicit memberwise constructor.
auto ctor = createImplicitConstructor(
decl, ImplicitConstructorKind::Memberwise, ctx);
decl->addMember(ctor);
}
if (areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl))
TypeChecker::defineDefaultConstructor(decl);
}
@@ -1203,6 +1181,43 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
}
}
llvm::Expected<bool>
HasMemberwiseInitRequest::evaluate(Evaluator &evaluator,
StructDecl *decl) const {
// Don't synthesize a memberwise init for imported decls.
if (decl->hasClangNode())
return false;
// If the user has already defined a designated initializer, then don't
// synthesize a memberwise init.
if (hasUserDefinedDesignatedInit(evaluator, decl))
return false;
for (auto *member : decl->getMembers()) {
if (auto *var = dyn_cast<VarDecl>(member)) {
// If this is a backing storage property for a property wrapper,
// skip it.
if (var->getOriginalWrappedProperty())
continue;
if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
return true;
}
}
return false;
}
llvm::Expected<ConstructorDecl *>
SynthesizeMemberwiseInitRequest::evaluate(Evaluator &evaluator,
NominalTypeDecl *decl) const {
// Create the implicit memberwise constructor.
auto &ctx = decl->getASTContext();
auto ctor =
createImplicitConstructor(decl, ImplicitConstructorKind::Memberwise, ctx);
decl->addMember(ctor);
return ctor;
}
/// Synthesizer callback for a function body consisting of "return".
static std::pair<BraceStmt *, bool>
synthesizeSingleReturnFunctionBody(AbstractFunctionDecl *afd, void *) {