Skip to content

Commit 57da0f5

Browse files
authored
Merge pull request #5323 from mxswd/fix-stmtconditionelement
2 parents b0a5669 + e75e3fe commit 57da0f5

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

lib/AST/Stmt.cpp

Lines changed: 9 additions & 6 deletions
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,7 @@ SourceLoc StmtConditionElement::getStartLoc() const {
321326
case StmtConditionElement::CK_Availability:
322327
return getAvailability()->getStartLoc();
323328
case StmtConditionElement::CK_PatternBinding:
324-
if (IntroducerLoc.isValid())
325-
return IntroducerLoc;
326-
return getPattern()->getStartLoc();
329+
return getSourceRange().Start;
327330
}
328331
}
329332

@@ -334,7 +337,7 @@ SourceLoc StmtConditionElement::getEndLoc() const {
334337
case StmtConditionElement::CK_Availability:
335338
return getAvailability()->getEndLoc();
336339
case StmtConditionElement::CK_PatternBinding:
337-
return getInitializer()->getEndLoc();
340+
return getSourceRange().End;
338341
}
339342
}
340343

unittests/AST/SourceLocTests.cpp

Lines changed: 59 additions & 0 deletions
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;
@@ -136,6 +138,63 @@ TEST(SourceLoc, AssignExpr) {
136138
EXPECT_EQ(SourceRange(), invalidAll->getSourceRange());
137139
}
138140

141+
TEST(SourceLoc, StmtConditionElement) {
142+
TestContext C;
143+
144+
// In a pattern binding statement condition element the SourceRange is only
145+
// valid iff the Initializer has a valid end loc and either:
146+
// a. the IntroducerLoc has a valid start loc
147+
// b. if the IntroducerLoc is invalid, the pattern has a valid start loc
148+
// If neither of these hold, source range must be invalid.
149+
150+
auto bufferID = C.Ctx.SourceMgr // 0123456789012345678901234567890
151+
.addMemBufferCopy("if let x = Optional.some(1) { }");
152+
SourceLoc start = C.Ctx.SourceMgr.getLocForBufferStart(bufferID);
153+
154+
auto vardecl = new (C.Ctx) VarDecl( false, true, start.getAdvancedLoc(7)
155+
, C.Ctx.getIdentifier("x")
156+
, Type()
157+
, nullptr);
158+
auto pattern = new (C.Ctx) NamedPattern(vardecl);
159+
auto init = new (C.Ctx) IntegerLiteralExpr( "1", start.getAdvancedLoc(25)
160+
, false);
161+
162+
// Case a, when the IntroducerLoc is valid.
163+
auto introducer = StmtConditionElement( start.getAdvancedLoc(3)
164+
, pattern, init);
165+
166+
EXPECT_EQ(start.getAdvancedLoc(3), introducer.getStartLoc());
167+
EXPECT_EQ(start.getAdvancedLoc(25), introducer.getEndLoc());
168+
EXPECT_EQ( SourceRange(start.getAdvancedLoc(3), start.getAdvancedLoc(25))
169+
, introducer.getSourceRange());
170+
171+
// Case b, when the IntroducerLoc is invalid, but the pattern has a valid loc.
172+
auto patternStmtCond = StmtConditionElement(SourceLoc(), pattern, init);
173+
174+
EXPECT_EQ(start.getAdvancedLoc(7), patternStmtCond.getStartLoc());
175+
EXPECT_EQ(start.getAdvancedLoc(25), patternStmtCond.getEndLoc());
176+
EXPECT_EQ( SourceRange(start.getAdvancedLoc(7), start.getAdvancedLoc(25))
177+
, patternStmtCond.getSourceRange());
178+
179+
// If the IntroducerLoc is valid but the stmt cond init is invalid.
180+
auto invalidInit = new (C.Ctx) IntegerLiteralExpr("1", SourceLoc(), false);
181+
auto introducerStmtInvalid = StmtConditionElement( start.getAdvancedLoc(3)
182+
, pattern, invalidInit);
183+
184+
EXPECT_EQ(SourceLoc(), introducerStmtInvalid.getStartLoc());
185+
EXPECT_EQ(SourceLoc(), introducerStmtInvalid.getEndLoc());
186+
EXPECT_EQ(SourceRange(), introducerStmtInvalid.getSourceRange());
187+
188+
// If the IntroducerLoc is invalid, the pattern is valid, but the stmt cond
189+
// init is invalid.
190+
auto patternStmtInvalid = StmtConditionElement( SourceLoc(), pattern
191+
, invalidInit);
192+
193+
EXPECT_EQ(SourceLoc(), patternStmtInvalid.getStartLoc());
194+
EXPECT_EQ(SourceLoc(), patternStmtInvalid.getEndLoc());
195+
EXPECT_EQ(SourceRange(), patternStmtInvalid.getSourceRange());
196+
}
197+
139198
TEST(SourceLoc, TupleExpr) {
140199
TestContext C;
141200

0 commit comments

Comments
 (0)