Skip to content

Commit ab8b4a2

Browse files
authored
Merge pull request #62637 from ahoppen/ahoppen/stmtcondition-at-loc
[Sema] Teach typeCheckASTNodeAtLoc to check StmtConditionElement
2 parents 5469760 + 07eb645 commit ab8b4a2

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,12 @@ void StmtChecker::typeCheckASTNode(ASTNode &node) {
18361836
return;
18371837
}
18381838

1839+
if (auto *Cond = node.dyn_cast<StmtConditionElement *>()) {
1840+
bool IsFalsable; // ignored
1841+
TypeChecker::typeCheckStmtConditionElement(*Cond, IsFalsable, DC);
1842+
return;
1843+
}
1844+
18391845
llvm_unreachable("Type checking null ASTNode");
18401846
}
18411847

@@ -2163,6 +2169,19 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
21632169
class ASTNodeFinder : public ASTWalker {
21642170
SourceManager &SM;
21652171
SourceLoc Loc;
2172+
2173+
/// When the \c ASTNode that we want to check was found inside a brace
2174+
/// statement, we need to store a *reference* to the element in the
2175+
/// \c BraceStmt. When the brace statement gets type checked for result
2176+
/// builders its elements will be updated in-place, which makes
2177+
/// \c FoundNodeRef now point to the type-checked replacement node. We need
2178+
/// this behavior.
2179+
///
2180+
/// But for all other cases, we just want to store a plain \c ASTNode. To
2181+
/// make sure we free the \c ASTNode again, we store it in
2182+
/// \c FoundNodeStorage and set \c FoundNodeRef to point to
2183+
/// \c FoundNodeStorage.
2184+
ASTNode FoundNodeStorage;
21662185
ASTNode *FoundNode = nullptr;
21672186

21682187
/// The innermost DeclContext that contains \c FoundNode.
@@ -2230,6 +2249,20 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
22302249
}
22312250
// Already walked into.
22322251
return Action::Stop();
2252+
} else if (auto Conditional = dyn_cast<LabeledConditionalStmt>(S)) {
2253+
for (StmtConditionElement &Cond : Conditional->getCond()) {
2254+
if (SM.isBeforeInBuffer(Loc, Cond.getStartLoc())) {
2255+
break;
2256+
}
2257+
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, Cond.getEndLoc());
2258+
if (SM.isBeforeInBuffer(endLoc, Loc) || endLoc == Loc) {
2259+
continue;
2260+
}
2261+
2262+
FoundNodeStorage = ASTNode(&Cond);
2263+
FoundNode = &FoundNodeStorage;
2264+
return Action::Stop();
2265+
}
22332266
}
22342267

22352268
return Action::Continue(S);
@@ -2270,7 +2303,8 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
22702303
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, D->getEndLoc());
22712304
if (!(SM.isBeforeInBuffer(endLoc, Loc) || endLoc == Loc)) {
22722305
if (!isa<TopLevelCodeDecl>(D)) {
2273-
FoundNode = new ASTNode(D);
2306+
FoundNodeStorage = ASTNode(D);
2307+
FoundNode = &FoundNodeStorage;
22742308
}
22752309
}
22762310
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
func foo() {
2+
let myVar: Int? = 2
3+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):10 %s -- %s | %FileCheck %s
4+
if let myVar = myVar {
5+
}
6+
}
7+
8+
// CHECK: source.lang.swift.decl.var.local (4:10-4:15)
9+
// CHECK-NEXT: myVar
10+
// CHECK-NEXT: s:24cursor_on_if_let_binding3fooyyF5myVarL0_Sivp
11+
// CHECK-NEXT: source.lang.swift
12+
// CHECK-NEXT: Int

0 commit comments

Comments
 (0)