mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[AST] Introduce CaseStmt::createImplicit
This allows us to re-use the same logic to create the case body variables.
This commit is contained in:
@@ -1243,13 +1243,17 @@ public:
|
||||
ArrayRef<CaseLabelItem> CaseLabelItems,
|
||||
BraceStmt *Body);
|
||||
|
||||
static CaseStmt *
|
||||
createImplicit(ASTContext &ctx, CaseParentKind parentKind,
|
||||
ArrayRef<CaseLabelItem> caseLabelItems, BraceStmt *body,
|
||||
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
|
||||
|
||||
static CaseStmt *
|
||||
create(ASTContext &C, CaseParentKind ParentKind, SourceLoc ItemIntroducerLoc,
|
||||
ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
|
||||
SourceLoc ItemTerminatorLoc, BraceStmt *Body,
|
||||
ArrayRef<VarDecl *> CaseBodyVariables,
|
||||
std::optional<bool> Implicit = std::nullopt,
|
||||
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
|
||||
ArrayRef<VarDecl *> CaseBodyVariables, std::optional<bool> Implicit,
|
||||
NullablePtr<FallthroughStmt> fallthroughStmt);
|
||||
|
||||
CaseParentKind getParentKind() const { return ParentKind; }
|
||||
|
||||
|
||||
@@ -897,10 +897,22 @@ CaseStmt *CaseStmt::createParsedDoCatch(ASTContext &ctx, SourceLoc catchLoc,
|
||||
}
|
||||
|
||||
CaseStmt *
|
||||
CaseStmt::create(ASTContext &ctx, CaseParentKind ParentKind, SourceLoc caseLoc,
|
||||
CaseStmt::createImplicit(ASTContext &ctx, CaseParentKind parentKind,
|
||||
ArrayRef<CaseLabelItem> caseLabelItems,
|
||||
SourceLoc unknownAttrLoc, SourceLoc colonLoc, BraceStmt *body,
|
||||
ArrayRef<VarDecl *> caseVarDecls, std::optional<bool> implicit,
|
||||
BraceStmt *body,
|
||||
NullablePtr<FallthroughStmt> fallthroughStmt) {
|
||||
auto caseVarDecls = getCaseVarDecls(ctx, caseLabelItems);
|
||||
return create(ctx, parentKind, /*catchLoc*/ SourceLoc(), caseLabelItems,
|
||||
/*unknownAttrLoc*/ SourceLoc(), /*colonLoc*/ SourceLoc(), body,
|
||||
caseVarDecls, /*implicit*/ true, fallthroughStmt);
|
||||
}
|
||||
|
||||
CaseStmt *CaseStmt::create(ASTContext &ctx, CaseParentKind ParentKind,
|
||||
SourceLoc caseLoc,
|
||||
ArrayRef<CaseLabelItem> caseLabelItems,
|
||||
SourceLoc unknownAttrLoc, SourceLoc colonLoc,
|
||||
BraceStmt *body, ArrayRef<VarDecl *> caseVarDecls,
|
||||
std::optional<bool> implicit,
|
||||
NullablePtr<FallthroughStmt> fallthroughStmt) {
|
||||
void *mem =
|
||||
ctx.Allocate(totalSizeToAlloc<FallthroughStmt *, CaseLabelItem>(
|
||||
|
||||
@@ -805,9 +805,8 @@ DeclRefExpr *DerivedConformance::convertEnumToIndex(SmallVectorImpl<ASTNode> &st
|
||||
assignExpr->setType(TupleType::getEmpty(C));
|
||||
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(assignExpr),
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
/*case body vardecls*/ std::nullopt));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
// generate: switch enumVar { }
|
||||
@@ -967,9 +966,7 @@ CaseStmt *DerivedConformance::unavailableEnumElementCaseStmt(
|
||||
auto *callExpr =
|
||||
DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr(C);
|
||||
auto body = BraceStmt::create(C, SourceLoc(), {callExpr}, SourceLoc());
|
||||
return CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(), labelItem,
|
||||
SourceLoc(), SourceLoc(), body, {},
|
||||
/*implicit*/ true);
|
||||
return CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body);
|
||||
}
|
||||
|
||||
/// Creates a named variable based on a prefix character and a numeric index.
|
||||
|
||||
@@ -946,27 +946,10 @@ createEnumSwitch(ASTContext &C, DeclContext *DC, Expr *expr, EnumDecl *enumDecl,
|
||||
// .<elt>(let a0, let a1, ...)
|
||||
SmallVector<VarDecl *, 3> payloadVars;
|
||||
Pattern *subpattern = nullptr;
|
||||
ArrayRef<VarDecl *> caseBodyVarDecls;
|
||||
|
||||
if (createSubpattern) {
|
||||
subpattern = DerivedConformance::enumElementPayloadSubpattern(
|
||||
elt, 'a', DC, payloadVars, /* useLabels */ true);
|
||||
|
||||
auto hasBoundDecls = !payloadVars.empty();
|
||||
if (hasBoundDecls) {
|
||||
// We allocated a direct copy of our var decls for the case
|
||||
// body.
|
||||
auto copy = C.Allocate<VarDecl *>(payloadVars.size());
|
||||
for (unsigned i : indices(payloadVars)) {
|
||||
auto *vOld = payloadVars[i];
|
||||
auto *vNew = new (C) VarDecl(
|
||||
/*IsStatic*/ false, vOld->getIntroducer(), vOld->getNameLoc(),
|
||||
vOld->getName(), vOld->getDeclContext());
|
||||
vNew->setImplicit();
|
||||
copy[i] = vNew;
|
||||
}
|
||||
caseBodyVarDecls = copy;
|
||||
}
|
||||
}
|
||||
|
||||
// CodingKeys.x
|
||||
@@ -985,10 +968,8 @@ createEnumSwitch(ASTContext &C, DeclContext *DC, Expr *expr, EnumDecl *enumDecl,
|
||||
subpattern, DC);
|
||||
|
||||
auto labelItem = CaseLabelItem(pat);
|
||||
auto stmt =
|
||||
CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(), labelItem,
|
||||
SourceLoc(), SourceLoc(), caseBody,
|
||||
caseBodyVarDecls);
|
||||
auto stmt = CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem,
|
||||
caseBody);
|
||||
cases.push_back(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,10 +222,8 @@ deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
|
||||
auto *returnStmt = ReturnStmt::createImplicit(C, caseValue);
|
||||
auto *caseBody = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(),
|
||||
caseBody,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
|
||||
labelItem, caseBody));
|
||||
}
|
||||
|
||||
auto *selfRef = DerivedConformance::createSelfDeclRef(strValDecl);
|
||||
@@ -292,9 +290,8 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
|
||||
|
||||
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(assignment),
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
auto *anyPat = AnyPattern::createImplicit(C);
|
||||
@@ -303,10 +300,8 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
|
||||
auto *dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
|
||||
auto *dfltBody = BraceStmt::create(C, SourceLoc(), ASTNode(dfltReturnStmt),
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
dfltLabelItem, SourceLoc(), SourceLoc(),
|
||||
dfltBody,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
|
||||
dfltLabelItem, dfltBody));
|
||||
|
||||
auto *stringValueDecl = initDecl->getParameters()->get(0);
|
||||
auto *stringValueRef = new (C) DeclRefExpr(stringValueDecl, DeclNameLoc(),
|
||||
|
||||
@@ -127,23 +127,6 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
|
||||
auto *rhsElemPat = EnumElementPattern::createImplicit(
|
||||
enumType, elt, rhsSubpattern, /*DC*/ ltDecl);
|
||||
|
||||
auto hasBoundDecls = !lhsPayloadVars.empty();
|
||||
ArrayRef<VarDecl *> caseBodyVarDecls;
|
||||
if (hasBoundDecls) {
|
||||
// We allocated a direct copy of our lhs var decls for the case
|
||||
// body.
|
||||
auto copy = C.Allocate<VarDecl *>(lhsPayloadVars.size());
|
||||
for (unsigned i : indices(lhsPayloadVars)) {
|
||||
auto *vOld = lhsPayloadVars[i];
|
||||
auto *vNew = new (C) VarDecl(
|
||||
/*IsStatic*/ false, vOld->getIntroducer(),
|
||||
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
|
||||
vNew->setImplicit();
|
||||
copy[i] = vNew;
|
||||
}
|
||||
caseBodyVarDecls = copy;
|
||||
}
|
||||
|
||||
// case (.<elt>(let l0, let l1, ...), .<elt>(let r0, let r1, ...))
|
||||
auto caseTuplePattern = TuplePattern::createImplicit(C, {
|
||||
TuplePatternElt(lhsElemPat), TuplePatternElt(rhsElemPat) });
|
||||
@@ -177,9 +160,8 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
|
||||
|
||||
auto body = BraceStmt::create(C, SourceLoc(), statementsInCase,
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
caseBodyVarDecls));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
// default: result = <enum index>(lhs) < <enum index>(rhs)
|
||||
@@ -190,10 +172,8 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
|
||||
auto defaultPattern = AnyPattern::createImplicit(C);
|
||||
auto defaultItem = CaseLabelItem::getDefault(defaultPattern);
|
||||
auto body = deriveBodyComparable_enum_noAssociatedValues_lt(ltDecl, nullptr).first;
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
defaultItem, SourceLoc(), SourceLoc(),
|
||||
body,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, defaultItem, body));
|
||||
}
|
||||
|
||||
// switch (a, b) { <case statements> }
|
||||
|
||||
@@ -193,23 +193,6 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
|
||||
auto *rhsElemPat = EnumElementPattern::createImplicit(
|
||||
enumType, elt, rhsSubpattern, /*DC*/ eqDecl);
|
||||
|
||||
auto hasBoundDecls = !lhsPayloadVars.empty();
|
||||
ArrayRef<VarDecl *> caseBodyVarDecls;
|
||||
if (hasBoundDecls) {
|
||||
// We allocated a direct copy of our lhs var decls for the case
|
||||
// body.
|
||||
auto copy = C.Allocate<VarDecl *>(lhsPayloadVars.size());
|
||||
for (unsigned i : indices(lhsPayloadVars)) {
|
||||
auto *vOld = lhsPayloadVars[i];
|
||||
auto *vNew = new (C) VarDecl(
|
||||
/*IsStatic*/ false, vOld->getIntroducer(),
|
||||
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
|
||||
vNew->setImplicit();
|
||||
copy[i] = vNew;
|
||||
}
|
||||
caseBodyVarDecls = copy;
|
||||
}
|
||||
|
||||
// case (.<elt>(let l0, let l1, ...), .<elt>(let r0, let r1, ...))
|
||||
auto caseTuplePattern = TuplePattern::createImplicit(C, {
|
||||
TuplePatternElt(lhsElemPat), TuplePatternElt(rhsElemPat) });
|
||||
@@ -244,9 +227,8 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
|
||||
|
||||
auto body = BraceStmt::create(C, SourceLoc(), statementsInCase,
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
caseBodyVarDecls));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
// default: result = false
|
||||
@@ -261,10 +243,8 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
|
||||
auto *returnStmt = ReturnStmt::createImplicit(C, falseExpr);
|
||||
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
|
||||
SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
defaultItem, SourceLoc(), SourceLoc(),
|
||||
body,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, defaultItem, body));
|
||||
}
|
||||
|
||||
// switch (a, b) { <case statements> }
|
||||
@@ -735,26 +715,9 @@ deriveBodyHashable_enum_hasAssociatedValues_hashInto(
|
||||
statements.emplace_back(ASTNode(combineExpr));
|
||||
}
|
||||
|
||||
auto hasBoundDecls = !payloadVars.empty();
|
||||
ArrayRef<VarDecl *> caseBodyVarDecls;
|
||||
if (hasBoundDecls) {
|
||||
auto copy = C.Allocate<VarDecl *>(payloadVars.size());
|
||||
for (unsigned i : indices(payloadVars)) {
|
||||
auto *vOld = payloadVars[i];
|
||||
auto *vNew = new (C) VarDecl(
|
||||
/*IsStatic*/ false, vOld->getIntroducer(),
|
||||
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
|
||||
vNew->setImplicit();
|
||||
copy[i] = vNew;
|
||||
}
|
||||
caseBodyVarDecls = copy;
|
||||
}
|
||||
|
||||
auto body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
caseBodyVarDecls,
|
||||
/*implicit*/ true));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
// generate: switch enumVar { }
|
||||
|
||||
@@ -129,9 +129,8 @@ deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl, void *) {
|
||||
auto body = BraceStmt::create(C, SourceLoc(),
|
||||
ASTNode(returnStmt), SourceLoc());
|
||||
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
labelItem, SourceLoc(), SourceLoc(), body,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(
|
||||
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
|
||||
}
|
||||
|
||||
auto selfRef = DerivedConformance::createSelfDeclRef(toRawDecl);
|
||||
@@ -363,10 +362,8 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) {
|
||||
stmts, SourceLoc());
|
||||
|
||||
// cases.append("case \(litPat): \(body)")
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
CaseLabelItem(litPat), SourceLoc(),
|
||||
SourceLoc(), body,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
|
||||
CaseLabelItem(litPat), body));
|
||||
++Idx;
|
||||
}
|
||||
|
||||
@@ -376,10 +373,8 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) {
|
||||
auto dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
|
||||
auto dfltBody = BraceStmt::create(C, SourceLoc(),
|
||||
ASTNode(dfltReturnStmt), SourceLoc());
|
||||
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
|
||||
dfltLabelItem, SourceLoc(), SourceLoc(),
|
||||
dfltBody,
|
||||
/*case body var decls*/ std::nullopt));
|
||||
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
|
||||
dfltLabelItem, dfltBody));
|
||||
|
||||
auto rawDecl = initDecl->getParameters()->get(0);
|
||||
auto rawRef = new (C) DeclRefExpr(rawDecl, DeclNameLoc(), /*implicit*/true);
|
||||
|
||||
@@ -286,10 +286,8 @@ TEST_F(SemaTest, TestSwitchExprLocator) {
|
||||
{IntegerLiteralExpr::createFromUnsigned(Context, 1, SourceLoc())});
|
||||
auto *truePattern = ExprPattern::createImplicit(
|
||||
Context, new (Context) BooleanLiteralExpr(true, SourceLoc()), DC);
|
||||
auto *trueCase =
|
||||
CaseStmt::create(Context, CaseParentKind::Switch, SourceLoc(),
|
||||
{CaseLabelItem(truePattern)}, SourceLoc(), SourceLoc(),
|
||||
trueBrace, /*caseBodyVars*/ std::nullopt);
|
||||
auto *trueCase = CaseStmt::createImplicit(
|
||||
Context, CaseParentKind::Switch, {CaseLabelItem(truePattern)}, trueBrace);
|
||||
|
||||
// case false: 2
|
||||
auto *falseBrace = BraceStmt::createImplicit(
|
||||
@@ -298,9 +296,8 @@ TEST_F(SemaTest, TestSwitchExprLocator) {
|
||||
auto *falsePattern = ExprPattern::createImplicit(
|
||||
Context, new (Context) BooleanLiteralExpr(false, SourceLoc()), DC);
|
||||
auto *falseCase =
|
||||
CaseStmt::create(Context, CaseParentKind::Switch, SourceLoc(),
|
||||
{CaseLabelItem(falsePattern)}, SourceLoc(), SourceLoc(),
|
||||
falseBrace, /*caseBodyVars*/ std::nullopt);
|
||||
CaseStmt::createImplicit(Context, CaseParentKind::Switch,
|
||||
{CaseLabelItem(falsePattern)}, falseBrace);
|
||||
|
||||
auto *subject = new (Context) BooleanLiteralExpr(true, SourceLoc());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user