Skip to content

Commit 72b1e27

Browse files
author
David Ungar
authored
Merge pull request #26768 from davidungar/A-8-21-parserPR
[Parser, NameLookup, ASTScope] Parser changes for lazy ASTScopes
2 parents d80b1d3 + 35e8218 commit 72b1e27

File tree

7 files changed

+80
-13
lines changed

7 files changed

+80
-13
lines changed

include/swift/AST/Expr.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,11 +926,13 @@ class TapExpr : public Expr {
926926
void setBody(BraceStmt * b) { Body = b; }
927927

928928
SourceLoc getLoc() const { return SubExpr ? SubExpr->getLoc() : SourceLoc(); }
929-
930-
SourceRange getSourceRange() const {
931-
return SubExpr ? SubExpr->getSourceRange() : SourceRange();
929+
930+
SourceLoc getStartLoc() const {
931+
return SubExpr ? SubExpr->getStartLoc() : SourceLoc();
932932
}
933933

934+
SourceLoc getEndLoc() const;
935+
934936
static bool classof(const Expr *E) {
935937
return E->getKind() == ExprKind::Tap;
936938
}
@@ -1027,6 +1029,8 @@ class InterpolatedStringLiteralExpr : public LiteralExpr {
10271029
// token, so the range should be (Start == End).
10281030
return Loc;
10291031
}
1032+
1033+
/// Could also be computed by relexing.
10301034
SourceLoc getTrailingQuoteLoc() const {
10311035
return TrailingQuoteLoc;
10321036
}

include/swift/Parse/Parser.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ class Parser {
571571

572572
/// Retrieve the location just past the end of the previous
573573
/// source location.
574-
SourceLoc getEndOfPreviousLoc();
574+
SourceLoc getEndOfPreviousLoc() const;
575575

576576
/// If the current token is the specified kind, consume it and
577577
/// return true. Otherwise, return false without consuming it.
@@ -812,6 +812,19 @@ class Parser {
812812
bool parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
813813
SourceLoc OtherLoc);
814814

815+
/// Returns the proper location for a missing right brace, parenthesis, etc.
816+
SourceLoc getLocForMissingMatchingToken() const;
817+
818+
/// When encountering an error or a missing matching token (e.g. '}'), return
819+
/// the location to use for it. This value should be at the last token in
820+
/// the ASTNode being parsed so that it nests within any enclosing nodes, and,
821+
/// for ASTScope lookups, it does not preceed any identifiers to be looked up.
822+
/// However, the latter case does not hold when parsing an interpolated
823+
/// string literal because there may be identifiers to be looked up in the
824+
/// literal and their locations will not precede the location of a missing
825+
/// close brace.
826+
SourceLoc getErrorOrMissingLoc() const;
827+
815828
/// Parse a comma separated list of some elements.
816829
ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
817830
bool AllowSepAfterLast, Diag<> ErrorDiag,
@@ -1068,6 +1081,9 @@ class Parser {
10681081

10691082
ParserResult<TypeRepr> parseDeclResultType(Diag<> MessageID);
10701083

1084+
/// Get the location for a type error.
1085+
SourceLoc getTypeErrorLoc() const;
1086+
10711087
//===--------------------------------------------------------------------===//
10721088
// Type Parsing
10731089

lib/AST/ASTVerifier.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3646,7 +3646,9 @@ class Verifier : public ASTWalker {
36463646
if (D->isImplicit())
36473647
return;
36483648
// FIXME: This is not working well for decl parents.
3649-
return;
3649+
// But it must work when using lazy ASTScopes for IterableDeclContexts
3650+
if (!isa<IterableDeclContext>(D))
3651+
return;
36503652
} else if (Stmt *S = Parent.getAsStmt()) {
36513653
Enclosing = S->getSourceRange();
36523654
if (S->isImplicit())

lib/AST/Expr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,20 @@ VarDecl * TapExpr::getVar() const {
22272227
return dyn_cast<VarDecl>(Body->getElement(0).dyn_cast<Decl *>());
22282228
}
22292229

2230+
SourceLoc TapExpr::getEndLoc() const {
2231+
// Include the body in the range, assuming the body follows the SubExpr.
2232+
// Also, be (perhaps overly) defensive about null pointers & invalid
2233+
// locations.
2234+
if (auto *const b = getBody()) {
2235+
const auto be = b->getEndLoc();
2236+
if (be.isValid())
2237+
return be;
2238+
}
2239+
if (auto *const se = getSubExpr())
2240+
return se->getEndLoc();
2241+
return SourceLoc();
2242+
}
2243+
22302244
// See swift/Basic/Statistic.h for declaration: this enables tracing Exprs, is
22312245
// defined here to avoid too much layering violation / circular linkage
22322246
// dependency.

lib/Parse/ParseExpr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,9 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
19921992
llvm::SaveAndRestore<Token> SavedTok(Tok);
19931993
llvm::SaveAndRestore<ParsedTrivia> SavedLeadingTrivia(LeadingTrivia);
19941994
llvm::SaveAndRestore<ParsedTrivia> SavedTrailingTrivia(TrailingTrivia);
1995+
// For errors, we need the real PreviousLoc, i.e. the start of the
1996+
// whole InterpolatedStringLiteral.
1997+
llvm::SaveAndRestore<SourceLoc> SavedPreviousLoc(PreviousLoc);
19951998

19961999
// We're not in a place where an interpolation would be valid.
19972000
if (!CurLocalContext) {
@@ -3426,7 +3429,8 @@ ParserResult<Expr> Parser::parseExprCollection() {
34263429

34273430
if (Status.isError()) {
34283431
// If we've already got errors, don't emit missing RightK diagnostics.
3429-
RSquareLoc = Tok.is(tok::r_square) ? consumeToken() : PreviousLoc;
3432+
RSquareLoc = Tok.is(tok::r_square) ? consumeToken()
3433+
: getLocForMissingMatchingToken();
34303434
} else if (parseMatchingToken(tok::r_square, RSquareLoc,
34313435
diag::expected_rsquare_array_expr,
34323436
LSquareLoc)) {

lib/Parse/ParseType.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
520520
auto diag = diagnose(Tok, diag::extra_rbracket);
521521
diag.fixItInsert(result.get()->getStartLoc(), getTokenText(tok::l_square));
522522
consumeToken();
523-
return makeParserErrorResult(new (Context) ErrorTypeRepr(Tok.getLoc()));
523+
return makeParserErrorResult(new (Context)
524+
ErrorTypeRepr(getTypeErrorLoc()));
524525
} else if (!result.isParseError() && Tok.is(tok::colon)) {
525526
auto colonTok = consumeToken();
526527
auto secondType = parseType(diag::expected_dictionary_value_type);
@@ -534,11 +535,17 @@ ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
534535
diag.fixItInsertAfter(secondType.get()->getEndLoc(), getTokenText(tok::r_square));
535536
}
536537
}
537-
return makeParserErrorResult(new (Context) ErrorTypeRepr(Tok.getLoc()));
538+
return makeParserErrorResult(new (Context)
539+
ErrorTypeRepr(getTypeErrorLoc()));
538540
}
539541
return result;
540542
}
541543

544+
SourceLoc Parser::getTypeErrorLoc() const {
545+
// Use the same location as a missing close brace, etc.
546+
return getErrorOrMissingLoc();
547+
}
548+
542549
ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &Args,
543550
SourceLoc &LAngleLoc,
544551
SourceLoc &RAngleLoc) {

lib/Parse/Parser.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ ParsedTokenSyntax Parser::consumeTokenSyntax() {
596596
return ParsedToken;
597597
}
598598

599-
SourceLoc Parser::getEndOfPreviousLoc() {
599+
SourceLoc Parser::getEndOfPreviousLoc() const {
600600
return Lexer::getLocForEndOfToken(SourceMgr, PreviousLoc);
601601
}
602602

@@ -968,8 +968,6 @@ bool Parser::parseToken(tok K, SourceLoc &TokLoc, const Diagnostic &D) {
968968
return true;
969969
}
970970

971-
/// Parse the specified expected token and return its location on success. On failure, emit the specified
972-
/// error diagnostic, a note at the specified note location, and return the location of the previous token.
973971
bool Parser::parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
974972
SourceLoc OtherLoc) {
975973
Diag<> OtherNote;
@@ -982,13 +980,34 @@ bool Parser::parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
982980
if (parseToken(K, TokLoc, ErrorDiag)) {
983981
diagnose(OtherLoc, OtherNote);
984982

985-
TokLoc = PreviousLoc;
983+
TokLoc = getLocForMissingMatchingToken();
986984
return true;
987985
}
988986

989987
return false;
990988
}
991989

990+
SourceLoc Parser::getLocForMissingMatchingToken() const {
991+
// At present, use the same location whether it's an error or whether
992+
// the matching token is missing.
993+
// Both cases supply a location for something the user didn't type.
994+
return getErrorOrMissingLoc();
995+
}
996+
997+
SourceLoc Parser::getErrorOrMissingLoc() const {
998+
// The next token might start a new enclosing construct,
999+
// and SourceLoc's are always at the start of a token (for example, for
1000+
// fixits, so use the previous token's SourceLoc and allow a subnode to end
1001+
// right at the same place as its supernode.
1002+
1003+
// The tricky case is when the previous token is an InterpolatedStringLiteral.
1004+
// Then, there will be names in scope whose SourceLoc is *after* the
1005+
// the location of a missing close brace.
1006+
// ASTScope tree creation will have to cope.
1007+
1008+
return PreviousLoc;
1009+
}
1010+
9921011
static SyntaxKind getListElementKind(SyntaxKind ListKind) {
9931012
switch (ListKind) {
9941013
case SyntaxKind::FunctionCallArgumentList:
@@ -1094,7 +1113,8 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
10941113

10951114
if (Status.isError()) {
10961115
// If we've already got errors, don't emit missing RightK diagnostics.
1097-
RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
1116+
RightLoc =
1117+
Tok.is(RightK) ? consumeToken() : getLocForMissingMatchingToken();
10981118
} else if (parseMatchingToken(RightK, RightLoc, ErrorDiag, LeftLoc)) {
10991119
Status.setIsParseError();
11001120
}

0 commit comments

Comments
 (0)