return [[t()]] -- or, for a class derived from a parent with a user ctor, emit the let-self / call Parent`Parent(self) / return self chain body.
| 311 | // return [[t()]] -- or, for a class derived from a parent with a user ctor, |
| 312 | // emit the let-self / call Parent`Parent(self) / return self chain body. |
| 313 | FunctionPtr makeConstructor ( Structure * str, bool isPrivate ) { |
| 314 | auto fn = new Function(); |
| 315 | fn->generated = true; |
| 316 | fn->privateFunction = isPrivate; |
| 317 | fn->name = str->name; |
| 318 | fn->at = fn->atDecl = str->at; |
| 319 | fn->result = new TypeDecl(str); |
| 320 | if ( str->isClass ) { |
| 321 | fn->isClassMethod = true; |
| 322 | fn->classParent = str; |
| 323 | DAS_ASSERT(fn->classParent); |
| 324 | } |
| 325 | if ( str->macroInterface ) fn->macroFunction = true; |
| 326 | auto block = new ExprBlock(); |
| 327 | block->at = str->at; |
| 328 | // For a synth ctor of a class whose ancestor chain has a user ctor, emit a |
| 329 | // chain body that calls the deepest USER ctor directly -- but only when |
| 330 | // (a) the class itself has no user ctor (true implicit-default case) |
| 331 | // AND (b) the chain target has a 0-arg-callable user ctor we can reach. |
| 332 | // Otherwise fall through to the plain field-init body. The latter preserves |
| 333 | // the long-standing `new Class(field=val)` named-init idiom for classes |
| 334 | // with user ctors. The lint catches missing super in the user's own ctor, |
| 335 | // which is the only path that actually runs invariants. |
| 336 | Structure * chainTarget = nullptr; |
| 337 | if ( !str->hasUserConstructor() ) { |
| 338 | auto * cand = findChainCtorAncestor(str); |
| 339 | if ( cand && cand->hasUserDefaultConstructor() ) { |
| 340 | chainTarget = cand; |
| 341 | } |
| 342 | } |
| 343 | if ( chainTarget ) { |
| 344 | // let self = [[Derived()]] |
| 345 | auto makeT = new ExprMakeStruct(str->at); |
| 346 | makeT->alwaysSafe = true; |
| 347 | makeT->useInitializer = true; |
| 348 | makeT->nativeClassInitializer = true; |
| 349 | makeT->makeType = new TypeDecl(str); |
| 350 | makeT->structs.push_back(new MakeStruct()); |
| 351 | auto letS = new ExprLet(); |
| 352 | letS->at = str->at; |
| 353 | letS->atInit = str->at; |
| 354 | letS->visibility = str->at; |
| 355 | letS->alwaysSafe = true; // local class variable |
| 356 | auto argT = new TypeDecl(str); |
| 357 | argT->constant = false; |
| 358 | auto argV = new Variable(); |
| 359 | argV->name = "self"; |
| 360 | argV->type = argT; |
| 361 | argV->at = str->at; |
| 362 | argV->generated = true; |
| 363 | argV->capture_as_ref = true; |
| 364 | argV->init = makeT; |
| 365 | argV->init_via_move = true; |
| 366 | letS->variables.push_back(argV); |
| 367 | block->list.push_back(letS); |
| 368 | // call ChainTarget`ChainTarget(self) -- closest ancestor with user ctor |
| 369 | auto cll = new ExprCall(str->at, chainTarget->name + "`" + chainTarget->name); |
| 370 | cll->arguments.push_back(new ExprVar(str->at, "self")); |
no test coverage detected