mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Parse] Remove Parser support for C-style for statement.
This commit is contained in:
@@ -992,30 +992,16 @@ ERROR(docatch_not_trycatch,PointsToFirstBadToken,
|
|||||||
"the 'do' keyword is used to specify a 'catch' region",
|
"the 'do' keyword is used to specify a 'catch' region",
|
||||||
())
|
())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// C-Style For Stmt
|
// C-Style For Stmt
|
||||||
ERROR(expected_init_for_stmt,PointsToFirstBadToken,
|
ERROR(c_style_for_stmt_removed,none,
|
||||||
"expected initialization in a 'for' statement", ())
|
"C-style for statement has been removed in Swift 3", ())
|
||||||
ERROR(missing_init_for_stmt,none,
|
|
||||||
"missing initialization in a 'for' statement", ())
|
|
||||||
ERROR(expected_semi_for_stmt,PointsToFirstBadToken,
|
|
||||||
"expected ';' in 'for' statement", ())
|
|
||||||
ERROR(expected_cond_for_stmt,none,
|
|
||||||
"expected condition in 'for' statement", ())
|
|
||||||
ERROR(expected_rparen_for_stmt,none,
|
|
||||||
"expected ')' in 'for' statement", ())
|
|
||||||
ERROR(expected_lbrace_after_for,none,
|
|
||||||
"expected '{' in 'for' statement", ())
|
|
||||||
ERROR(expected_var_decl_for_stmt,PointsToFirstBadToken,
|
|
||||||
"expected var declaration in a 'for' statement", ())
|
|
||||||
|
|
||||||
// For-each Stmt
|
// For-each Stmt
|
||||||
ERROR(expected_foreach_in,none,
|
ERROR(expected_foreach_in,PointsToFirstBadToken,
|
||||||
"expected 'in' after for-each pattern", ())
|
"expected 'in' after for-each pattern", ())
|
||||||
ERROR(expected_foreach_container,none,
|
ERROR(expected_foreach_container,PointsToFirstBadToken,
|
||||||
"expected Sequence expression for for-each loop", ())
|
"expected Sequence expression for for-each loop", ())
|
||||||
ERROR(expected_foreach_lbrace,none,
|
ERROR(expected_foreach_lbrace,PointsToFirstBadToken,
|
||||||
"expected '{' to start the body of for-each loop", ())
|
"expected '{' to start the body of for-each loop", ())
|
||||||
ERROR(expected_foreach_where_expr,PointsToFirstBadToken,
|
ERROR(expected_foreach_where_expr,PointsToFirstBadToken,
|
||||||
"expected expression in 'where' guard of 'for/in'", ())
|
"expected expression in 'where' guard of 'for/in'", ())
|
||||||
|
|||||||
@@ -476,6 +476,7 @@ public:
|
|||||||
void skipUntilDeclRBrace();
|
void skipUntilDeclRBrace();
|
||||||
|
|
||||||
void skipUntilDeclStmtRBrace(tok T1);
|
void skipUntilDeclStmtRBrace(tok T1);
|
||||||
|
void skipUntilDeclStmtRBrace(tok T1, tok T2);
|
||||||
|
|
||||||
void skipUntilDeclRBrace(tok T1, tok T2);
|
void skipUntilDeclRBrace(tok T1, tok T2);
|
||||||
|
|
||||||
@@ -1279,11 +1280,7 @@ public:
|
|||||||
ParserResult<Stmt> parseStmtRepeat(LabeledStmtInfo LabelInfo);
|
ParserResult<Stmt> parseStmtRepeat(LabeledStmtInfo LabelInfo);
|
||||||
ParserResult<Stmt> parseStmtDo(LabeledStmtInfo LabelInfo);
|
ParserResult<Stmt> parseStmtDo(LabeledStmtInfo LabelInfo);
|
||||||
ParserResult<CatchStmt> parseStmtCatch();
|
ParserResult<CatchStmt> parseStmtCatch();
|
||||||
ParserResult<Stmt> parseStmtFor(LabeledStmtInfo LabelInfo);
|
ParserResult<Stmt> parseStmtForEach(LabeledStmtInfo LabelInfo);
|
||||||
ParserResult<Stmt> parseStmtForCStyle(SourceLoc ForLoc,
|
|
||||||
LabeledStmtInfo LabelInfo);
|
|
||||||
ParserResult<Stmt> parseStmtForEach(SourceLoc ForLoc,
|
|
||||||
LabeledStmtInfo LabelInfo);
|
|
||||||
ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo);
|
ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo);
|
||||||
ParserStatus parseStmtCases(SmallVectorImpl<ASTNode> &cases, bool IsActive);
|
ParserStatus parseStmtCases(SmallVectorImpl<ASTNode> &cases, bool IsActive);
|
||||||
ParserResult<CaseStmt> parseStmtCase(bool IsActive);
|
ParserResult<CaseStmt> parseStmtCase(bool IsActive);
|
||||||
|
|||||||
@@ -573,10 +573,14 @@ std::pair<bool, Stmt *> ModelASTWalker::walkToStmtPre(Stmt *S) {
|
|||||||
SyntaxStructureNode SN;
|
SyntaxStructureNode SN;
|
||||||
SN.Kind = SyntaxStructureKind::ForEachStatement;
|
SN.Kind = SyntaxStructureKind::ForEachStatement;
|
||||||
SN.Range = charSourceRangeFromSourceRange(SM, S->getSourceRange());
|
SN.Range = charSourceRangeFromSourceRange(SM, S->getSourceRange());
|
||||||
if (ForEachS->getPattern())
|
if (ForEachS->getPattern()) {
|
||||||
SN.Elements.emplace_back(SyntaxStructureElementKind::Id,
|
auto Pat = ForEachS->getPattern();
|
||||||
charSourceRangeFromSourceRange(SM,
|
if (!Pat->isImplicit()) {
|
||||||
ForEachS->getPattern()->getSourceRange()));
|
SourceRange ElemRange = Pat->getSourceRange();
|
||||||
|
SN.Elements.emplace_back(SyntaxStructureElementKind::Id,
|
||||||
|
charSourceRangeFromSourceRange(SM, ElemRange));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ForEachS->getSequence())
|
if (ForEachS->getSequence())
|
||||||
addExprElem(SyntaxStructureElementKind::Expr, ForEachS->getSequence(),SN);
|
addExprElem(SyntaxStructureElementKind::Expr, ForEachS->getSequence(),SN);
|
||||||
pushStructureNode(SN, S);
|
pushStructureNode(SN, S);
|
||||||
|
|||||||
@@ -545,7 +545,7 @@ ParserResult<Stmt> Parser::parseStmt() {
|
|||||||
return parseStmtDo(LabelInfo);
|
return parseStmtDo(LabelInfo);
|
||||||
case tok::kw_for:
|
case tok::kw_for:
|
||||||
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
|
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
|
||||||
return parseStmtFor(LabelInfo);
|
return parseStmtForEach(LabelInfo);
|
||||||
case tok::kw_switch:
|
case tok::kw_switch:
|
||||||
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
|
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
|
||||||
return parseStmtSwitch(LabelInfo);
|
return parseStmtSwitch(LabelInfo);
|
||||||
@@ -1749,308 +1749,48 @@ ParserResult<CatchStmt> Parser::parseStmtCatch() {
|
|||||||
return makeParserResult(status, result);
|
return makeParserResult(status, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParserResult<Stmt> Parser::parseStmtFor(LabeledStmtInfo LabelInfo) {
|
static bool isStmtForCStyle(Parser &P) {
|
||||||
SourceLoc ForLoc = consumeToken(tok::kw_for);
|
// If we have a leading identifier followed by a ':' or 'in', or have a
|
||||||
|
// 'case', then this is obviously a for-each loop. "for in ..." is malformed
|
||||||
|
// but it's obviously not a C-style for.
|
||||||
|
if ((P.Tok.isIdentifierOrUnderscore() &&
|
||||||
|
P.peekToken().isAny(tok::colon, tok::kw_in)) ||
|
||||||
|
P.Tok.isAny(tok::kw_case, tok::kw_in))
|
||||||
|
return false;
|
||||||
|
|
||||||
// The c-style-for loop and foreach-style-for loop are conflated together into
|
// Otherwise, we have to look forward if we see ';' in control part.
|
||||||
// a single keyword, so we have to do some lookahead to resolve what is going
|
Parser::BacktrackingScope Backtrack(P);
|
||||||
// on.
|
|
||||||
|
|
||||||
// If we have a leading identifier followed by a ':' or 'in', then this is
|
|
||||||
// obviously a for-each loop. For error recovery, also parse "for in ..." as
|
|
||||||
// foreach.
|
|
||||||
if ((Tok.isIdentifierOrUnderscore() &&
|
|
||||||
peekToken().isAny(tok::colon, tok::kw_in)) ||
|
|
||||||
Tok.is(tok::kw_in))
|
|
||||||
return parseStmtForEach(ForLoc, LabelInfo);
|
|
||||||
|
|
||||||
// If we have "for ;" then this is clearly a c-style for loop.
|
// The condition of a c-style-for loop can be parenthesized.
|
||||||
if (Tok.is(tok::semi))
|
auto HasLParen = P.consumeIf(tok::l_paren);
|
||||||
return parseStmtForCStyle(ForLoc, LabelInfo);
|
|
||||||
|
|
||||||
// Otherwise, we have to do lookahead. An unparenthesized valid C-style
|
// Skip until we see ';', or something that ends control part.
|
||||||
// for-each loop will start with "let/var <irrefutable pattern> =". Check for
|
while (P.Tok.isNot(tok::eof, tok::kw_in, tok::semi, tok::l_brace,
|
||||||
// that.
|
tok::r_brace, tok::r_paren) && !P.isStartOfStmt()) {
|
||||||
bool isCStyleFor = false;
|
// If we saw newline before ';', consider it is a foreach statement.
|
||||||
{
|
if (!HasLParen && P.Tok.isAtStartOfLine())
|
||||||
Parser::BacktrackingScope Backtrack(*this);
|
return false;
|
||||||
|
P.skipSingle();
|
||||||
// The condition of a foreach loop can be parenthesized.
|
|
||||||
consumeIf(tok::l_paren);
|
|
||||||
|
|
||||||
// Skip until we see eof, "in" (in which case we have a for-in loop),
|
|
||||||
// ";" in which case we have a simple expression as the first part of a
|
|
||||||
// c-style for loop, or "{" in which case we have a malformed statement.
|
|
||||||
while (Tok.isNot(tok::eof, tok::kw_in, tok::semi, tok::l_brace))
|
|
||||||
skipSingle();
|
|
||||||
|
|
||||||
isCStyleFor = Tok.isAny(tok::semi, tok::l_brace, tok::eof);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, this is some sort of c-style for loop.
|
|
||||||
if (isCStyleFor)
|
|
||||||
return parseStmtForCStyle(ForLoc, LabelInfo);
|
|
||||||
|
|
||||||
return parseStmtForEach(ForLoc, LabelInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Given an expression, check to see if it is a set of braces "{...}" parsed as
|
|
||||||
/// a ClosureExpr that is probably a body of a statement. If so, convert it
|
|
||||||
/// into a BraceStmt that can be used as the body of a control flow statement
|
|
||||||
/// to improve error recovery.
|
|
||||||
///
|
|
||||||
/// If this expression isn't a ClosureExpr or isn't convertible, this returns
|
|
||||||
/// null.
|
|
||||||
///
|
|
||||||
static BraceStmt *ConvertClosureToBraceStmt(Expr *E, ASTContext &Ctx) {
|
|
||||||
if (!E) return nullptr;
|
|
||||||
|
|
||||||
auto *CE = dyn_cast<ClosureExpr>(E);
|
|
||||||
if (!CE) return nullptr;
|
|
||||||
|
|
||||||
// If this had a signature or anon-closure parameters (like $0) used, then it
|
|
||||||
// doesn't "look" like the body of a control flow statement, it looks like a
|
|
||||||
// closure.
|
|
||||||
if (CE->getInLoc().isValid() || CE->hasExplicitResultType() ||
|
|
||||||
CE->getParameters()->size() != 0)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Silence downstream errors by giving it type ()->(), to match up with the
|
|
||||||
// call we will produce.
|
|
||||||
CE->setImplicit();
|
|
||||||
auto empty = TupleTypeRepr::createEmpty(Ctx, CE->getStartLoc());
|
|
||||||
CE->setExplicitResultType(CE->getStartLoc(), empty);
|
|
||||||
|
|
||||||
// The trick here is that the ClosureExpr provides a DeclContext for stuff
|
|
||||||
// inside of it, so it isn't safe to just drop it and rip the BraceStmt
|
|
||||||
// from inside of it. While we could try to walk the body and update any
|
|
||||||
// Decls, ClosureExprs, etc within the body of the ClosureExpr, it is easier
|
|
||||||
// to just turn it into BraceStmt(CallExpr(TheClosure, VoidTuple)). This also
|
|
||||||
// more correctly handles the implicit ReturnStmt injected into single-expr
|
|
||||||
// closures.
|
|
||||||
ASTNode theCall = CallExpr::createImplicit(Ctx, CE, { }, { });
|
|
||||||
return BraceStmt::create(Ctx, CE->getStartLoc(), theCall, CE->getEndLoc(),
|
|
||||||
/*implicit*/true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// stmt-for-c-style:
|
|
||||||
/// (identifier ':')? 'for' stmt-for-c-style-init? ';' expr-basic? ';'
|
|
||||||
/// (expr-basic (',' expr-basic)*)? stmt-brace
|
|
||||||
/// (identifier ':')? 'for' '(' stmt-for-c-style-init? ';' expr-basic? ';'
|
|
||||||
/// (expr-basic (',' expr-basic)*)? ')' stmt-brace
|
|
||||||
/// stmt-for-c-style-init:
|
|
||||||
/// decl-var
|
|
||||||
/// expr (',' expr)*
|
|
||||||
ParserResult<Stmt> Parser::parseStmtForCStyle(SourceLoc ForLoc,
|
|
||||||
LabeledStmtInfo LabelInfo) {
|
|
||||||
SourceLoc Semi1Loc, Semi2Loc;
|
|
||||||
SourceLoc LPLoc, RPLoc;
|
|
||||||
bool LPLocConsumed = false;
|
|
||||||
|
|
||||||
ParserStatus Status;
|
|
||||||
|
|
||||||
ParserResult<Expr> First;
|
|
||||||
SmallVector<Decl*, 2> FirstDecls;
|
|
||||||
ParserResult<Expr> Second;
|
|
||||||
ParserResult<Expr> Third;
|
|
||||||
ParserResult<BraceStmt> Body;
|
|
||||||
|
|
||||||
// Introduce a new scope to contain any var decls in the init value.
|
|
||||||
Scope S(this, ScopeKind::ForVars);
|
|
||||||
|
|
||||||
if (Tok.is(tok::l_paren)) {
|
|
||||||
LPLoc = consumeToken();
|
|
||||||
LPLocConsumed = true;
|
|
||||||
}
|
|
||||||
// Parse the first part, either a var, let, expr, or stmt-assign.
|
|
||||||
if (Tok.is(tok::kw_var) || Tok.is(tok::kw_let) || Tok.is(tok::at_sign)) {
|
|
||||||
DeclAttributes Attributes;
|
|
||||||
bool FoundCCToken;
|
|
||||||
parseDeclAttributeList(Attributes, FoundCCToken);
|
|
||||||
|
|
||||||
// After parsing optional attributes above we should be at 'var' or 'let'
|
|
||||||
if (!Tok.is(tok::kw_var) && !Tok.is(tok::kw_let)) {
|
|
||||||
diagnose(Tok.getLoc(), diag::expected_var_decl_for_stmt);
|
|
||||||
return makeParserError();
|
|
||||||
}
|
|
||||||
|
|
||||||
ParserStatus VarDeclStatus = parseDeclVar(PD_InLoop, Attributes, FirstDecls,
|
|
||||||
SourceLoc(),
|
|
||||||
StaticSpellingKind::None,
|
|
||||||
SourceLoc());
|
|
||||||
if (VarDeclStatus.isError())
|
|
||||||
return VarDeclStatus; // FIXME: better recovery
|
|
||||||
} else if (Tok.isNot(tok::semi)) {
|
|
||||||
SmallVector<Expr *, 1> FirstExprs;
|
|
||||||
|
|
||||||
// Parse the first expression.
|
|
||||||
First = parseExpr(diag::expected_init_for_stmt);
|
|
||||||
Status |= First;
|
|
||||||
if (First.isNull() || First.hasCodeCompletion())
|
|
||||||
return makeParserResult<Stmt>(Status, nullptr); // FIXME: better recovery
|
|
||||||
|
|
||||||
FirstExprs.push_back(First.get());
|
|
||||||
|
|
||||||
// Parse additional expressions.
|
|
||||||
while (Tok.is(tok::comma)) {
|
|
||||||
consumeToken(tok::comma);
|
|
||||||
|
|
||||||
First = parseExpr(diag::expected_expr);
|
|
||||||
Status |= First;
|
|
||||||
|
|
||||||
if (First.isNull() || First.hasCodeCompletion())
|
|
||||||
return makeParserResult<Stmt>(Status, nullptr); // FIXME: better recovery
|
|
||||||
|
|
||||||
if (First.isNonNull())
|
|
||||||
FirstExprs.push_back(First.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we had more than one expression, form a tuple.
|
|
||||||
if (FirstExprs.size() > 1) {
|
|
||||||
First = makeParserResult(
|
|
||||||
TupleExpr::createImplicit(Context, FirstExprs, { }));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Decl *> FirstDeclsContext;
|
return P.Tok.is(tok::semi);
|
||||||
if (!FirstDecls.empty())
|
|
||||||
FirstDeclsContext = Context.AllocateCopy(FirstDecls);
|
|
||||||
|
|
||||||
// If we're missing a semicolon, try to recover.
|
|
||||||
if (Tok.isNot(tok::semi)) {
|
|
||||||
// Provide a reasonable default location for the first semicolon.
|
|
||||||
Semi1Loc = PreviousLoc;
|
|
||||||
|
|
||||||
if (auto *BS = ConvertClosureToBraceStmt(First.getPtrOrNull(), Context)) {
|
|
||||||
// We have seen:
|
|
||||||
// for { ... }
|
|
||||||
// and there's no semicolon after that.
|
|
||||||
//
|
|
||||||
// We parsed the brace statement as a closure. Recover by using the
|
|
||||||
// brace statement as a 'for' body.
|
|
||||||
First = makeParserErrorResult(new (Context) ErrorExpr(BS->getStartLoc()));
|
|
||||||
Second = nullptr;
|
|
||||||
Third = nullptr;
|
|
||||||
Body = makeParserErrorResult(BS);
|
|
||||||
diagnose(ForLoc, diag::missing_init_for_stmt)
|
|
||||||
.highlight(SourceRange(ForLoc, BS->getStartLoc()));
|
|
||||||
Status.setIsParseError();
|
|
||||||
|
|
||||||
return makeParserResult(
|
|
||||||
Status, new (Context) ForStmt(LabelInfo, ForLoc, First.getPtrOrNull(),
|
|
||||||
FirstDeclsContext,
|
|
||||||
Semi1Loc, Second.getPtrOrNull(),
|
|
||||||
Semi2Loc, Third.getPtrOrNull(),
|
|
||||||
Body.get()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume the first semicolon.
|
|
||||||
if (parseToken(tok::semi, Semi1Loc, diag::expected_semi_for_stmt))
|
|
||||||
Status.setIsParseError();
|
|
||||||
|
|
||||||
if (Tok.isNot(tok::semi)) {
|
|
||||||
Second = parseExprBasic(diag::expected_cond_for_stmt);
|
|
||||||
Status |= Second;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tok.isNot(tok::semi) && Second.isNonNull()) {
|
|
||||||
Expr *RecoveredCondition = nullptr;
|
|
||||||
BraceStmt *RecoveredBody = ConvertClosureToBraceStmt(Second.get(), Context);
|
|
||||||
|
|
||||||
if (auto *CE = dyn_cast<CallExpr>(Second.get())) {
|
|
||||||
if (auto *PE = dyn_cast<ParenExpr>(CE->getArg())) {
|
|
||||||
if (PE->hasTrailingClosure() && !RecoveredBody) {
|
|
||||||
// We have seen:
|
|
||||||
// for ... ; ... { ... }
|
|
||||||
// and there's no semicolon after that.
|
|
||||||
//
|
|
||||||
// We parsed the condition as a CallExpr with a brace statement as a
|
|
||||||
// trailing closure. Recover by using the original expression as the
|
|
||||||
// condition and brace statement as a 'for' body.
|
|
||||||
RecoveredBody = ConvertClosureToBraceStmt(PE->getSubExpr(), Context);
|
|
||||||
RecoveredCondition = CE->getFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (RecoveredBody) {
|
|
||||||
SourceLoc LBraceLoc = RecoveredBody->getStartLoc();
|
|
||||||
Second = makeParserErrorResult(RecoveredCondition);
|
|
||||||
Third = nullptr;
|
|
||||||
Body = makeParserErrorResult(RecoveredBody);
|
|
||||||
diagnose(LBraceLoc, diag::expected_semi_for_stmt)
|
|
||||||
.highlight(SourceRange(ForLoc, LBraceLoc));
|
|
||||||
Status.setIsParseError();
|
|
||||||
|
|
||||||
return makeParserResult(
|
|
||||||
Status, new (Context) ForStmt(LabelInfo, ForLoc, First.getPtrOrNull(),
|
|
||||||
FirstDeclsContext,
|
|
||||||
Semi1Loc, Second.getPtrOrNull(),
|
|
||||||
Semi2Loc, Third.getPtrOrNull(),
|
|
||||||
Body.get()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume the second semicolon.
|
|
||||||
if (parseToken(tok::semi, Semi2Loc, diag::expected_semi_for_stmt))
|
|
||||||
Status.setIsParseError();
|
|
||||||
|
|
||||||
if (Tok.isNot(tok::l_brace, tok::r_paren)) {
|
|
||||||
SmallVector<Expr *, 1> ThirdExprs;
|
|
||||||
|
|
||||||
// Parse the first expression.
|
|
||||||
Third = parseExprBasic(diag::expected_expr);
|
|
||||||
Status |= Third;
|
|
||||||
if (Third.isNonNull())
|
|
||||||
ThirdExprs.push_back(Third.get());
|
|
||||||
|
|
||||||
// Parse additional expressions.
|
|
||||||
while (Tok.is(tok::comma)) {
|
|
||||||
consumeToken(tok::comma);
|
|
||||||
|
|
||||||
Third = parseExprBasic(diag::expected_expr);
|
|
||||||
Status |= Third;
|
|
||||||
|
|
||||||
if (Third.isNonNull())
|
|
||||||
ThirdExprs.push_back(Third.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we had more than one expression, form a tuple.
|
|
||||||
if (ThirdExprs.size() > 1) {
|
|
||||||
Third = makeParserResult(
|
|
||||||
TupleExpr::createImplicit(Context, ThirdExprs, { }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LPLocConsumed && parseMatchingToken(tok::r_paren, RPLoc,
|
|
||||||
diag::expected_rparen_for_stmt,LPLoc))
|
|
||||||
Status.setIsParseError();
|
|
||||||
|
|
||||||
Body = parseBraceItemList(diag::expected_lbrace_after_for);
|
|
||||||
Status |= Body;
|
|
||||||
if (Body.isNull())
|
|
||||||
Body = makeParserResult(
|
|
||||||
Body, BraceStmt::create(Context, PreviousLoc, {}, PreviousLoc, true));
|
|
||||||
|
|
||||||
return makeParserResult(
|
|
||||||
Status,
|
|
||||||
new (Context) ForStmt(LabelInfo, ForLoc, First.getPtrOrNull(),
|
|
||||||
FirstDeclsContext,
|
|
||||||
Semi1Loc, Second.getPtrOrNull(), Semi2Loc,
|
|
||||||
Third.getPtrOrNull(), Body.get()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// stmt-for-each:
|
/// stmt-for-each:
|
||||||
/// (identifier ':')? 'for' pattern 'in' expr-basic \
|
/// (identifier ':')? 'for' pattern 'in' expr-basic \
|
||||||
/// ('where' expr-basic)? stmt-brace
|
/// ('where' expr-basic)? stmt-brace
|
||||||
ParserResult<Stmt> Parser::parseStmtForEach(SourceLoc ForLoc,
|
ParserResult<Stmt> Parser::parseStmtForEach(LabeledStmtInfo LabelInfo) {
|
||||||
LabeledStmtInfo LabelInfo) {
|
SourceLoc ForLoc = consumeToken(tok::kw_for);
|
||||||
ParserStatus Status;
|
ParserStatus Status;
|
||||||
|
|
||||||
ParserResult<Pattern> pattern;
|
ParserResult<Pattern> pattern;
|
||||||
|
ParserResult<Expr> Container;
|
||||||
|
|
||||||
|
// The C-style for loop which was supported in Swift2 and foreach-style-for
|
||||||
|
// loop are conflated together into a single keyword, so we have to do some
|
||||||
|
// lookahead to resolve what is going on.
|
||||||
|
bool IsCStyleFor = isStmtForCStyle(*this);
|
||||||
|
auto StartOfControl = Tok.getLoc();
|
||||||
|
|
||||||
// Parse the pattern. This is either 'case <refutable pattern>' or just a
|
// Parse the pattern. This is either 'case <refutable pattern>' or just a
|
||||||
// normal pattern.
|
// normal pattern.
|
||||||
@@ -2059,7 +1799,7 @@ ParserResult<Stmt> Parser::parseStmtForEach(SourceLoc ForLoc,
|
|||||||
T(InVarOrLetPattern, Parser::IVOLP_InMatchingPattern);
|
T(InVarOrLetPattern, Parser::IVOLP_InMatchingPattern);
|
||||||
pattern = parseMatchingPattern(/*isExprBasic*/true);
|
pattern = parseMatchingPattern(/*isExprBasic*/true);
|
||||||
pattern = parseOptionalPatternTypeAnnotation(pattern, /*isOptional*/false);
|
pattern = parseOptionalPatternTypeAnnotation(pattern, /*isOptional*/false);
|
||||||
} else {
|
} else if (!IsCStyleFor || Tok.is(tok::kw_var)) {
|
||||||
// Change the parser state to know that the pattern we're about to parse is
|
// Change the parser state to know that the pattern we're about to parse is
|
||||||
// implicitly mutable. Bound variables can be changed to mutable explicitly
|
// implicitly mutable. Bound variables can be changed to mutable explicitly
|
||||||
// if desired by using a 'var' pattern.
|
// if desired by using a 'var' pattern.
|
||||||
@@ -2071,18 +1811,38 @@ ParserResult<Stmt> Parser::parseStmtForEach(SourceLoc ForLoc,
|
|||||||
InVarOrLetPattern = IVOLP_NotInVarOrLet;
|
InVarOrLetPattern = IVOLP_NotInVarOrLet;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pattern.isNull())
|
SourceLoc InLoc;
|
||||||
|
if (pattern.isNull()) {
|
||||||
// Recover by creating a "_" pattern.
|
// Recover by creating a "_" pattern.
|
||||||
pattern = makeParserErrorResult(new (Context) AnyPattern(SourceLoc()));
|
pattern = makeParserErrorResult(new (Context) AnyPattern(SourceLoc()));
|
||||||
|
consumeIf(tok::kw_in, InLoc);
|
||||||
|
} else if (!IsCStyleFor) {
|
||||||
|
parseToken(tok::kw_in, InLoc, diag::expected_foreach_in);
|
||||||
|
}
|
||||||
|
|
||||||
// Bound variables all get their initial values from the generator.
|
// Bound variables all get their initial values from the generator.
|
||||||
pattern.get()->markHasNonPatternBindingInit();
|
pattern.get()->markHasNonPatternBindingInit();
|
||||||
|
|
||||||
SourceLoc InLoc;
|
|
||||||
parseToken(tok::kw_in, InLoc, diag::expected_foreach_in);
|
|
||||||
|
|
||||||
ParserResult<Expr> Container;
|
if (IsCStyleFor) {
|
||||||
if (Tok.is(tok::l_brace)) {
|
// Skip until start of body part.
|
||||||
|
if (Tok.is(tok::l_paren)) {
|
||||||
|
skipSingle();
|
||||||
|
} else {
|
||||||
|
// If not parenthesized, don't run over the line.
|
||||||
|
while (Tok.isNot(tok::eof, tok::r_brace, tok::l_brace, tok::code_complete)
|
||||||
|
&& !Tok.isAtStartOfLine())
|
||||||
|
skipSingle();
|
||||||
|
}
|
||||||
|
if (Tok.is(tok::code_complete))
|
||||||
|
return makeParserCodeCompletionStatus();
|
||||||
|
|
||||||
|
assert(StartOfControl != Tok.getLoc());
|
||||||
|
SourceRange ControlRange(StartOfControl, PreviousLoc);
|
||||||
|
Container = makeParserErrorResult(new (Context) ErrorExpr(ControlRange));
|
||||||
|
diagnose(ForLoc, diag::c_style_for_stmt_removed)
|
||||||
|
.highlight(ControlRange);
|
||||||
|
Status = makeParserError();
|
||||||
|
} else if (Tok.is(tok::l_brace)) {
|
||||||
SourceLoc LBraceLoc = Tok.getLoc();
|
SourceLoc LBraceLoc = Tok.getLoc();
|
||||||
diagnose(LBraceLoc, diag::expected_foreach_container);
|
diagnose(LBraceLoc, diag::expected_foreach_container);
|
||||||
Container = makeParserErrorResult(new (Context) ErrorExpr(LBraceLoc));
|
Container = makeParserErrorResult(new (Context) ErrorExpr(LBraceLoc));
|
||||||
@@ -2099,6 +1859,10 @@ ParserResult<Stmt> Parser::parseStmtForEach(SourceLoc ForLoc,
|
|||||||
Container = parseExprBasic(diag::expected_foreach_container);
|
Container = parseExprBasic(diag::expected_foreach_container);
|
||||||
if (Container.isNull())
|
if (Container.isNull())
|
||||||
Container = makeParserErrorResult(new (Context) ErrorExpr(Tok.getLoc()));
|
Container = makeParserErrorResult(new (Context) ErrorExpr(Tok.getLoc()));
|
||||||
|
if (Container.isParseError())
|
||||||
|
// Recover.
|
||||||
|
skipUntilDeclStmtRBrace(tok::l_brace, tok::kw_where);
|
||||||
|
|
||||||
Status |= Container;
|
Status |= Container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2120,7 +1884,6 @@ ParserResult<Stmt> Parser::parseStmtForEach(SourceLoc ForLoc,
|
|||||||
Status |= Where;
|
Status |= Where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// stmt-brace
|
// stmt-brace
|
||||||
ParserResult<BraceStmt> Body =
|
ParserResult<BraceStmt> Body =
|
||||||
parseBraceItemList(diag::expected_foreach_lbrace);
|
parseBraceItemList(diag::expected_foreach_lbrace);
|
||||||
|
|||||||
@@ -496,6 +496,14 @@ void Parser::skipUntilDeclStmtRBrace(tok T1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Parser::skipUntilDeclStmtRBrace(tok T1, tok T2) {
|
||||||
|
while (Tok.isNot(T1, T2, tok::eof, tok::r_brace, tok::pound_endif,
|
||||||
|
tok::code_complete) &&
|
||||||
|
!isStartOfStmt() && !isStartOfDecl()) {
|
||||||
|
skipSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::skipUntilDeclRBrace(tok T1, tok T2) {
|
void Parser::skipUntilDeclRBrace(tok T1, tok T2) {
|
||||||
while (Tok.isNot(T1, T2, tok::eof, tok::r_brace, tok::pound_endif) &&
|
while (Tok.isNot(T1, T2, tok::eof, tok::r_brace, tok::pound_endif) &&
|
||||||
!isStartOfDecl()) {
|
!isStartOfDecl()) {
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ func resyncParserB5() {}
|
|||||||
for var i = 0; ; {
|
for var i = 0; ; {
|
||||||
#^TOP_LEVEL_STMT_5^#
|
#^TOP_LEVEL_STMT_5^#
|
||||||
// TOP_LEVEL_STMT_5: Begin completions
|
// TOP_LEVEL_STMT_5: Begin completions
|
||||||
// TOP_LEVEL_STMT_5: Decl[LocalVar]/Local: i[#Int#]{{; name=.+$}}
|
// TOP_LEVEL_STMT_5: Decl[LocalVar]/Local: i[#<<error type>>#]{{; name=.+$}}
|
||||||
// TOP_LEVEL_STMT_5: End completions
|
// TOP_LEVEL_STMT_5: End completions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_DO_WHILE_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_DO_WHILE_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_DO_WHILE_2 | %FileCheck %s -check-prefix=COND-WITH-RELATION1
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_DO_WHILE_2 | %FileCheck %s -check-prefix=COND-WITH-RELATION1
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_1 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_1 | %FileCheck %s -check-prefix=COND_NONE
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_2 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_3 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INIT_3 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
|
||||||
@@ -26,54 +26,26 @@
|
|||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_2 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_3 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_3 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_1 > %t.cond.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.cond.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_E_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.cond.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_2 > %t.cond.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.cond.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.cond.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_COND_I_E_1 > %t.cond.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.cond.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_E_LOCAL < %t.cond.txt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_1 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_2 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_3 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_4 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_E_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_1 > %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.incr.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_2 > %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.incr.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_3 > %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.incr.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_4 > %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.incr.txt
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_INCR_I_E_1 > %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.incr.txt
|
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_E_LOCAL < %t.incr.txt
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: should have 'i' in these results.
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_1 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_1 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
// FIXME: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.body.txt
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_2 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_2 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.body.txt
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_3 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_3 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
@@ -81,16 +53,15 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_4 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_4 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.body.txt
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_5 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_5 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.body.txt
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_6 > %t.body.txt
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=C_STYLE_FOR_BODY_I_6 > %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=COND_COMMON < %t.body.txt
|
||||||
// RUN: %FileCheck %s -check-prefix=WITH_I_INT_LOCAL < %t.body.txt
|
// RUN: %FileCheck %s -check-prefix=WITH_I_ERROR_LOCAL < %t.body.txt
|
||||||
|
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FOR_EACH_EXPR_1 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FOR_EACH_EXPR_1 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FOR_EACH_EXPR_2 | %FileCheck %s -check-prefix=COND_COMMON
|
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FOR_EACH_EXPR_2 | %FileCheck %s -check-prefix=COND_COMMON
|
||||||
@@ -518,10 +489,6 @@ func testSwitchCaseWhereExprIJ1(_ fooObject: FooStruct) {
|
|||||||
|
|
||||||
// WITH_J_INT: Decl[LocalVar]/Local: j[#Int#]{{; name=.+$}}
|
// WITH_J_INT: Decl[LocalVar]/Local: j[#Int#]{{; name=.+$}}
|
||||||
|
|
||||||
// WITH_I_E_LOCAL: Decl[LocalVar]/Local: i[#Int#]{{; name=.+$}}
|
|
||||||
// WITH_I_E_LOCAL: Decl[LocalVar]/Local: e[#Int#]{{; name=.+$}}
|
|
||||||
|
|
||||||
|
|
||||||
enum A { case aaa }
|
enum A { case aaa }
|
||||||
enum B { case bbb }
|
enum B { case bbb }
|
||||||
// UNRESOLVED_B-NOT: aaa
|
// UNRESOLVED_B-NOT: aaa
|
||||||
|
|||||||
@@ -66,9 +66,11 @@ func ffoo() {}
|
|||||||
|
|
||||||
// CHECK: <foreach>for <elem-id>i</elem-id> in <elem-expr>0...5</elem-expr> <brace>{}</brace></foreach>
|
// CHECK: <foreach>for <elem-id>i</elem-id> in <elem-expr>0...5</elem-expr> <brace>{}</brace></foreach>
|
||||||
for i in 0...5 {}
|
for i in 0...5 {}
|
||||||
// CHECK: <for>for <elem-initexpr>var i = 0, i2 = 1</elem-initexpr>; <elem-expr>i == 0</elem-expr>; <elem-expr>++i</elem-expr> <brace>{}</brace></for>
|
// CHECK: <foreach>for <elem-id>var (i, j)</elem-id> in <elem-expr>array</elem-expr> <brace>{}</brace></foreach>
|
||||||
|
for var (i, j) in array {}
|
||||||
|
// CHECK: <foreach>for <elem-id>var i</elem-id> = 0, i2 = 1; i == 0; ++i <brace>{}</brace></foreach>
|
||||||
for var i = 0, i2 = 1; i == 0; ++i {}
|
for var i = 0, i2 = 1; i == 0; ++i {}
|
||||||
// CHECK: <for>for <elem-initexpr>var (i,i2) = (0,0), i3 = 1</elem-initexpr>; <elem-expr>i == 0</elem-expr>; <elem-expr>++i</elem-expr> <brace>{}</brace></for>
|
// CHECK: <foreach>for <elem-id>var (i,i2)</elem-id> = (0,0), i3 = 1; i == 0; ++i <brace>{}</brace></foreach>
|
||||||
for var (i,i2) = (0,0), i3 = 1; i == 0; ++i {}
|
for var (i,i2) = (0,0), i3 = 1; i == 0; ++i {}
|
||||||
|
|
||||||
for i = 0; i == 0; ++i {}
|
for i = 0; i == 0; ++i {}
|
||||||
@@ -105,7 +107,7 @@ let myArray2 = [1]
|
|||||||
// CHECK: <gvar>let <name>myDict2</name> = <dictionary>[<elem-expr>1</elem-expr>:<elem-expr>1</elem-expr>]</dictionary></gvar>
|
// CHECK: <gvar>let <name>myDict2</name> = <dictionary>[<elem-expr>1</elem-expr>:<elem-expr>1</elem-expr>]</dictionary></gvar>
|
||||||
let myDict2 = [1:1]
|
let myDict2 = [1:1]
|
||||||
|
|
||||||
// CHECK: <for>for <brace><brace>{}</brace></brace></for>
|
// CHECK: <foreach>for <brace>{}</brace></foreach>
|
||||||
for {}
|
for {}
|
||||||
|
|
||||||
// CHECK: <class>class <name><#MyCls#></name> : <inherited><elem-typeref><#OtherClass#></elem-typeref></inherited> {}
|
// CHECK: <class>class <name><#MyCls#></name> : <inherited><elem-typeref><#OtherClass#></elem-typeref></inherited> {}
|
||||||
|
|||||||
@@ -319,8 +319,8 @@ class LazyProperties {
|
|||||||
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [94:5 - 94:10] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [94:5 - 94:10] expanded
|
||||||
// CHECK-EXPANDED-NEXT: {{^}} `-CaseStmt {{.*}} [97:5 - 97:10] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-CaseStmt {{.*}} [97:5 - 97:10] expanded
|
||||||
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [97:5 - 97:10] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [97:5 - 97:10] expanded
|
||||||
// CHECK-EXPANDED-NEXT: {{^}} `-ForStmt {{.*}} [99:3 - 99:38] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-ForEachStmt {{.*}} [99:3 - 99:38] expanded
|
||||||
// CHECK-EXPANDED-NEXT: {{^}} `-ForStmtInitializer {{.*}} [99:17 - 99:38] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-ForEachPattern {{.*}} [99:36 - 99:38] expanded
|
||||||
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [99:36 - 99:38] expanded
|
// CHECK-EXPANDED-NEXT: {{^}} `-BraceStmt {{.*}} [99:36 - 99:38] expanded
|
||||||
|
|
||||||
// CHECK-EXPANDED: TypeDecl {{.*}} StructContainsAbstractStorageDecls [114:1 - 130:1] expanded
|
// CHECK-EXPANDED: TypeDecl {{.*}} StructContainsAbstractStorageDecls [114:1 - 130:1] expanded
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// RUN: %target-typecheck-verify-swift
|
// RUN: %target-typecheck-verify-swift
|
||||||
|
|
||||||
func fuzz() { for var H
|
func fuzz() { for var H
|
||||||
// expected-note@-1 {{to match this opening '{'}}
|
// expected-error@-1{{expected 'in' after for-each pattern}}
|
||||||
// expected-error@-2{{type annotation missing in pattern}}
|
// expected-error@-2{{expected Sequence expression for for-each loop}}
|
||||||
// expected-error@-3 2 {{expected ';' in 'for' statement}}
|
// expected-error@-3{{expected '{' to start the body of for-each loop}}
|
||||||
// expected-error@+4{{expected '{' in 'for' statement}}
|
// expected-note@-4 {{to match this opening '{'}}
|
||||||
// expected-error@+3{{expected '}' at end of brace statement}}
|
// expected-error@+1{{expected '}' at end of brace statement}}
|
||||||
// expected-error@+2{{expected condition in 'for' statement}}
|
|
||||||
// expected-error@+1{{expected expression}}
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ struct IntRange<Int> : Sequence, IteratorProtocol {
|
|||||||
func makeIterator() -> IntRange<Int> { return self }
|
func makeIterator() -> IntRange<Int> { return self }
|
||||||
}
|
}
|
||||||
|
|
||||||
func for_each(r: Range<Int>, iir: IntRange<Int>) { // expected-note 2 {{did you mean 'r'?}}
|
func for_each(r: Range<Int>, iir: IntRange<Int>) { // expected-note {{did you mean 'r'?}}
|
||||||
var sum = 0
|
var sum = 0
|
||||||
|
|
||||||
// Simple foreach loop, using the variable in the body
|
// Simple foreach loop, using the variable in the body
|
||||||
@@ -30,7 +30,11 @@ func for_each(r: Range<Int>, iir: IntRange<Int>) { // expected-note 2 {{did you
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse errors
|
// Parse errors
|
||||||
for i r { // expected-error 2{{expected ';' in 'for' statement}} expected-error {{use of unresolved identifier 'i'}} expected-error {{'Range<Int>' is not convertible to 'Bool'}}
|
// FIXME: Bad diagnostics; should be just 'expected 'in' after for-each patter'.
|
||||||
}
|
for i r { // expected-error {{found an unexpected second identifier in constant declaration}}
|
||||||
|
} // expected-note @-1 {{join the identifiers together}}
|
||||||
|
// expected-note @-2 {{join the identifiers together with camel-case}}
|
||||||
|
// expected-error @-3 {{expected 'in' after for-each pattern}}
|
||||||
|
// expected-error @-4 {{expected Sequence expression for for-each loop}}
|
||||||
for i in CountableRange(r) sum = sum + i; // expected-error{{expected '{' to start the body of for-each loop}}
|
for i in CountableRange(r) sum = sum + i; // expected-error{{expected '{' to start the body of for-each loop}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,64 +140,81 @@ func missingWhileInRepeat() {
|
|||||||
func acceptsClosure<T>(t: T) -> Bool { return true }
|
func acceptsClosure<T>(t: T) -> Bool { return true }
|
||||||
|
|
||||||
func missingControllingExprInFor() {
|
func missingControllingExprInFor() {
|
||||||
for // expected-error {{expected initialization in a 'for' statement}}
|
for ; { // expected-error {{C-style for statement has been removed in Swift 3}}
|
||||||
|
|
||||||
for { // expected-error {{missing initialization in a 'for' statement}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for // expected-error {{missing initialization in a 'for' statement}}
|
for ; // expected-error {{C-style for statement has been removed in Swift 3}}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
for var i { // expected-error 2{{expected ';' in 'for' statement}} expected-error {{type annotation missing in pattern}}
|
for ; true { // expected-error {{C-style for statement has been removed in Swift 3}}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ; { // expected-error {{expected ';' in 'for' statement}}
|
for var i = 0; true { // expected-error {{C-style for statement has been removed in Swift 3}}
|
||||||
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: it would be better if this diagnostic appeared on the previous line.
|
|
||||||
for ;
|
|
||||||
{ // expected-error {{expected ';' in 'for' statement}}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; true { // expected-error {{expected ';' in 'for' statement}}
|
|
||||||
}
|
|
||||||
|
|
||||||
for var i = 0; true { // expected-error {{expected ';' in 'for' statement}}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The #if block is used to provide a scope for the for stmt to force it to end
|
|
||||||
// where necessary to provoke the crash.
|
|
||||||
#if true // <rdar://problem/21679557> compiler crashes on "for{{"
|
|
||||||
// expected-error @+2 {{missing initialization in a 'for' statement}}
|
|
||||||
// expected-note @+1 2 {{to match this opening '{'}}
|
|
||||||
for{{ // expected-error {{expression resolves to an unused function}}
|
|
||||||
#endif // expected-error 2 {{expected '}' at end of closure}}
|
|
||||||
|
|
||||||
#if true
|
|
||||||
// expected-error @+1 {{missing initialization in a 'for' statement}}
|
|
||||||
for{
|
|
||||||
var x = 42
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func missingControllingExprInForEach() {
|
func missingControllingExprInForEach() {
|
||||||
for in { // expected-error {{expected pattern}} expected-error {{expected Sequence expression for for-each loop}}
|
// expected-error @+3 {{expected pattern}}
|
||||||
}
|
// expected-error @+2 {{expected Sequence expression for for-each loop}}
|
||||||
|
// expected-error @+1 {{expected '{' to start the body of for-each loop}}
|
||||||
|
for
|
||||||
|
|
||||||
|
|
||||||
// expected-error @+4 {{expected 'in' after for-each pattern}}
|
|
||||||
// expected-error @+3 {{expected '{' to start the body of for-each loop}}
|
|
||||||
// expected-error @+2 {{expected pattern}}
|
// expected-error @+2 {{expected pattern}}
|
||||||
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for {
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+2 {{expected pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+2 {{expected 'in' after for-each pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for i {
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+2 {{expected 'in' after for-each pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for var i {
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+2 {{expected pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for in {
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+1 {{expected pattern}}
|
||||||
|
for 0..<12 {
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error @+3 {{expected pattern}}
|
||||||
|
// expected-error @+2 {{expected Sequence expression for for-each loop}}
|
||||||
|
// expected-error @+1 {{expected '{' to start the body of for-each loop}}
|
||||||
for for in { // expected-error {{expected pattern}} expected-error {{expected Sequence expression for for-each loop}}
|
for for in { // expected-error {{expected pattern}} expected-error {{expected Sequence expression for for-each loop}}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in { // expected-error {{expected Sequence expression for for-each loop}}
|
for i in { // expected-error {{expected Sequence expression for for-each loop}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The #if block is used to provide a scope for the for stmt to force it to end
|
||||||
|
// where necessary to provoke the crash.
|
||||||
|
#if true // <rdar://problem/21679557> compiler crashes on "for{{"
|
||||||
|
// expected-error @+2 {{expected pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for{{ // expected-note 2 {{to match this opening '{'}}
|
||||||
|
#endif // expected-error {{expected '}' at end of closure}} expected-error {{expected '}' at end of brace statement}}
|
||||||
|
|
||||||
|
#if true
|
||||||
|
// expected-error @+2 {{expected pattern}}
|
||||||
|
// expected-error @+1 {{expected Sequence expression for for-each loop}}
|
||||||
|
for{
|
||||||
|
var x = 42
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
func missingControllingExprInSwitch() {
|
func missingControllingExprInSwitch() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// RUN: %target-typecheck-verify-swift -parse-as-library
|
// RUN: %target-typecheck-verify-swift -parse-as-library
|
||||||
// RUN: %target-typecheck-verify-swift -parse-as-library -enable-astscope-lookup
|
// RUN: %target-typecheck-verify-swift -parse-as-library -enable-astscope-lookup
|
||||||
|
|
||||||
let x = 42 // expected-note{{did you mean 'x'?}}
|
let x = 42
|
||||||
x + x; // expected-error {{expressions are not allowed at the top level}} expected-warning {{result of operator '+' is unused}}
|
x + x; // expected-error {{expressions are not allowed at the top level}} expected-warning {{result of operator '+' is unused}}
|
||||||
x + x; // expected-error {{expressions are not allowed at the top level}} expected-warning {{result of operator '+' is unused}}
|
x + x; // expected-error {{expressions are not allowed at the top level}} expected-warning {{result of operator '+' is unused}}
|
||||||
// Make sure we don't crash on closures at the top level
|
// Make sure we don't crash on closures at the top level
|
||||||
@@ -10,9 +10,7 @@ x + x; // expected-error {{expressions are not allowed at the top level}} expect
|
|||||||
// expected-warning @-1 {{result of call is unused}}
|
// expected-warning @-1 {{result of call is unused}}
|
||||||
|
|
||||||
|
|
||||||
// FIXME: Too many errors for this.
|
// expected-error @+3 {{expected 'in' after for-each pattern}}
|
||||||
for i // expected-error 2 {{expected ';' in 'for' statement}}
|
// expected-error @+2 {{expected Sequence expression for for-each loop}}
|
||||||
// expected-error @-1{{use of unresolved identifier 'i'}}
|
// expected-error @+1 {{expected '{' to start the body of for-each loop}}
|
||||||
// expected-error @+3{{expected '{' in 'for' statement}}
|
for i
|
||||||
// expected-error @+2{{expected condition in 'for' statement}}
|
|
||||||
// expected-error @+1{{expected expression}}
|
|
||||||
|
|||||||
@@ -624,26 +624,16 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key.kind: source.lang.swift.stmt.for,
|
key.kind: source.lang.swift.stmt.foreach,
|
||||||
key.offset: 1132,
|
key.offset: 1132,
|
||||||
key.length: 37,
|
key.length: 37,
|
||||||
key.nameoffset: 0,
|
key.nameoffset: 0,
|
||||||
key.namelength: 0,
|
key.namelength: 0,
|
||||||
key.elements: [
|
key.elements: [
|
||||||
{
|
{
|
||||||
key.kind: source.lang.swift.structure.elem.init_expr,
|
key.kind: source.lang.swift.structure.elem.id,
|
||||||
key.offset: 1136,
|
key.offset: 1136,
|
||||||
key.length: 17
|
key.length: 5
|
||||||
},
|
|
||||||
{
|
|
||||||
key.kind: source.lang.swift.structure.elem.expr,
|
|
||||||
key.offset: 1155,
|
|
||||||
key.length: 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key.kind: source.lang.swift.structure.elem.expr,
|
|
||||||
key.offset: 1163,
|
|
||||||
key.length: 3
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
key.substructure: [
|
key.substructure: [
|
||||||
@@ -984,6 +974,20 @@
|
|||||||
key.severity: source.diagnostic.severity.error,
|
key.severity: source.diagnostic.severity.error,
|
||||||
key.description: "getter/setter can only be defined for a single variable",
|
key.description: "getter/setter can only be defined for a single variable",
|
||||||
key.diagnostic_stage: source.diagnostic.stage.swift.parse
|
key.diagnostic_stage: source.diagnostic.stage.swift.parse
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key.line: 77,
|
||||||
|
key.column: 1,
|
||||||
|
key.filepath: main.swift,
|
||||||
|
key.severity: source.diagnostic.severity.error,
|
||||||
|
key.description: "C-style for statement has been removed in Swift 3",
|
||||||
|
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
|
||||||
|
key.ranges: [
|
||||||
|
{
|
||||||
|
key.offset: 1136,
|
||||||
|
key.length: 30
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,25 @@
|
|||||||
// RUN: %target-typecheck-verify-swift -typecheck %s
|
// RUN: %target-typecheck-verify-swift -typecheck %s
|
||||||
|
|
||||||
for var i = 0; i < 10; i++ {}
|
for var i = 0; i < 10; i++ {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{14-20= ..< }} {{22-27=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
// expected-error @-2 {{unary operator '++' cannot be applied}}
|
|
||||||
// expected-note @-3 {{overloads for '++' exist}}
|
|
||||||
|
|
||||||
for var i = 0; i < 10; i += 1 {}
|
for var i = 0; i < 10; i += 1 {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{14-20= ..< }} {{22-30=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
|
|
||||||
for var i = 0; i <= 10; i++ {}
|
for var i = 0; i <= 10; i++ {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{14-21= ... }} {{23-28=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
// expected-error @-2 {{unary operator '++' cannot be applied}}
|
|
||||||
// expected-note @-3 {{overloads for '++' exist}}
|
|
||||||
|
|
||||||
for var i = 0; i <= 10; i += 1 {}
|
for var i = 0; i <= 10; i += 1 {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{14-21= ... }} {{23-31=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
|
|
||||||
for var i = 10; i > 0; i-- {}
|
for var i = 10; i > 0; i-- {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{13-13=((0 + 1)...}} {{15-15=).reversed()}} {{15-27=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
// expected-error @-2 {{unary operator '--' cannot be applied}}
|
|
||||||
// expected-note @-3 {{overloads for '--' exist}}
|
|
||||||
|
|
||||||
for var i = 10; i > 0; i -= 1 {}
|
for var i = 10; i > 0; i -= 1 {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{13-13=((0 + 1)...}} {{15-15=).reversed()}} {{15-30=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
|
|
||||||
for var i = 10; i >= 0; i-- {}
|
for var i = 10; i >= 0; i-- {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{13-13=(0...}} {{15-15=).reversed()}} {{15-28=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
// expected-error @-2 {{unary operator '--' cannot be applied}}
|
|
||||||
// expected-note @-3 {{overloads for '--' exist}}
|
|
||||||
|
|
||||||
for var i = 10; i >= 0; i -= 1 {}
|
for var i = 10; i >= 0; i -= 1 {}
|
||||||
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{5-9=}} {{10-13= in }} {{13-13=(0...}} {{15-15=).reversed()}} {{15-31=}}
|
// expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}}
|
||||||
|
|||||||
Reference in New Issue
Block a user