@@ -1330,6 +1330,77 @@ createDefaultConstructor(ClangImporter::Implementation &Impl,
1330
1330
return constructor;
1331
1331
}
1332
1332
1333
+ // / Synthesizer callback for the body of a struct value constructor.
1334
+ static std::pair<BraceStmt *, bool >
1335
+ synthesizeValueConstructorBody (AbstractFunctionDecl *afd, void *context) {
1336
+ auto constructor = cast<ConstructorDecl>(afd);
1337
+ ArrayRef<VarDecl *> members (static_cast <VarDecl **>(context) + 1 ,
1338
+ static_cast <uintptr_t *>(context)[0 ]);
1339
+
1340
+ ASTContext &ctx = constructor->getASTContext ();
1341
+
1342
+ // Assign all of the member variables appropriately.
1343
+ SmallVector<ASTNode, 4 > stmts;
1344
+
1345
+ auto *selfDecl = constructor->getImplicitSelfDecl ();
1346
+
1347
+ // To keep DI happy, initialize stored properties before computed.
1348
+ auto parameters = constructor->getParameters ();
1349
+ for (unsigned pass = 0 ; pass < 2 ; pass++) {
1350
+ unsigned paramPos = 0 ;
1351
+
1352
+ for (unsigned i = 0 , e = members.size (); i < e; i++) {
1353
+ auto var = members[i];
1354
+
1355
+ if (var->hasClangNode () &&
1356
+ isa<clang::IndirectFieldDecl>(var->getClangDecl ()))
1357
+ continue ;
1358
+
1359
+ if (var->hasStorage () == (pass != 0 )) {
1360
+ paramPos++;
1361
+ continue ;
1362
+ }
1363
+
1364
+ // Construct left-hand side.
1365
+ Expr *lhs = new (ctx) DeclRefExpr (selfDecl, DeclNameLoc (),
1366
+ /* Implicit=*/ true );
1367
+ lhs->setType (LValueType::get (selfDecl->getType ()));
1368
+
1369
+ auto semantics = (var->hasStorage ()
1370
+ ? AccessSemantics::DirectToStorage
1371
+ : AccessSemantics::Ordinary);
1372
+
1373
+ lhs = new (ctx) MemberRefExpr (lhs, SourceLoc (), var, DeclNameLoc (),
1374
+ /* Implicit=*/ true , semantics);
1375
+ lhs->setType (LValueType::get (var->getType ()));
1376
+
1377
+ // Construct right-hand side.
1378
+ auto rhs = new (ctx) DeclRefExpr (parameters->get (paramPos),
1379
+ DeclNameLoc (), /* Implicit=*/ true );
1380
+ rhs->setType (parameters->get (paramPos)->getType ());
1381
+
1382
+ // Add assignment.
1383
+ auto assign = new (ctx) AssignExpr (lhs, SourceLoc (), rhs,
1384
+ /* Implicit=*/ true );
1385
+ assign->setType (TupleType::getEmpty (ctx));
1386
+
1387
+ stmts.push_back (assign);
1388
+ paramPos++;
1389
+ }
1390
+ }
1391
+
1392
+ auto result = TupleExpr::createEmpty (ctx, SourceLoc (), SourceLoc (),
1393
+ /* Implicit=*/ true );
1394
+ result->setType (TupleType::getEmpty (ctx));
1395
+
1396
+ auto ret = new (ctx) ReturnStmt (SourceLoc (), result, /* Implicit=*/ true );
1397
+ stmts.push_back (ret);
1398
+
1399
+ // Create the function body.
1400
+ auto body = BraceStmt::create (ctx, SourceLoc (), stmts, SourceLoc ());
1401
+ return { body, /* isTypeChecked=*/ true };
1402
+ }
1403
+
1333
1404
// / Create a constructor that initializes a struct from its members.
1334
1405
static ConstructorDecl *
1335
1406
createValueConstructor (ClangImporter::Implementation &Impl,
@@ -1383,66 +1454,14 @@ createValueConstructor(ClangImporter::Implementation &Impl,
1383
1454
constructor->getAttrs ().add (new (context) TransparentAttr (/* implicit*/ true ));
1384
1455
1385
1456
if (wantBody) {
1386
- // Assign all of the member variables appropriately.
1387
- SmallVector<ASTNode, 4 > stmts;
1388
-
1389
- auto *selfDecl = constructor->getImplicitSelfDecl ();
1390
-
1391
- // To keep DI happy, initialize stored properties before computed.
1392
- for (unsigned pass = 0 ; pass < 2 ; pass++) {
1393
- unsigned paramPos = 0 ;
1394
-
1395
- for (unsigned i = 0 , e = members.size (); i < e; i++) {
1396
- auto var = members[i];
1397
-
1398
- if (var->hasClangNode () && isa<clang::IndirectFieldDecl>(var->getClangDecl ()))
1399
- continue ;
1400
-
1401
- if (var->hasStorage () == (pass != 0 )) {
1402
- paramPos++;
1403
- continue ;
1404
- }
1405
-
1406
- // Construct left-hand side.
1407
- Expr *lhs = new (context) DeclRefExpr (selfDecl, DeclNameLoc (),
1408
- /* Implicit=*/ true );
1409
- lhs->setType (LValueType::get (selfDecl->getType ()));
1410
-
1411
- auto semantics = (var->hasStorage ()
1412
- ? AccessSemantics::DirectToStorage
1413
- : AccessSemantics::Ordinary);
1414
-
1415
- lhs = new (context) MemberRefExpr (lhs, SourceLoc (), var, DeclNameLoc (),
1416
- /* Implicit=*/ true ,
1417
- semantics);
1418
- lhs->setType (LValueType::get (var->getType ()));
1419
-
1420
- // Construct right-hand side.
1421
- auto rhs = new (context) DeclRefExpr (valueParameters[paramPos],
1422
- DeclNameLoc (),
1423
- /* Implicit=*/ true );
1424
- rhs->setType (valueParameters[paramPos]->getType ());
1425
-
1426
- // Add assignment.
1427
- auto assign = new (context) AssignExpr (lhs, SourceLoc (), rhs,
1428
- /* Implicit=*/ true );
1429
- assign->setType (TupleType::getEmpty (context));
1430
-
1431
- stmts.push_back (assign);
1432
- paramPos++;
1433
- }
1434
- }
1435
-
1436
- auto result = TupleExpr::createEmpty (context, SourceLoc (), SourceLoc (),
1437
- /* Implicit=*/ true );
1438
- result->setType (TupleType::getEmpty (context));
1439
-
1440
- auto ret = new (context) ReturnStmt (SourceLoc (), result, /* Implicit=*/ true );
1441
- stmts.push_back (ret);
1442
-
1443
- // Create the function body.
1444
- auto body = BraceStmt::create (context, SourceLoc (), stmts, SourceLoc ());
1445
- constructor->setBody (body, AbstractFunctionDecl::BodyKind::TypeChecked);
1457
+ auto memberMemory =
1458
+ context.AllocateUninitialized <uintptr_t >(members.size () + 1 );
1459
+ memberMemory[0 ] = members.size ();
1460
+ for (unsigned i : indices (members)) {
1461
+ memberMemory[i+1 ] = reinterpret_cast <uintptr_t >(members[i]);
1462
+ }
1463
+ constructor->setBodySynthesizer (synthesizeValueConstructorBody,
1464
+ memberMemory.data ());
1446
1465
}
1447
1466
1448
1467
// We're done.
@@ -1523,12 +1542,12 @@ static void makeStructRawValued(
1523
1542
structDecl->addMember (
1524
1543
createValueConstructor (Impl, structDecl, var,
1525
1544
/* wantCtorParamNames=*/ false ,
1526
- /* wantBody=*/ !Impl. hasFinishedTypeChecking () ));
1545
+ /* wantBody=*/ true ));
1527
1546
1528
1547
auto *initRawValue =
1529
1548
createValueConstructor (Impl, structDecl, var,
1530
1549
/* wantCtorParamNames=*/ true ,
1531
- /* wantBody=*/ !Impl. hasFinishedTypeChecking () );
1550
+ /* wantBody=*/ true );
1532
1551
structDecl->addMember (initRawValue);
1533
1552
structDecl->addMember (patternBinding);
1534
1553
structDecl->addMember (var);
@@ -1653,19 +1672,16 @@ static void makeStructRawValuedWithBridge(
1653
1672
ctx, StaticSpellingKind::None, computedVarPattern, /* InitExpr*/ nullptr ,
1654
1673
structDecl);
1655
1674
1656
- // Don't bother synthesizing the body if we've already finished
1657
- // type-checking.
1658
- bool wantBody = !Impl.hasFinishedTypeChecking ();
1659
-
1660
1675
auto init = createRawValueBridgingConstructor (Impl, structDecl, computedVar,
1661
1676
storedVar,
1662
- /* wantLabel*/ true , wantBody);
1677
+ /* wantLabel*/ true ,
1678
+ /* wantBody*/ true );
1663
1679
1664
1680
ConstructorDecl *unlabeledCtor = nullptr ;
1665
1681
if (makeUnlabeledValueInit)
1666
1682
unlabeledCtor = createRawValueBridgingConstructor (
1667
1683
Impl, structDecl, computedVar, storedVar,
1668
- /* wantLabel*/ false , wantBody);
1684
+ /* wantLabel*/ false , /* wantBody*/ !Impl. hasFinishedTypeChecking () );
1669
1685
1670
1686
if (unlabeledCtor)
1671
1687
structDecl->addMember (unlabeledCtor);
@@ -3299,7 +3315,7 @@ namespace {
3299
3315
auto valueCtor =
3300
3316
createValueConstructor (Impl, result, VD,
3301
3317
/* want param names*/ true ,
3302
- /* wantBody=*/ !Impl. hasFinishedTypeChecking () );
3318
+ /* wantBody=*/ true );
3303
3319
ctors.push_back (valueCtor);
3304
3320
}
3305
3321
}
@@ -3318,11 +3334,10 @@ namespace {
3318
3334
//
3319
3335
// If we can completely represent the struct in SIL, leave the body
3320
3336
// implicit, otherwise synthesize one to call property setters.
3321
- bool wantBody = (hasUnreferenceableStorage &&
3322
- !Impl.hasFinishedTypeChecking ());
3323
- auto valueCtor = createValueConstructor (Impl, result, members,
3324
- /* want param names*/ true ,
3325
- /* want body*/ wantBody);
3337
+ auto valueCtor = createValueConstructor (
3338
+ Impl, result, members,
3339
+ /* want param names*/ true ,
3340
+ /* want body*/ hasUnreferenceableStorage);
3326
3341
if (!hasUnreferenceableStorage)
3327
3342
valueCtor->setIsMemberwiseInitializer ();
3328
3343
0 commit comments