void FunctionAnalyzer::visitInit(const InitializerDefPtr& node) { FunctionSymbolPtr init = static_pointer_cast<SymboledInit>(node)->symbol; TypePtr funcType = init->getType(); SCOPED_SET(ctx->currentFunction, funcType); { InitializationTracer tracer(nullptr, InitializationTracer::Sequence); SCOPED_SET(ctx->currentInitializationTracer, &tracer); node->getBody()->accept(semanticAnalyzer); //check if some stored property is not initialized for(const SymbolPtr& storedProp : ctx->currentType->getDeclaredStoredProperties()) { if(!storedProp->hasFlags(SymbolFlagInitialized)) { error(node, Errors::E_PROPERTY_A_NOT_INITIALIZED, L"self." + storedProp->getName()); return; } } } if(node->hasModifier(DeclarationModifiers::Convenience)) { //convenience initializer must call designated initializer in all paths InitializerValidator validator(ctx, this); node->getBody()->accept(&validator); NodePtr refNode = validator.getRefNode() ? validator.getRefNode() : node; if(validator.getResult() & InitializerCoverMultiple) { error(refNode, Errors::E_SELF_INIT_CALLED_MULTIPLE_TIMES_IN_INITIALIZER); return; } switch(validator.getResult()) { case InitializerCoverNoResult: case InitializerCoverUnmatched: case InitializerCoverPartial: error(refNode, Errors::E_SELF_INIT_ISNT_CALLED_ON_ALL_PATHS_IN_DELEGATING_INITIALIZER); return; default: break; } } else { //designated initializer must call designated initializer if parent type has customized initializer bool hasCustomizedInitializer = false; if(ctx->currentType->getParentType()) { FunctionOverloadedSymbolPtr inits = ctx->currentType->getDeclaredInitializer(); if(inits) { for(const FunctionSymbolPtr& init : *inits) { if(!init->getType()->getParameters().empty()) { hasCustomizedInitializer = true; break; } } } } if(hasCustomizedInitializer) { InitializerValidator validator(ctx, this); node->getBody()->accept(&validator); NodePtr refNode = validator.getRefNode() ? validator.getRefNode() : node; if(validator.getResult() & InitializerCoverMultiple) { error(refNode, Errors::E_SUPER_INIT_CALLED_MULTIPLE_TIMES_IN_INITIALIZER); return; } switch(validator.getResult()) { case InitializerCoverNoResult: case InitializerCoverUnmatched: case InitializerCoverPartial: error(refNode, Errors::E_SUPER_INIT_ISNT_CALLED_BEFORE_RETURNING_FROM_INITIALIZER); return; default: break; } } } }