Skip to content

Commit b6c3ca0

Browse files
authored
Merge pull request #23801 from gottesmm/pr-56c61430037696146352efbfcedf418a94036015
[silgenpattern] Fix two ASAN errors.
2 parents 5150981 + 564b4fc commit b6c3ca0

File tree

7 files changed

+120
-40
lines changed

7 files changed

+120
-40
lines changed

include/swift/AST/Stmt.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,15 +1055,26 @@ class CaseStmt final
10551055
return UnknownAttrLoc.isValid();
10561056
}
10571057

1058-
Optional<ArrayRef<VarDecl *>> getCaseBodyVariables() const {
1059-
if (!CaseBodyVariables)
1060-
return None;
1058+
/// Return an ArrayRef containing the case body variables of this CaseStmt.
1059+
///
1060+
/// Asserts if case body variables was not explicitly initialized. In contexts
1061+
/// where one wants a non-asserting version, \see
1062+
/// getCaseBodyVariablesOrEmptyArray.
1063+
ArrayRef<VarDecl *> getCaseBodyVariables() const {
10611064
ArrayRef<VarDecl *> a = *CaseBodyVariables;
10621065
return a;
10631066
}
10641067

1065-
Optional<MutableArrayRef<VarDecl *>> getCaseBodyVariables() {
1066-
return CaseBodyVariables;
1068+
bool hasCaseBodyVariables() const { return CaseBodyVariables.hasValue(); }
1069+
1070+
/// Return an MutableArrayRef containing the case body variables of this
1071+
/// CaseStmt.
1072+
///
1073+
/// Asserts if case body variables was not explicitly initialized. In contexts
1074+
/// where one wants a non-asserting version, \see
1075+
/// getCaseBodyVariablesOrEmptyArray.
1076+
MutableArrayRef<VarDecl *> getCaseBodyVariables() {
1077+
return *CaseBodyVariables;
10671078
}
10681079

10691080
ArrayRef<VarDecl *> getCaseBodyVariablesOrEmptyArray() const {

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,13 +1622,13 @@ class PrintStmt : public StmtVisitor<PrintStmt> {
16221622
if (S->hasUnknownAttr())
16231623
OS << " @unknown";
16241624

1625-
if (auto caseBodyVars = S->getCaseBodyVariables()) {
1625+
if (S->hasCaseBodyVariables()) {
16261626
OS << '\n';
16271627
OS.indent(Indent + 2);
16281628
PrintWithColorRAII(OS, ParenthesisColor) << '(';
16291629
PrintWithColorRAII(OS, StmtColor) << "case_body_variables";
16301630
OS << '\n';
1631-
for (auto *vd : *caseBodyVars) {
1631+
for (auto *vd : S->getCaseBodyVariables()) {
16321632
OS.indent(2);
16331633
// TODO: Printing a var decl does an Indent ... dump(vd) ... '\n'. We
16341634
// should see if we can factor this dumping so that the caller of

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5094,7 +5094,7 @@ NullablePtr<VarDecl> VarDecl::getCorrespondingCaseBodyVariable() const {
50945094

50955095
// A var decl associated with a case stmt implies that the case stmt has body
50965096
// var decls. So we can access the optional value here without worry.
5097-
auto caseBodyVars = *caseStmt->getCaseBodyVariables();
5097+
auto caseBodyVars = caseStmt->getCaseBodyVariables();
50985098
auto result = llvm::find_if(caseBodyVars, [&](VarDecl *caseBodyVar) {
50995099
return caseBodyVar->getName() == name;
51005100
});

lib/AST/NameLookup.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2349,10 +2349,8 @@ void FindLocalVal::visitCaseStmt(CaseStmt *S) {
23492349
}
23502350

23512351
if (!inPatterns && !items.empty()) {
2352-
if (auto caseBodyVars = S->getCaseBodyVariables()) {
2353-
for (auto *vd : *caseBodyVars) {
2354-
checkValueDecl(vd, DeclVisibilityKind::LocalVariable);
2355-
}
2352+
for (auto *vd : S->getCaseBodyVariablesOrEmptyArray()) {
2353+
checkValueDecl(vd, DeclVisibilityKind::LocalVariable);
23562354
}
23572355
}
23582356
visit(S->getBody());

lib/SILGen/SILGenPattern.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,12 +2332,8 @@ void PatternMatchEmission::initSharedCaseBlockDest(CaseStmt *caseBlock,
23322332
auto *block = SGF.createBasicBlock();
23332333
result.first->second.first = block;
23342334

2335-
// Add args for any pattern variables
2336-
auto caseBodyVars = caseBlock->getCaseBodyVariables();
2337-
if (!caseBodyVars)
2338-
return;
2339-
2340-
for (auto *vd : *caseBodyVars) {
2335+
// Add args for any pattern variables if we have any.
2336+
for (auto *vd : caseBlock->getCaseBodyVariablesOrEmptyArray()) {
23412337
if (!vd->hasName())
23422338
continue;
23432339

@@ -2365,14 +2361,10 @@ void PatternMatchEmission::emitAddressOnlyAllocations() {
23652361
for (auto &entry : SharedCases) {
23662362
CaseStmt *caseBlock = entry.first;
23672363

2368-
auto caseBodyVars = caseBlock->getCaseBodyVariables();
2369-
if (!caseBodyVars)
2370-
continue;
2371-
23722364
// If we have a shared case with bound decls, setup the arguments for the
23732365
// shared block by emitting the temporary allocation used for the arguments
23742366
// of the shared block.
2375-
for (auto *vd : *caseBodyVars) {
2367+
for (auto *vd : caseBlock->getCaseBodyVariablesOrEmptyArray()) {
23762368
if (!vd->hasName())
23772369
continue;
23782370

@@ -2436,8 +2428,7 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
24362428
assert(SGF.getCleanupsDepth() == PatternMatchStmtDepth);
24372429
SWIFT_DEFER { assert(SGF.getCleanupsDepth() == PatternMatchStmtDepth); };
24382430

2439-
auto caseBodyVars = caseBlock->getCaseBodyVariables();
2440-
if (!caseBodyVars) {
2431+
if (!caseBlock->hasCaseBodyVariables()) {
24412432
emitCaseBody(caseBlock);
24422433
continue;
24432434
}
@@ -2448,7 +2439,7 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
24482439
// args needing Cleanup will get that as well.
24492440
Scope scope(SGF.Cleanups, CleanupLocation(caseBlock));
24502441
unsigned argIndex = 0;
2451-
for (auto *vd : *caseBodyVars) {
2442+
for (auto *vd : caseBlock->getCaseBodyVariables()) {
24522443
if (!vd->hasName())
24532444
continue;
24542445

@@ -2606,14 +2597,14 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26062597
if (!row.hasFallthroughTo() && caseBlock->getCaseLabelItems().size() == 1) {
26072598
// If we have case body vars, set them up to point at the matching var
26082599
// decls.
2609-
if (auto caseBodyVars = caseBlock->getCaseBodyVariables()) {
2600+
if (caseBlock->hasCaseBodyVariables()) {
26102601
// Since we know that we only have one case label item, grab its pattern
26112602
// vars and use that to update expected with the right SILValue.
26122603
//
26132604
// TODO: Do we need a copy here?
26142605
SmallVector<VarDecl *, 4> patternVars;
26152606
row.getCasePattern()->collectVariables(patternVars);
2616-
for (auto *expected : *caseBodyVars) {
2607+
for (auto *expected : caseBlock->getCaseBodyVariables()) {
26172608
if (!expected->hasName())
26182609
continue;
26192610
for (auto *vd : patternVars) {
@@ -2622,7 +2613,8 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26222613
}
26232614

26242615
// Ok, we found a match. Update the VarLocs for the case block.
2625-
SGF.VarLocs[expected] = SGF.VarLocs[vd];
2616+
auto v = SGF.VarLocs[vd];
2617+
SGF.VarLocs[expected] = v;
26262618
}
26272619
}
26282620
}
@@ -2639,8 +2631,7 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26392631

26402632
// If we do not have any bound decls, we do not need to setup any
26412633
// variables. Just jump to the shared destination.
2642-
auto caseBodyVars = caseBlock->getCaseBodyVariables();
2643-
if (!caseBodyVars) {
2634+
if (!caseBlock->hasCaseBodyVariables()) {
26442635
// Don't emit anything yet, we emit it at the cleanup level of the switch
26452636
// statement.
26462637
JumpDest sharedDest = emission.getSharedCaseBlockDest(caseBlock);
@@ -2657,7 +2648,7 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26572648
SILModule &M = SGF.F.getModule();
26582649
SmallVector<VarDecl *, 4> patternVars;
26592650
row.getCasePattern()->collectVariables(patternVars);
2660-
for (auto *expected : *caseBodyVars) {
2651+
for (auto *expected : caseBlock->getCaseBodyVariables()) {
26612652
if (!expected->hasName())
26622653
continue;
26632654
for (auto *var : patternVars) {
@@ -2844,8 +2835,7 @@ void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {
28442835

28452836
// If our destination case doesn't have any bound decls, there is no rebinding
28462837
// to do. Just jump to the shared dest.
2847-
auto destCaseBodyVars = destCaseStmt->getCaseBodyVariables();
2848-
if (!destCaseBodyVars) {
2838+
if (!destCaseStmt->hasCaseBodyVariables()) {
28492839
Cleanups.emitBranchAndCleanups(sharedDest, S);
28502840
return;
28512841
}
@@ -2855,13 +2845,13 @@ void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {
28552845
SmallVector<SILValue, 4> args;
28562846
CaseStmt *fallthroughSourceStmt = S->getFallthroughSource();
28572847

2858-
for (auto *expected : *destCaseBodyVars) {
2848+
for (auto *expected : destCaseStmt->getCaseBodyVariables()) {
28592849
if (!expected->hasName())
28602850
continue;
28612851

28622852
// The type checker enforces that if our destination case has variables then
28632853
// our fallthrough source must as well.
2864-
for (auto *var : *fallthroughSourceStmt->getCaseBodyVariables()) {
2854+
for (auto *var : fallthroughSourceStmt->getCaseBodyVariables()) {
28652855
if (!var->hasName() || var->getName() != expected->getName()) {
28662856
continue;
28672857
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,10 +2414,8 @@ class VarDeclUsageChecker : public ASTWalker {
24142414

24152415
// Make sure that we setup our case body variables.
24162416
if (auto *caseStmt = dyn_cast<CaseStmt>(S)) {
2417-
if (auto caseBoundDecls = caseStmt->getCaseBodyVariables()) {
2418-
for (auto *vd : *caseBoundDecls) {
2419-
VarDecls[vd] |= 0;
2420-
}
2417+
for (auto *vd : caseStmt->getCaseBodyVariablesOrEmptyArray()) {
2418+
VarDecls[vd] |= 0;
24212419
}
24222420
}
24232421

test/SILGen/switch.swift

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,3 +1500,86 @@ func nonTrivialLoadableFallthroughCallee2(_ e : MultipleNonTrivialCaseEnum) {
15001500
}
15011501
}
15021502

1503+
// Make sure that we do not crash while emitting this code.
1504+
//
1505+
// DISCUSSION: The original crash was due to us performing an assignment/lookup
1506+
// on the VarLocs DenseMap in the same statement. This was caught be an
1507+
// asanified compiler. This test is just to make sure we do not regress.
1508+
enum Storage {
1509+
case empty
1510+
case single(Int)
1511+
case pair(Int, Int)
1512+
case array([Int])
1513+
1514+
subscript(range: [Int]) -> Storage {
1515+
get {
1516+
return .empty
1517+
}
1518+
set {
1519+
switch self {
1520+
case .empty:
1521+
break
1522+
case .single(let index):
1523+
break
1524+
case .pair(let first, let second):
1525+
switch (range[0], range[1]) {
1526+
case (0, 0):
1527+
switch newValue {
1528+
case .empty:
1529+
break
1530+
case .single(let other):
1531+
break
1532+
case .pair(let otherFirst, let otherSecond):
1533+
break
1534+
case .array(let other):
1535+
break
1536+
}
1537+
break
1538+
case (0, 1):
1539+
switch newValue {
1540+
case .empty:
1541+
break
1542+
case .single(let other):
1543+
break
1544+
case .pair(let otherFirst, let otherSecond):
1545+
break
1546+
case .array(let other):
1547+
break
1548+
}
1549+
break
1550+
case (0, 2):
1551+
break
1552+
case (1, 2):
1553+
switch newValue {
1554+
case .empty:
1555+
break
1556+
case .single(let other):
1557+
break
1558+
case .pair(let otherFirst, let otherSecond):
1559+
break
1560+
case .array(let other):
1561+
self = .array([first] + other)
1562+
}
1563+
break
1564+
case (2, 2):
1565+
switch newValue {
1566+
case .empty:
1567+
break
1568+
case .single(let other):
1569+
break
1570+
case .pair(let otherFirst, let otherSecond):
1571+
break
1572+
case .array(let other):
1573+
self = .array([first, second] + other)
1574+
}
1575+
break
1576+
default:
1577+
let r = range
1578+
}
1579+
case .array(let indexes):
1580+
break
1581+
}
1582+
}
1583+
}
1584+
}
1585+

0 commit comments

Comments
 (0)