Skip to content

Commit 3cdfb57

Browse files
committed
[CodeCompletion] Fix a crash in CCExprRemover
- Handle cases where getArgumentLabelLocs().size() == 0 - Add some assertions to verify invariants - Explicit handling of 'llvm::Optional' for 'getUnlabeledTrailingClosureIndex()' - Avoid walking into nodes after the removing happens rdar://problem/65556791 (cherry picked from commit f7fc1ed)
1 parent ef596b5 commit 3cdfb57

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,16 +226,30 @@ class CCExprRemover: public ASTWalker, public ExprVisitor<CCExprRemover, Expr *>
226226
} else if (auto tuple = dyn_cast<TupleExpr>(E->getArg())) {
227227
lParenLoc = tuple->getLParenLoc();
228228
rParenLoc = tuple->getRParenLoc();
229+
230+
assert((!E->getUnlabeledTrailingClosureIndex().hasValue() ||
231+
(tuple->getNumElements() == E->getArgumentLabels().size() &&
232+
tuple->getNumElements() == E->getArgumentLabelLocs().size())) &&
233+
"CallExpr with trailing closure must have the same number of "
234+
"argument labels");
235+
assert(tuple->getNumElements() == E->getArgumentLabels().size());
236+
assert(tuple->getNumElements() == E->getArgumentLabelLocs().size() ||
237+
E->getArgumentLabelLocs().size() == 0);
238+
239+
bool hasArgumentLabelLocs = E->getArgumentLabelLocs().size() > 0;
240+
229241
for (unsigned i = 0, e = tuple->getNumElements(); i != e; ++i) {
230242
if (isa<CodeCompletionExpr>(tuple->getElement(i))) {
231243
removing = true;
232244
continue;
233245
}
234246

235-
if (i < E->getUnlabeledTrailingClosureIndex()) {
247+
if (!E->getUnlabeledTrailingClosureIndex().hasValue() ||
248+
i < *E->getUnlabeledTrailingClosureIndex()) {
236249
// Normal arguments.
237250
argLabels.push_back(E->getArgumentLabels()[i]);
238-
argLabelLocs.push_back(E->getArgumentLabelLocs()[i]);
251+
if (hasArgumentLabelLocs)
252+
argLabelLocs.push_back(E->getArgumentLabelLocs()[i]);
239253
args.push_back(tuple->getElement(i));
240254
} else {
241255
// Trailing closure arguments.
@@ -259,7 +273,20 @@ class CCExprRemover: public ASTWalker, public ExprVisitor<CCExprRemover, Expr *>
259273
}
260274

261275
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
262-
return {true, visit(E)};
276+
if (Removed)
277+
return {false, nullptr};
278+
E = visit(E);
279+
return {!Removed, E};
280+
}
281+
282+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
283+
if (Removed)
284+
return {false, nullptr};
285+
return {true, S};
286+
}
287+
288+
bool walkToDeclPre(Decl *D) override {
289+
return !Removed;
263290
}
264291
};
265292
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
2+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=B -source-filename=%s
3+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=C -source-filename=%s
4+
5+
func myFunc(_: Int, _: Undefined) {}
6+
7+
undefined {
8+
  myFunc($0, undefined)
9+
} #^A^#
10+
11+
undefined(x: 1) {
12+
  myFunc($0, undefined)
13+
} #^B^#
14+
15+
undefined(1, 2) {
16+
  myFunc { 1 }
17+
} #^C^#

0 commit comments

Comments
 (0)