@@ -1390,7 +1390,23 @@ ParserResult<Stmt> Parser::parseStmtIf(LabeledStmtInfo LabelInfo) {
1390
1390
// by a conditional binding. The else branch does *not* see these variables.
1391
1391
{
1392
1392
Scope S (this , ScopeKind::IfVars);
1393
-
1393
+
1394
+ auto recoverWithCond = [&](ParserStatus Status,
1395
+ StmtCondition Condition) -> ParserResult<Stmt> {
1396
+ if (Condition.empty ()) {
1397
+ SmallVector<StmtConditionElement, 1 > ConditionElems;
1398
+ ConditionElems.emplace_back (new (Context) ErrorExpr (IfLoc));
1399
+ Condition = Context.AllocateCopy (ConditionElems);
1400
+ }
1401
+ auto EndLoc = Condition.back ().getEndLoc ();
1402
+ return makeParserResult (
1403
+ Status,
1404
+ new (Context) IfStmt (
1405
+ LabelInfo, IfLoc, Condition,
1406
+ BraceStmt::create (Context, EndLoc, {}, EndLoc, /* implicit=*/ true ),
1407
+ SourceLoc (), nullptr ));
1408
+ };
1409
+
1394
1410
if (Tok.is (tok::l_brace)) {
1395
1411
SourceLoc LBraceLoc = Tok.getLoc ();
1396
1412
diagnose (IfLoc, diag::missing_condition_after_if)
@@ -1401,17 +1417,14 @@ ParserResult<Stmt> Parser::parseStmtIf(LabeledStmtInfo LabelInfo) {
1401
1417
} else {
1402
1418
Status |= parseStmtCondition (Condition, diag::expected_condition_if,
1403
1419
StmtKind::If);
1404
- if (Status.isError () || Status.hasCodeCompletion ()) {
1405
- // FIXME: better recovery
1406
- return makeParserResult<Stmt>(Status, nullptr );
1407
- }
1420
+ if (Status.isError () || Status.hasCodeCompletion ())
1421
+ return recoverWithCond (Status, Condition);
1408
1422
}
1409
1423
1410
1424
NormalBody = parseBraceItemList (diag::expected_lbrace_after_if);
1411
- if (NormalBody.isNull ())
1412
- return nullptr ; // FIXME: better recovery
1413
-
1414
1425
Status |= NormalBody;
1426
+ if (NormalBody.isNull ())
1427
+ return recoverWithCond (Status, Condition);
1415
1428
}
1416
1429
1417
1430
// The else branch, if any, is outside of the scope of the condition.
@@ -1441,7 +1454,22 @@ ParserResult<Stmt> Parser::parseStmtGuard() {
1441
1454
ParserStatus Status;
1442
1455
StmtCondition Condition;
1443
1456
ParserResult<BraceStmt> Body;
1444
-
1457
+
1458
+ auto recoverWithCond = [&](ParserStatus Status,
1459
+ StmtCondition Condition) -> ParserResult<Stmt> {
1460
+ if (Condition.empty ()) {
1461
+ SmallVector<StmtConditionElement, 1 > ConditionElems;
1462
+ ConditionElems.emplace_back (new (Context) ErrorExpr (GuardLoc));
1463
+ Condition = Context.AllocateCopy (ConditionElems);
1464
+ }
1465
+ auto EndLoc = Condition.back ().getEndLoc ();
1466
+ return makeParserResult (
1467
+ Status,
1468
+ new (Context) GuardStmt (
1469
+ GuardLoc, Condition,
1470
+ BraceStmt::create (Context, EndLoc, {}, EndLoc, /* implicit=*/ true )));
1471
+ };
1472
+
1445
1473
if (Tok.is (tok::l_brace)) {
1446
1474
SourceLoc LBraceLoc = Tok.getLoc ();
1447
1475
diagnose (GuardLoc, diag::missing_condition_after_guard)
@@ -1454,15 +1482,15 @@ ParserResult<Stmt> Parser::parseStmtGuard() {
1454
1482
StmtKind::Guard);
1455
1483
if (Status.isError () || Status.hasCodeCompletion ()) {
1456
1484
// FIXME: better recovery
1457
- return makeParserResult<Stmt> (Status, nullptr );
1485
+ return recoverWithCond (Status, Condition );
1458
1486
}
1459
1487
}
1460
1488
1461
1489
// Parse the 'else'. If it is missing, and if the following token isn't a {
1462
1490
// then the parser is hopelessly lost - just give up instead of spewing.
1463
1491
if (parseToken (tok::kw_else, diag::expected_else_after_guard) &&
1464
1492
Tok.isNot (tok::l_brace))
1465
- return makeParserError ( );
1493
+ return recoverWithCond (Status, Condition );
1466
1494
1467
1495
// Before parsing the body, disable all of the bound variables so that they
1468
1496
// cannot be used unbound.
@@ -1479,8 +1507,8 @@ ParserResult<Stmt> Parser::parseStmtGuard() {
1479
1507
1480
1508
Body = parseBraceItemList (diag::expected_lbrace_after_guard);
1481
1509
if (Body.isNull ())
1482
- return nullptr ; // FIXME: better recovery
1483
-
1510
+ return recoverWithCond (Status, Condition);
1511
+
1484
1512
Status |= Body;
1485
1513
1486
1514
return makeParserResult (Status,
@@ -1810,6 +1838,21 @@ ParserResult<Stmt> Parser::parseStmtWhile(LabeledStmtInfo LabelInfo) {
1810
1838
ParserStatus Status;
1811
1839
StmtCondition Condition;
1812
1840
1841
+ auto recoverWithCond = [&](ParserStatus Status,
1842
+ StmtCondition Condition) -> ParserResult<Stmt> {
1843
+ if (Condition.empty ()) {
1844
+ SmallVector<StmtConditionElement, 1 > ConditionElems;
1845
+ ConditionElems.emplace_back (new (Context) ErrorExpr (WhileLoc));
1846
+ Condition = Context.AllocateCopy (ConditionElems);
1847
+ }
1848
+ auto EndLoc = Condition.back ().getEndLoc ();
1849
+ return makeParserResult (
1850
+ Status,
1851
+ new (Context) WhileStmt (
1852
+ LabelInfo, WhileLoc, Condition,
1853
+ BraceStmt::create (Context, EndLoc, {}, EndLoc, /* implicit=*/ true )));
1854
+ };
1855
+
1813
1856
if (Tok.is (tok::l_brace)) {
1814
1857
SourceLoc LBraceLoc = Tok.getLoc ();
1815
1858
diagnose (WhileLoc, diag::missing_condition_after_while)
@@ -1820,18 +1863,15 @@ ParserResult<Stmt> Parser::parseStmtWhile(LabeledStmtInfo LabelInfo) {
1820
1863
} else {
1821
1864
Status |= parseStmtCondition (Condition, diag::expected_condition_while,
1822
1865
StmtKind::While);
1823
- if (Status.isError () || Status.hasCodeCompletion ()) {
1824
- // FIXME: better recovery
1825
- return makeParserResult<Stmt>(Status, nullptr );
1826
- }
1866
+ if (Status.isError () || Status.hasCodeCompletion ())
1867
+ return recoverWithCond (Status, Condition);
1827
1868
}
1828
1869
1829
1870
ParserResult<BraceStmt> Body =
1830
1871
parseBraceItemList (diag::expected_lbrace_after_while);
1831
- if (Body.isNull ())
1832
- return nullptr ; // FIXME: better recovery
1833
-
1834
1872
Status |= Body;
1873
+ if (Body.isNull ())
1874
+ return recoverWithCond (Status, Condition);
1835
1875
1836
1876
return makeParserResult (
1837
1877
Status, new (Context) WhileStmt (LabelInfo, WhileLoc, Condition,
0 commit comments