Skip to content

Commit 4ec661d

Browse files
committed
Fix the SourceRange of an AssignExpr with an implicit source.
Fixed by Maxwell Swadling, unit test by me.
1 parent 2fdd456 commit 4ec661d

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

Diff for: include/swift/AST/Expr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -4270,7 +4270,7 @@ class AssignExpr : public Expr {
42704270
}
42714271
SourceLoc getEndLoc() const {
42724272
if (!isFolded()) return EqualLoc;
4273-
return Src->getEndLoc();
4273+
return (Src->isImplicit() ? Dest->getEndLoc() : Src->getEndLoc());
42744274
}
42754275

42764276
/// True if the node has been processed by binary expression folding.

Diff for: unittests/AST/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_swift_unittest(SwiftASTTests
22
OverrideTests.cpp
3+
SourceLocTests.cpp
34
TestContext.cpp
45
VersionRangeLattice.cpp
56
)

Diff for: unittests/AST/SourceLocTests.cpp

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//===--- SourceLocTests.cpp - Tests for source locations of AST nodes -----===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "TestContext.h"
14+
#include "swift/AST/Expr.h"
15+
#include "gtest/gtest.h"
16+
17+
using namespace swift;
18+
using namespace swift::unittest;
19+
20+
namespace swift {
21+
void PrintTo(SourceLoc loc, std::ostream *os) {
22+
*os << loc.getOpaquePointerValue();
23+
if (loc.isValid())
24+
*os << " '" << *(char *)loc.getOpaquePointerValue() << "'";
25+
}
26+
27+
void PrintTo(SourceRange range, std::ostream *os) {
28+
PrintTo(range.Start, os);
29+
*os << " - ";
30+
PrintTo(range.End, os);
31+
}
32+
} // end namespace swift
33+
34+
TEST(SourceLoc, AssignExpr) {
35+
TestContext C;
36+
37+
// 0123456789012
38+
auto bufferID = C.Ctx.SourceMgr.addMemBufferCopy("aa.bb = cc.dd");
39+
SourceLoc start = C.Ctx.SourceMgr.getLocForBufferStart(bufferID);
40+
41+
auto destBase = new (C.Ctx) UnresolvedDeclRefExpr(
42+
C.Ctx.getIdentifier("aa"),
43+
DeclRefKind::Ordinary,
44+
DeclNameLoc(start));
45+
auto dest = new (C.Ctx) UnresolvedDotExpr(
46+
destBase,
47+
start.getAdvancedLoc(2),
48+
C.Ctx.getIdentifier("bb"),
49+
DeclNameLoc(start.getAdvancedLoc(3)),
50+
/*implicit*/false);
51+
52+
auto sourceBase = new (C.Ctx) UnresolvedDeclRefExpr(
53+
C.Ctx.getIdentifier("cc"),
54+
DeclRefKind::Ordinary,
55+
DeclNameLoc(start.getAdvancedLoc(8)));
56+
auto source = new (C.Ctx) UnresolvedDotExpr(
57+
sourceBase,
58+
start.getAdvancedLoc(10),
59+
C.Ctx.getIdentifier("dd"),
60+
DeclNameLoc(start.getAdvancedLoc(11)),
61+
/*implicit*/false);
62+
63+
auto invalid = new (C.Ctx) UnresolvedDeclRefExpr(
64+
C.Ctx.getIdentifier("invalid"),
65+
DeclRefKind::Ordinary,
66+
DeclNameLoc());
67+
68+
auto complete = new (C.Ctx) AssignExpr(dest, start.getAdvancedLoc(6), source,
69+
/*implicit*/false);
70+
EXPECT_EQ(start, complete->getStartLoc());
71+
EXPECT_EQ(start.getAdvancedLoc(6), complete->getEqualLoc());
72+
EXPECT_EQ(start.getAdvancedLoc(6), complete->getLoc());
73+
EXPECT_EQ(start.getAdvancedLoc(11), complete->getEndLoc());
74+
EXPECT_EQ(SourceRange(start, start.getAdvancedLoc(11)),
75+
complete->getSourceRange());
76+
77+
auto invalidSource = new (C.Ctx) AssignExpr(dest, SourceLoc(), invalid,
78+
/*implicit*/true);
79+
EXPECT_EQ(start, invalidSource->getStartLoc());
80+
EXPECT_EQ(SourceLoc(), invalidSource->getEqualLoc());
81+
EXPECT_EQ(SourceLoc(), invalidSource->getLoc());
82+
EXPECT_EQ(start.getAdvancedLoc(3), invalidSource->getEndLoc());
83+
EXPECT_EQ(SourceRange(start, start.getAdvancedLoc(3)),
84+
invalidSource->getSourceRange());
85+
86+
auto invalidDest = new (C.Ctx) AssignExpr(invalid, SourceLoc(), source,
87+
/*implicit*/true);
88+
EXPECT_EQ(start.getAdvancedLoc(8), invalidDest->getStartLoc());
89+
EXPECT_EQ(SourceLoc(), invalidDest->getEqualLoc());
90+
EXPECT_EQ(SourceLoc(), invalidDest->getLoc());
91+
EXPECT_EQ(start.getAdvancedLoc(11), invalidDest->getEndLoc());
92+
EXPECT_EQ(SourceRange(start.getAdvancedLoc(8), start.getAdvancedLoc(11)),
93+
invalidDest->getSourceRange());
94+
95+
auto invalidAll = new (C.Ctx) AssignExpr(invalid, SourceLoc(), invalid,
96+
/*implicit*/true);
97+
EXPECT_EQ(SourceLoc(), invalidAll->getStartLoc());
98+
EXPECT_EQ(SourceLoc(), invalidAll->getEqualLoc());
99+
EXPECT_EQ(SourceLoc(), invalidAll->getLoc());
100+
EXPECT_EQ(SourceLoc(), invalidAll->getEndLoc());
101+
EXPECT_EQ(SourceRange(), invalidAll->getSourceRange());
102+
}

0 commit comments

Comments
 (0)