@@ -459,6 +459,55 @@ static bool isNSDictionaryMethod(const clang::ObjCMethodDecl *MD,
459
459
return true ;
460
460
}
461
461
462
+ // / Synthesize the body of \c init?(rawValue:RawType) for an imported enum.
463
+ static std::pair<BraceStmt *, bool >
464
+ synthesizeEnumRawValueConstructorBody (AbstractFunctionDecl *afd,
465
+ void *context) {
466
+ ASTContext &ctx = afd->getASTContext ();
467
+ auto ctorDecl = cast<ConstructorDecl>(afd);
468
+ auto enumDecl = static_cast <EnumDecl *>(context);
469
+ auto selfDecl = ctorDecl->getImplicitSelfDecl ();
470
+ auto selfRef = new (ctx) DeclRefExpr (selfDecl, DeclNameLoc (),
471
+ /* implicit*/ true );
472
+ selfRef->setType (LValueType::get (selfDecl->getType ()));
473
+
474
+ auto param = ctorDecl->getParameters ()->get (0 );
475
+ auto paramRef = new (ctx) DeclRefExpr (param, DeclNameLoc (),
476
+ /* implicit*/ true );
477
+ paramRef->setType (param->getType ());
478
+
479
+ auto reinterpretCast
480
+ = cast<FuncDecl>(
481
+ getBuiltinValueDecl (ctx, ctx.getIdentifier (" reinterpretCast" )));
482
+ auto rawTy = enumDecl->getRawType ();
483
+ auto enumTy = enumDecl->getDeclaredInterfaceType ();
484
+ SubstitutionMap subMap =
485
+ SubstitutionMap::get (reinterpretCast->getGenericSignature (),
486
+ { rawTy, enumTy }, { });
487
+ ConcreteDeclRef concreteDeclRef (reinterpretCast, subMap);
488
+ auto reinterpretCastRef
489
+ = new (ctx) DeclRefExpr (concreteDeclRef, DeclNameLoc (), /* implicit*/ true );
490
+ reinterpretCastRef->setType (FunctionType::get ({FunctionType::Param (rawTy)},
491
+ enumTy));
492
+
493
+ auto reinterpreted = CallExpr::createImplicit (ctx, reinterpretCastRef,
494
+ { paramRef }, { Identifier () });
495
+ reinterpreted->setType (enumTy);
496
+ reinterpreted->setThrows (false );
497
+
498
+ auto assign = new (ctx) AssignExpr (selfRef, SourceLoc (), reinterpreted,
499
+ /* implicit*/ true );
500
+ assign->setType (TupleType::getEmpty (ctx));
501
+
502
+ auto result = TupleExpr::createEmpty (ctx, SourceLoc (), SourceLoc (),
503
+ /* Implicit=*/ true );
504
+ auto ret = new (ctx) ReturnStmt (SourceLoc (), result, /* Implicit=*/ true );
505
+
506
+ auto body = BraceStmt::create (ctx, SourceLoc (), {assign, ret}, SourceLoc (),
507
+ /* implicit*/ true );
508
+ return { body, /* isTypeChecked=*/ true };
509
+ }
510
+
462
511
// Build the init(rawValue:) initializer for an imported NS_ENUM.
463
512
// enum NSSomeEnum: RawType {
464
513
// init?(rawValue: RawType) {
@@ -472,8 +521,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
472
521
EnumDecl *enumDecl) {
473
522
ASTContext &C = Impl.SwiftContext ;
474
523
auto rawTy = enumDecl->getRawType ();
475
- auto enumTy = enumDecl->getDeclaredInterfaceType ();
476
-
524
+
477
525
auto param = new (C) ParamDecl (VarDecl::Specifier::Default, SourceLoc (),
478
526
SourceLoc (), C.Id_rawValue ,
479
527
SourceLoc (), C.Id_rawValue ,
@@ -495,49 +543,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
495
543
496
544
ctorDecl->computeType ();
497
545
ctorDecl->setValidationToChecked ();
498
-
499
- // Don't bother synthesizing the body if we've already finished type-checking.
500
- if (Impl.hasFinishedTypeChecking ())
501
- return ctorDecl;
502
-
503
- auto selfDecl = ctorDecl->getImplicitSelfDecl ();
504
- auto selfRef = new (C) DeclRefExpr (selfDecl, DeclNameLoc (), /* implicit*/ true );
505
- selfRef->setType (LValueType::get (selfDecl->getType ()));
506
-
507
- auto paramRef = new (C) DeclRefExpr (param, DeclNameLoc (),
508
- /* implicit*/ true );
509
- paramRef->setType (param->getType ());
510
-
511
- auto reinterpretCast
512
- = cast<FuncDecl>(
513
- getBuiltinValueDecl (C, C.getIdentifier (" reinterpretCast" )));
514
- SubstitutionMap subMap =
515
- SubstitutionMap::get (reinterpretCast->getGenericSignature (),
516
- { rawTy, enumTy }, { });
517
- ConcreteDeclRef concreteDeclRef (reinterpretCast, subMap);
518
- auto reinterpretCastRef
519
- = new (C) DeclRefExpr (concreteDeclRef, DeclNameLoc (), /* implicit*/ true );
520
- reinterpretCastRef->setType (FunctionType::get ({FunctionType::Param (rawTy)},
521
- enumTy));
522
-
523
- auto reinterpreted = CallExpr::createImplicit (C, reinterpretCastRef,
524
- { paramRef }, { Identifier () });
525
- reinterpreted->setType (enumTy);
526
- reinterpreted->setThrows (false );
527
-
528
- auto assign = new (C) AssignExpr (selfRef, SourceLoc (), reinterpreted,
529
- /* implicit*/ true );
530
- assign->setType (TupleType::getEmpty (C));
531
-
532
- auto result = TupleExpr::createEmpty (C, SourceLoc (), SourceLoc (),
533
- /* Implicit=*/ true );
534
- auto ret = new (C) ReturnStmt (SourceLoc (), result, /* Implicit=*/ true );
535
-
536
- auto body = BraceStmt::create (C, SourceLoc (), {assign, ret}, SourceLoc (),
537
- /* implicit*/ true );
538
-
539
- ctorDecl->setBody (body, AbstractFunctionDecl::BodyKind::TypeChecked);
540
-
546
+ ctorDecl->setBodySynthesizer (synthesizeEnumRawValueConstructorBody, enumDecl);
541
547
return ctorDecl;
542
548
}
543
549
0 commit comments