Skip to content

Commit 5999021

Browse files
committed
Fixed a bug in StmtConditionElement::getSourceRange where it would create invalid source ranges
This bug was causing an assert.
1 parent 3adbab3 commit 5999021

File tree

2 files changed

+89
-5
lines changed

2 files changed

+89
-5
lines changed

lib/AST/Stmt.cpp

+30-5
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,13 @@ SourceRange StmtConditionElement::getSourceRange() const {
309309
Start = IntroducerLoc;
310310
else
311311
Start = getPattern()->getStartLoc();
312-
313-
return SourceRange(Start, getInitializer()->getEndLoc());
312+
313+
SourceLoc End = getInitializer()->getEndLoc();
314+
if (Start.isValid() && End.isValid()) {
315+
return SourceRange(Start, End);
316+
} else {
317+
return SourceRange();
318+
}
314319
}
315320
}
316321

@@ -321,9 +326,18 @@ SourceLoc StmtConditionElement::getStartLoc() const {
321326
case StmtConditionElement::CK_Availability:
322327
return getAvailability()->getStartLoc();
323328
case StmtConditionElement::CK_PatternBinding:
329+
SourceLoc Start;
324330
if (IntroducerLoc.isValid())
325-
return IntroducerLoc;
326-
return getPattern()->getStartLoc();
331+
Start = IntroducerLoc;
332+
else
333+
Start = getPattern()->getStartLoc();
334+
335+
SourceLoc End = getInitializer()->getEndLoc();
336+
if (Start.isValid() && End.isValid()) {
337+
return Start;
338+
} else {
339+
return SourceLoc();
340+
}
327341
}
328342
}
329343

@@ -334,7 +348,18 @@ SourceLoc StmtConditionElement::getEndLoc() const {
334348
case StmtConditionElement::CK_Availability:
335349
return getAvailability()->getEndLoc();
336350
case StmtConditionElement::CK_PatternBinding:
337-
return getInitializer()->getEndLoc();
351+
SourceLoc Start;
352+
if (IntroducerLoc.isValid())
353+
Start = IntroducerLoc;
354+
else
355+
Start = getPattern()->getStartLoc();
356+
357+
SourceLoc End = getInitializer()->getEndLoc();
358+
if (Start.isValid() && End.isValid()) {
359+
return End;
360+
} else {
361+
return SourceLoc();
362+
}
338363
}
339364
}
340365

unittests/AST/SourceLocTests.cpp

+59
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include "TestContext.h"
1414
#include "swift/AST/Expr.h"
15+
#include "swift/AST/Pattern.h"
16+
#include "swift/AST/Stmt.h"
1517
#include "gtest/gtest.h"
1618

1719
using namespace swift;
@@ -101,6 +103,63 @@ TEST(SourceLoc, AssignExpr) {
101103
EXPECT_EQ(SourceRange(), invalidAll->getSourceRange());
102104
}
103105

106+
TEST(SourceLoc, StmtConditionElement) {
107+
TestContext C;
108+
109+
// In a pattern binding statement condition element the SourceRange is only
110+
// valid iff the Initializer has a valid end loc and either:
111+
// a. the IntroducerLoc has a valid start loc
112+
// b. if the IntroducerLoc is invalid, the pattern has a valid start loc
113+
// If neither of these hold, source range must be invalid.
114+
115+
auto bufferID = C.Ctx.SourceMgr // 0123456789012345678901234567890
116+
.addMemBufferCopy("if let x = Optional.some(1) { }");
117+
SourceLoc start = C.Ctx.SourceMgr.getLocForBufferStart(bufferID);
118+
119+
auto vardecl = new (C.Ctx) VarDecl( false, true, start.getAdvancedLoc(7)
120+
, C.Ctx.getIdentifier("x")
121+
, Type()
122+
, nullptr);
123+
auto pattern = new (C.Ctx) NamedPattern(vardecl);
124+
auto init = new (C.Ctx) IntegerLiteralExpr( "1", start.getAdvancedLoc(25)
125+
, false);
126+
127+
// Case a, when the IntroducerLoc is valid.
128+
auto introducer = StmtConditionElement( start.getAdvancedLoc(3)
129+
, pattern, init);
130+
131+
EXPECT_EQ(start.getAdvancedLoc(3), introducer.getStartLoc());
132+
EXPECT_EQ(start.getAdvancedLoc(25), introducer.getEndLoc());
133+
EXPECT_EQ( SourceRange(start.getAdvancedLoc(3), start.getAdvancedLoc(25))
134+
, introducer.getSourceRange());
135+
136+
// Case b, when the IntroducerLoc is invalid, but the pattern has a valid loc.
137+
auto patternStmtCond = StmtConditionElement(SourceLoc(), pattern, init);
138+
139+
EXPECT_EQ(start.getAdvancedLoc(7), patternStmtCond.getStartLoc());
140+
EXPECT_EQ(start.getAdvancedLoc(25), patternStmtCond.getEndLoc());
141+
EXPECT_EQ( SourceRange(start.getAdvancedLoc(7), start.getAdvancedLoc(25))
142+
, patternStmtCond.getSourceRange());
143+
144+
// If the IntroducerLoc is valid but the stmt cond init is invalid.
145+
auto invalidInit = new (C.Ctx) IntegerLiteralExpr("1", SourceLoc(), false);
146+
auto introducerStmtInvalid = StmtConditionElement( start.getAdvancedLoc(3)
147+
, pattern, invalidInit);
148+
149+
EXPECT_EQ(SourceLoc(), introducerStmtInvalid.getStartLoc());
150+
EXPECT_EQ(SourceLoc(), introducerStmtInvalid.getEndLoc());
151+
EXPECT_EQ(SourceRange(), introducerStmtInvalid.getSourceRange());
152+
153+
// If the IntroducerLoc is invalid, the pattern is valid, but the stmt cond
154+
// init is invalid.
155+
auto patternStmtInvalid = StmtConditionElement( SourceLoc(), pattern
156+
, invalidInit);
157+
158+
EXPECT_EQ(SourceLoc(), patternStmtInvalid.getStartLoc());
159+
EXPECT_EQ(SourceLoc(), patternStmtInvalid.getEndLoc());
160+
EXPECT_EQ(SourceRange(), patternStmtInvalid.getSourceRange());
161+
}
162+
104163
TEST(SourceLoc, TupleExpr) {
105164
TestContext C;
106165

0 commit comments

Comments
 (0)