@@ -220,3 +220,125 @@ TEST_F(SemaTest, TestMultiStmtClosureBodyParentAndDepth) {
220220 ASSERT_EQ (cs.getParentExpr (result), closure);
221221 ASSERT_EQ (cs.getExprDepth (result), 1 );
222222}
223+
224+ TEST_F (SemaTest, TestIfExprLocator) {
225+ // Test to make sure we get the expected conjunction and locators.
226+
227+ // if true { 1 } else { 2 }
228+ auto *ifCond = new (Context) BooleanLiteralExpr (true , SourceLoc ());
229+ auto *thenBrace = BraceStmt::createImplicit (
230+ Context,
231+ {IntegerLiteralExpr::createFromUnsigned (Context, 1 , SourceLoc ())});
232+ auto *elseBrace = BraceStmt::createImplicit (
233+ Context,
234+ {IntegerLiteralExpr::createFromUnsigned (Context, 2 , SourceLoc ())});
235+ auto *ifStmt =
236+ new (Context) IfStmt (SourceLoc (), ifCond, thenBrace, SourceLoc (),
237+ elseBrace, /* implicit*/ true , Context);
238+ auto *ifExpr = SingleValueStmtExpr::createWithWrappedBranches (
239+ Context, ifStmt, DC, /* mustBeExpr*/ true );
240+
241+ SyntacticElementTarget target (ifExpr, DC, ContextualTypeInfo (),
242+ /* isDiscarded*/ true );
243+
244+ ConstraintSystem cs (DC, ConstraintSystemOptions ());
245+ auto hadError = cs.generateConstraints (target);
246+ ASSERT_FALSE (hadError);
247+
248+ auto *conjunction = &cs.getConstraints ().front ();
249+ ASSERT_EQ (conjunction->getKind (), ConstraintKind::Conjunction);
250+
251+ auto nested = conjunction->getNestedConstraints ();
252+ ASSERT_EQ (nested.size (), 4 );
253+
254+ auto *condConstraint = nested[0 ];
255+ auto *thenConstraint = nested[1 ];
256+ auto *elseConstraint = nested[2 ];
257+ auto *joinConstraint = nested[3 ];
258+
259+ auto *ifStmtLoc =
260+ cs.getConstraintLocator (ifExpr, LocatorPathElt::SyntacticElement (ifStmt));
261+
262+ auto *condLoc =
263+ cs.getConstraintLocator (ifStmtLoc, LocatorPathElt::Condition ());
264+ ASSERT_EQ (condConstraint->getLocator (), condLoc);
265+
266+ auto *thenLoc =
267+ cs.getConstraintLocator (ifStmtLoc, LocatorPathElt::TernaryBranch (true ));
268+ ASSERT_EQ (thenConstraint->getLocator (), thenLoc);
269+
270+ auto *elseLoc =
271+ cs.getConstraintLocator (ifStmtLoc, LocatorPathElt::TernaryBranch (false ));
272+ ASSERT_EQ (elseConstraint->getLocator (), elseLoc);
273+
274+ auto *joinLoc = cs.getConstraintLocator (
275+ ifStmtLoc,
276+ LocatorPathElt::SyntacticElement (joinConstraint->getSyntacticElement ()));
277+ ASSERT_EQ (joinConstraint->getLocator (), joinLoc);
278+ }
279+
280+ TEST_F (SemaTest, TestSwitchExprLocator) {
281+ // Test to make sure we get the expected conjunction and locators.
282+
283+ // case true: 1
284+ auto *trueBrace = BraceStmt::createImplicit (
285+ Context,
286+ {IntegerLiteralExpr::createFromUnsigned (Context, 1 , SourceLoc ())});
287+ auto *truePattern = ExprPattern::createImplicit (
288+ Context, new (Context) BooleanLiteralExpr (true , SourceLoc ()), DC);
289+ auto *trueCase =
290+ CaseStmt::create (Context, CaseParentKind::Switch, SourceLoc (),
291+ {CaseLabelItem (truePattern)}, SourceLoc (), SourceLoc (),
292+ trueBrace, /* caseBodyVars*/ llvm::None);
293+
294+ // case false: 2
295+ auto *falseBrace = BraceStmt::createImplicit (
296+ Context,
297+ {IntegerLiteralExpr::createFromUnsigned (Context, 2 , SourceLoc ())});
298+ auto *falsePattern = ExprPattern::createImplicit (
299+ Context, new (Context) BooleanLiteralExpr (false , SourceLoc ()), DC);
300+ auto *falseCase =
301+ CaseStmt::create (Context, CaseParentKind::Switch, SourceLoc (),
302+ {CaseLabelItem (falsePattern)}, SourceLoc (), SourceLoc (),
303+ falseBrace, /* caseBodyVars*/ llvm::None);
304+
305+ auto *subject = new (Context) BooleanLiteralExpr (true , SourceLoc ());
306+
307+ // switch true { case true: 1 case false: 2 }
308+ auto *switchStmt = SwitchStmt::create (LabeledStmtInfo (), SourceLoc (), subject,
309+ SourceLoc (), {trueCase, falseCase},
310+ SourceLoc (), SourceLoc (), Context);
311+ auto *switchExpr = SingleValueStmtExpr::createWithWrappedBranches (
312+ Context, switchStmt, DC, /* mustBeExpr*/ true );
313+
314+ SyntacticElementTarget target (switchExpr, DC, ContextualTypeInfo (),
315+ /* isDiscarded*/ true );
316+
317+ ConstraintSystem cs (DC, ConstraintSystemOptions ());
318+ auto hadError = cs.generateConstraints (target);
319+ ASSERT_FALSE (hadError);
320+
321+ auto *conjunction = &cs.getConstraints ().front ();
322+ ASSERT_EQ (conjunction->getKind (), ConstraintKind::Conjunction);
323+
324+ auto nested = conjunction->getNestedConstraints ();
325+ ASSERT_EQ (nested.size (), 4 );
326+
327+ auto *subjectConstraint = nested[0 ];
328+ auto *trueConstraint = nested[1 ];
329+ auto *falseConstraint = nested[2 ];
330+ auto *joinConstraint = nested[3 ];
331+
332+ auto *switchStmtLoc = cs.getConstraintLocator (
333+ switchExpr, LocatorPathElt::SyntacticElement (switchStmt));
334+
335+ // These currently all get the switch statement locator.
336+ ASSERT_EQ (subjectConstraint->getLocator (), switchStmtLoc);
337+ ASSERT_EQ (trueConstraint->getLocator (), switchStmtLoc);
338+ ASSERT_EQ (falseConstraint->getLocator (), switchStmtLoc);
339+
340+ auto *joinLoc = cs.getConstraintLocator (
341+ switchStmtLoc,
342+ LocatorPathElt::SyntacticElement (joinConstraint->getSyntacticElement ()));
343+ ASSERT_EQ (joinConstraint->getLocator (), joinLoc);
344+ }
0 commit comments