Skip to content

Commit f7fc1ed

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
1 parent b327dbf commit f7fc1ed

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
@@ -213,16 +213,30 @@ class CCExprRemover: public ASTWalker, public ExprVisitor<CCExprRemover, Expr *>
213213
} else if (auto tuple = dyn_cast<TupleExpr>(E->getArg())) {
214214
lParenLoc = tuple->getLParenLoc();
215215
rParenLoc = tuple->getRParenLoc();
216+
217+
assert((!E->getUnlabeledTrailingClosureIndex().hasValue() ||
218+
(tuple->getNumElements() == E->getArgumentLabels().size() &&
219+
tuple->getNumElements() == E->getArgumentLabelLocs().size())) &&
220+
"CallExpr with trailing closure must have the same number of "
221+
"argument labels");
222+
assert(tuple->getNumElements() == E->getArgumentLabels().size());
223+
assert(tuple->getNumElements() == E->getArgumentLabelLocs().size() ||
224+
E->getArgumentLabelLocs().size() == 0);
225+
226+
bool hasArgumentLabelLocs = E->getArgumentLabelLocs().size() > 0;
227+
216228
for (unsigned i = 0, e = tuple->getNumElements(); i != e; ++i) {
217229
if (isa<CodeCompletionExpr>(tuple->getElement(i))) {
218230
removing = true;
219231
continue;
220232
}
221233

222-
if (i < E->getUnlabeledTrailingClosureIndex()) {
234+
if (!E->getUnlabeledTrailingClosureIndex().hasValue() ||
235+
i < *E->getUnlabeledTrailingClosureIndex()) {
223236
// Normal arguments.
224237
argLabels.push_back(E->getArgumentLabels()[i]);
225-
argLabelLocs.push_back(E->getArgumentLabelLocs()[i]);
238+
if (hasArgumentLabelLocs)
239+
argLabelLocs.push_back(E->getArgumentLabelLocs()[i]);
226240
args.push_back(tuple->getElement(i));
227241
} else {
228242
// Trailing closure arguments.
@@ -246,7 +260,20 @@ class CCExprRemover: public ASTWalker, public ExprVisitor<CCExprRemover, Expr *>
246260
}
247261

248262
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
249-
return {true, visit(E)};
263+
if (Removed)
264+
return {false, nullptr};
265+
E = visit(E);
266+
return {!Removed, E};
267+
}
268+
269+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
270+
if (Removed)
271+
return {false, nullptr};
272+
return {true, S};
273+
}
274+
275+
bool walkToDeclPre(Decl *D) override {
276+
return !Removed;
250277
}
251278
};
252279
}
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)