@@ -493,6 +493,19 @@ DerivedConformance::createBuiltinCall(ASTContext &ctx,
493493 return call;
494494}
495495
496+ CallExpr *DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr (
497+ ASTContext &ctx) {
498+ FuncDecl *diagnoseDecl = ctx.getDiagnoseUnavailableCodeReached ();
499+ auto diagnoseDeclRefExpr =
500+ new (ctx) DeclRefExpr (diagnoseDecl, DeclNameLoc (), true );
501+ diagnoseDeclRefExpr->setType (diagnoseDecl->getInterfaceType ());
502+ auto argList = ArgumentList::createImplicit (ctx, {});
503+ auto callExpr = CallExpr::createImplicit (ctx, diagnoseDeclRefExpr, argList);
504+ callExpr->setType (ctx.getNeverType ());
505+ callExpr->setThrows (false );
506+ return callExpr;
507+ }
508+
496509AccessorDecl *DerivedConformance::
497510addGetterToReadOnlyDerivedProperty (VarDecl *property,
498511 Type propertyContextType) {
@@ -761,6 +774,13 @@ DeclRefExpr *DerivedConformance::convertEnumToIndex(SmallVectorImpl<ASTNode> &st
761774 unsigned index = 0 ;
762775 SmallVector<ASTNode, 4 > cases;
763776 for (auto elt : enumDecl->getAllElements ()) {
777+ if (auto *unavailableElementCase =
778+ DerivedConformance::unavailableEnumElementCaseStmt (enumType, elt,
779+ funcDecl)) {
780+ cases.push_back (unavailableElementCase);
781+ continue ;
782+ }
783+
764784 // generate: case .<Case>:
765785 auto pat = new (C)
766786 EnumElementPattern (TypeExpr::createImplicit (enumType, C), SourceLoc (),
@@ -907,6 +927,52 @@ Pattern *DerivedConformance::enumElementPayloadSubpattern(
907927 return ParenPattern::createImplicit (C, letPattern);
908928}
909929
930+ CaseStmt *DerivedConformance::unavailableEnumElementCaseStmt (
931+ Type enumType, EnumElementDecl *elt, DeclContext *parentDC,
932+ unsigned subPatternCount) {
933+ assert (subPatternCount > 0 );
934+
935+ ASTContext &C = parentDC->getASTContext ();
936+ auto availableAttr = elt->getAttrs ().getUnavailable (C);
937+ if (!availableAttr)
938+ return nullptr ;
939+
940+ if (!availableAttr->isUnconditionallyUnavailable ())
941+ return nullptr ;
942+
943+ auto createElementPattern = [&]() -> EnumElementPattern * {
944+ // .<elt>
945+ EnumElementPattern *eltPattern = new (C) EnumElementPattern (
946+ TypeExpr::createImplicit (enumType, C), SourceLoc (), DeclNameLoc (),
947+ DeclNameRef (elt->getBaseIdentifier ()), elt, nullptr , /* DC*/ parentDC);
948+ eltPattern->setImplicit ();
949+ return eltPattern;
950+ };
951+
952+ Pattern *labelItemPattern;
953+ if (subPatternCount > 1 ) {
954+ SmallVector<TuplePatternElt, 2 > tuplePatternElts;
955+ for (unsigned i = 0 ; i < subPatternCount; i++) {
956+ tuplePatternElts.push_back (TuplePatternElt (createElementPattern ()));
957+ }
958+
959+ // (.<elt>, ..., .<elt>)
960+ auto caseTuplePattern = TuplePattern::createImplicit (C, tuplePatternElts);
961+ caseTuplePattern->setImplicit ();
962+ labelItemPattern = caseTuplePattern;
963+ } else {
964+ labelItemPattern = createElementPattern ();
965+ }
966+
967+ auto labelItem = CaseLabelItem (labelItemPattern);
968+ auto *callExpr =
969+ DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr (C);
970+ auto body = BraceStmt::create (C, SourceLoc (), {callExpr}, SourceLoc ());
971+ return CaseStmt::create (C, CaseParentKind::Switch, SourceLoc (), labelItem,
972+ SourceLoc (), SourceLoc (), body, {},
973+ /* implicit*/ true );
974+ }
975+
910976// / Creates a named variable based on a prefix character and a numeric index.
911977// / \p prefixChar The prefix character for the variable's name.
912978// / \p index The numeric index to append to the variable's name.
0 commit comments