aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-10-12 16:37:45 +0000
committerDouglas Gregor <dgregor@apple.com>2011-10-12 16:37:45 +0000
commit4a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41b (patch)
tree51429fab5effd4a81368c423996e314d702e1bad /lib/Parse
parentd41679d6881d2b424d8b3600fc774308087735a7 (diff)
Introduce BalancedDelimiterTracker, to better track open/close
delimiter pairs and detect when we exceed the implementation limit for nesting depth, from Aaron Ballman! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141782 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseDecl.cpp148
-rw-r--r--lib/Parse/ParseDeclCXX.cpp125
-rw-r--r--lib/Parse/ParseExpr.cpp113
-rw-r--r--lib/Parse/ParseExprCXX.cpp231
-rw-r--r--lib/Parse/ParseInit.cpp23
-rw-r--r--lib/Parse/ParseObjc.cpp65
-rw-r--r--lib/Parse/ParseStmt.cpp82
-rw-r--r--lib/Parse/Parser.cpp107
8 files changed, 502 insertions, 392 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6de9e1b4eb..228e53c4f0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -564,12 +564,11 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
AvailabilityChange Changes[Unknown];
// Opening '('.
- SourceLocation LParenLoc;
- if (!Tok.is(tok::l_paren)) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
Diag(Tok, diag::err_expected_lparen);
return;
}
- LParenLoc = ConsumeParen();
// Parse the platform name,
if (Tok.isNot(tok::identifier)) {
@@ -667,12 +666,11 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
} while (true);
// Closing ')'.
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- if (RParenLoc.isInvalid())
+ if (T.consumeClose())
return;
if (endLoc)
- *endLoc = RParenLoc;
+ *endLoc = T.getCloseLocation();
// The 'unavailable' availability cannot be combined with any other
// availability changes. Make sure that hasn't happened.
@@ -694,7 +692,8 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
}
// Record this attribute
- attrs.addNew(&Availability, SourceRange(AvailabilityLoc, RParenLoc),
+ attrs.addNew(&Availability,
+ SourceRange(AvailabilityLoc, T.getCloseLocation()),
0, SourceLocation(),
Platform, PlatformLoc,
Changes[Introduced],
@@ -840,8 +839,8 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
SourceLocation *EndLoc) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
- SourceLocation LeftParenLoc = Tok.getLocation();
- ConsumeParen();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
ExprVector ArgExprs(Actions);
bool ArgExprsOk = true;
@@ -851,7 +850,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
ArgExprsOk = false;
- MatchRHSPunctuation(tok::r_paren, LeftParenLoc);
+ T.consumeClose();
break;
} else {
ArgExprs.push_back(ArgExpr.release());
@@ -861,13 +860,12 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
ConsumeToken(); // Eat the comma, move to the next argument
}
// Match the ')'.
- if (ArgExprsOk && Tok.is(tok::r_paren)) {
- if (EndLoc)
- *EndLoc = Tok.getLocation();
- ConsumeParen();
+ if (ArgExprsOk && !T.consumeClose()) {
Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
ArgExprs.take(), ArgExprs.size());
}
+ if (EndLoc)
+ *EndLoc = T.getCloseLocation();
}
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
@@ -1241,7 +1239,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
- SourceLocation LParenLoc = ConsumeParen();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+
ExprVector Exprs(Actions);
CommaLocsTy CommaLocs;
@@ -1259,7 +1259,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
}
} else {
// Match the ')'.
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ T.consumeClose();
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
"Unexpected number of commas!");
@@ -1269,9 +1269,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
ExitScope();
}
- Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
+ Actions.AddCXXDirectInitializerToDecl(ThisDecl, T.getOpenLocation(),
move_arg(Exprs),
- RParenLoc,
+ T.getCloseLocation(),
TypeContainsAuto);
}
} else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
@@ -1532,24 +1532,24 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation KWLoc = Tok.getLocation();
ConsumeToken();
- SourceLocation ParamLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen))
return;
- ExprResult ArgExpr = ParseAlignArgument(ParamLoc);
+ ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation());
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren);
return;
}
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, ParamLoc);
+ T.consumeClose();
if (endLoc)
- *endLoc = RParenLoc;
+ *endLoc = T.getCloseLocation();
ExprVector ArgExprs(Actions);
ArgExprs.push_back(ArgExpr.release());
Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc,
- 0, ParamLoc, ArgExprs.take(), 1, false, true);
+ 0, T.getOpenLocation(), ArgExprs.take(), 1, false, true);
}
/// ParseDeclarationSpecifiers
@@ -2626,7 +2626,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
"parsing struct/union body");
- SourceLocation LBraceLoc = ConsumeBrace();
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ if (T.consumeOpen())
+ return;
ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
@@ -2712,7 +2714,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
}
}
- SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ T.consumeClose();
ParsedAttributes attrs(AttrFactory);
// If attributes exist after struct contents, parse them.
@@ -2720,10 +2722,11 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
Actions.ActOnFields(getCurScope(),
RecordLoc, TagDecl, FieldDecls,
- LBraceLoc, RBraceLoc,
+ T.getOpenLocation(), T.getCloseLocation(),
attrs.getList());
StructScope.Exit();
- Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl,
+ T.getCloseLocation());
}
/// ParseEnumSpecifier
@@ -2994,7 +2997,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
ParseScope EnumScope(this, Scope::DeclScope);
Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
- SourceLocation LBraceLoc = ConsumeBrace();
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
@@ -3051,18 +3055,20 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
}
// Eat the }.
- SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ T.consumeClose();
// If attributes exist after the identifier list, parse them.
ParsedAttributes attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
- Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
- EnumConstantDecls.data(), EnumConstantDecls.size(),
- getCurScope(), attrs.getList());
+ Actions.ActOnEnumBody(StartLoc, T.getOpenLocation(), T.getCloseLocation(),
+ EnumDecl, EnumConstantDecls.data(),
+ EnumConstantDecls.size(), getCurScope(),
+ attrs.getList());
EnumScope.Exit();
- Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc);
+ Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,
+ T.getCloseLocation());
}
/// isTypeSpecifierQualifier - Return true if the current token could be the
@@ -3877,7 +3883,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
break;
}
ParsedAttributes attrs(AttrFactory);
- ParseFunctionDeclarator(ConsumeParen(), D, attrs);
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+ ParseFunctionDeclarator(D, attrs, T);
} else if (Tok.is(tok::l_square)) {
ParseBracketDeclarator(D);
} else {
@@ -3900,7 +3908,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
/// parameter-type-list[opt] ')'
///
void Parser::ParseParenDeclarator(Declarator &D) {
- SourceLocation StartLoc = ConsumeParen();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+
assert(!D.isPastIdentifier() && "Should be called before passing identifier");
// Eat any attributes before we look at whether this is a grouping or function
@@ -3963,9 +3973,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
// Match the ')'.
- SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc);
- D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc),
- attrs, EndLoc);
+ T.consumeClose();
+ D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(),
+ T.getCloseLocation()),
+ attrs, T.getCloseLocation());
D.setGroupingParens(hadGroupingParens);
return;
@@ -3977,7 +3988,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// ParseFunctionDeclarator to handle of argument list.
D.SetIdentifier(0, Tok.getLocation());
- ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg);
+ ParseFunctionDeclarator(D, attrs, T, RequiresArg);
}
/// ParseFunctionDeclarator - We are after the identifier and have parsed the
@@ -3998,8 +4009,9 @@ void Parser::ParseParenDeclarator(Declarator &D) {
/// dynamic-exception-specification
/// noexcept-specification
///
-void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
+void Parser::ParseFunctionDeclarator(Declarator &D,
ParsedAttributes &attrs,
+ BalancedDelimiterTracker &Tracker,
bool RequiresArg) {
// lparen is already consumed!
assert(D.isPastIdentifier() && "Should not call before identifier!");
@@ -4023,14 +4035,14 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
ParsedType TrailingReturnType;
SourceLocation EndLoc;
-
if (isFunctionDeclaratorIdentifierList()) {
if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
ParseFunctionDeclaratorIdentifierList(D, ParamInfo);
- EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ Tracker.consumeClose();
+ EndLoc = Tracker.getCloseLocation();
} else {
// Enter function-declaration scope, limiting any declarators to the
// function prototype scope, including parameter declarators.
@@ -4045,7 +4057,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
HasProto = ParamInfo.size() || getLang().CPlusPlus;
// If we have the closing ')', eat it.
- EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ Tracker.consumeClose();
+ EndLoc = Tracker.getCloseLocation();
if (getLang().CPlusPlus) {
MaybeParseCXX0XAttributes(attrs);
@@ -4101,7 +4114,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : 0,
- LParenLoc, EndLoc, D,
+ Tracker.getOpenLocation(),
+ EndLoc, D,
TrailingReturnType),
attrs, EndLoc);
}
@@ -4235,7 +4249,7 @@ void Parser::ParseParameterDeclarationClause(
// Parse the declaration-specifiers.
// Just use the ParsingDeclaration "scope" of the declarator.
DeclSpec DS(AttrFactory);
-
+
// Skip any Microsoft attributes before a param.
if (getLang().MicrosoftExt && Tok.is(tok::l_square))
ParseMicrosoftAttributes(DS.getAttributes());
@@ -4369,20 +4383,22 @@ void Parser::ParseParameterDeclarationClause(
/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
void Parser::ParseBracketDeclarator(Declarator &D) {
- SourceLocation StartLoc = ConsumeBracket();
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
// C array syntax has many features, but by-far the most common is [] and [4].
// This code does a fast path to handle some of the most obvious cases.
if (Tok.getKind() == tok::r_square) {
- SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ T.consumeClose();
ParsedAttributes attrs(AttrFactory);
MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed the empty array type.
ExprResult NumElements;
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
- StartLoc, EndLoc),
- attrs, EndLoc);
+ T.getOpenLocation(),
+ T.getCloseLocation()),
+ attrs, T.getCloseLocation());
return;
} else if (Tok.getKind() == tok::numeric_constant &&
GetLookAheadToken(1).is(tok::r_square)) {
@@ -4390,15 +4406,16 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
ExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
ConsumeToken();
- SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ T.consumeClose();
ParsedAttributes attrs(AttrFactory);
MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0,
ExprRes.release(),
- StartLoc, EndLoc),
- attrs, EndLoc);
+ T.getOpenLocation(),
+ T.getCloseLocation()),
+ attrs, T.getCloseLocation());
return;
}
@@ -4455,7 +4472,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
return;
}
- SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ T.consumeClose();
ParsedAttributes attrs(AttrFactory);
MaybeParseCXX0XAttributes(attrs);
@@ -4464,8 +4481,9 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
StaticLoc.isValid(), isStar,
NumElements.release(),
- StartLoc, EndLoc),
- attrs, EndLoc);
+ T.getOpenLocation(),
+ T.getCloseLocation()),
+ attrs, T.getCloseLocation());
}
/// [GNU] typeof-specifier:
@@ -4530,10 +4548,8 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
assert(Tok.is(tok::kw__Atomic) && "Not an atomic specifier");
SourceLocation StartLoc = ConsumeToken();
- SourceLocation LParenLoc = Tok.getLocation();
-
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
- "_Atomic")) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "_Atomic")) {
SkipUntil(tok::r_paren);
return;
}
@@ -4545,17 +4561,13 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
}
// Match the ')'
- SourceLocation RParenLoc;
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ T.consumeClose();
- if (RParenLoc.isInvalid())
+ if (T.getCloseLocation().isInvalid())
return;
- DS.setTypeofParensRange(SourceRange(LParenLoc, RParenLoc));
- DS.SetRangeEnd(RParenLoc);
+ DS.setTypeofParensRange(T.getRange());
+ DS.SetRangeEnd(T.getCloseLocation());
const char *PrevSpec = 0;
unsigned DiagID;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 45e6251559..51cdf6b64e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -95,7 +95,8 @@ Decl *Parser::ParseNamespace(unsigned Context,
}
- if (Tok.isNot(tok::l_brace)) {
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ if (T.consumeOpen()) {
if (!ExtraIdent.empty()) {
Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon)
<< SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
@@ -105,8 +106,6 @@ Decl *Parser::ParseNamespace(unsigned Context,
return 0;
}
- SourceLocation LBrace = ConsumeBrace();
-
if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||
getCurScope()->getFnParent()) {
@@ -114,7 +113,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon)
<< SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
}
- Diag(LBrace, diag::err_namespace_nonnamespace_scope);
+ Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace, false);
return 0;
}
@@ -157,23 +156,23 @@ Decl *Parser::ParseNamespace(unsigned Context,
Decl *NamespcDecl =
Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc,
- IdentLoc, Ident, LBrace, attrs.getList());
+ IdentLoc, Ident, T.getOpenLocation(),
+ attrs.getList());
PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
"parsing namespace");
- SourceLocation RBraceLoc;
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
- InlineLoc, LBrace, attrs, RBraceLoc);
+ InlineLoc, attrs, T);
// Leave the namespace scope.
NamespaceScope.Exit();
- Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
+ DeclEnd = T.getCloseLocation();
+ Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);
- DeclEnd = RBraceLoc;
return NamespcDecl;
}
@@ -182,9 +181,8 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
std::vector<IdentifierInfo*>& Ident,
std::vector<SourceLocation>& NamespaceLoc,
unsigned int index, SourceLocation& InlineLoc,
- SourceLocation& LBrace,
ParsedAttributes& attrs,
- SourceLocation& RBraceLoc) {
+ BalancedDelimiterTracker &Tracker) {
if (index == Ident.size()) {
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -192,7 +190,10 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
MaybeParseMicrosoftAttributes(attrs);
ParseExternalDeclaration(attrs);
}
- RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);
+
+ // The caller is what called check -- we are simply calling
+ // the close for it.
+ Tracker.consumeClose();
return;
}
@@ -202,14 +203,15 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
Decl *NamespcDecl =
Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(),
NamespaceLoc[index], IdentLoc[index],
- Ident[index], LBrace, attrs.getList());
+ Ident[index], Tracker.getOpenLocation(),
+ attrs.getList());
ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
- LBrace, attrs, RBraceLoc);
+ attrs, Tracker);
NamespaceScope.Exit();
- Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
+ Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
}
/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
@@ -298,7 +300,8 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
ProhibitAttributes(attrs);
- SourceLocation LBrace = ConsumeBrace();
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX0XAttributes(attrs);
@@ -306,9 +309,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
ParseExternalDeclaration(attrs);
}
- SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+ T.consumeClose();
return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
- RBrace);
+ T.getCloseLocation());
}
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
@@ -585,13 +588,12 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
SourceLocation StaticAssertLoc = ConsumeToken();
- if (Tok.isNot(tok::l_paren)) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
Diag(Tok, diag::err_expected_lparen);
return 0;
}
- SourceLocation LParenLoc = ConsumeParen();
-
ExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipUntil(tok::semi);
@@ -611,7 +613,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
if (AssertMessage.isInvalid())
return 0;
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ T.consumeClose();
DeclEnd = Tok.getLocation();
ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);
@@ -619,7 +621,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
AssertExpr.take(),
AssertMessage.take(),
- RParenLoc);
+ T.getCloseLocation());
}
/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
@@ -630,11 +632,9 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
SourceLocation StartLoc = ConsumeToken();
- SourceLocation LParenLoc = Tok.getLocation();
-
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
- "decltype")) {
- SkipUntil(tok::r_paren);
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ "decltype", tok::r_paren)) {
return;
}
@@ -651,13 +651,8 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
}
// Match the ')'
- SourceLocation RParenLoc;
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
- if (RParenLoc.isInvalid())
+ T.consumeClose();
+ if (T.getCloseLocation().isInvalid())
return;
const char *PrevSpec = 0;
@@ -673,11 +668,9 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
"Not an underlying type specifier");
SourceLocation StartLoc = ConsumeToken();
- SourceLocation LParenLoc = Tok.getLocation();
-
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
- "__underlying_type")) {
- SkipUntil(tok::r_paren);
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ "__underlying_type", tok::r_paren)) {
return;
}
@@ -688,13 +681,8 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
}
// Match the ')'
- SourceLocation RParenLoc;
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
- if (RParenLoc.isInvalid())
+ T.consumeClose();
+ if (T.getCloseLocation().isInvalid())
return;
const char *PrevSpec = 0;
@@ -2106,12 +2094,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
}
assert(Tok.is(tok::l_brace));
-
- SourceLocation LBraceLoc = ConsumeBrace();
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
if (TagDecl)
Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,
- LBraceLoc);
+ T.getOpenLocation());
// C++ 11p3: Members of a class defined with the keyword class are private
// by default. Members of a class defined with the keywords struct or union
@@ -2122,7 +2110,6 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
else
CurAS = AS_public;
- SourceLocation RBraceLoc;
if (TagDecl) {
// While we still have something to read, read the member-declarations.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@@ -2163,7 +2150,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
ParseCXXClassMemberDeclaration(CurAS);
}
- RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ T.consumeClose();
} else {
SkipUntil(tok::r_brace, false, false);
}
@@ -2174,7 +2161,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl)
Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,
- LBraceLoc, RBraceLoc,
+ T.getOpenLocation(),
+ T.getCloseLocation(),
attrs.getList());
// C++0x [class.mem]p2: Within the class member-specification, the class is
@@ -2198,7 +2186,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
}
if (TagDecl)
- Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl,
+ T.getCloseLocation());
// Leave the class scope.
ParsingDef.Pop();
@@ -2323,7 +2312,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
TemplateTypeTy, IdLoc, InitList.take(),
EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
- SourceLocation LParenLoc = ConsumeParen();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
// Parse the optional expression-list.
ExprVector ArgExprs(Actions);
@@ -2333,7 +2323,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return true;
}
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ T.consumeClose();
SourceLocation EllipsisLoc;
if (Tok.is(tok::ellipsis))
@@ -2341,8 +2331,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, IdLoc,
- LParenLoc, ArgExprs.take(),
- ArgExprs.size(), RParenLoc,
+ T.getOpenLocation(), ArgExprs.take(),
+ ArgExprs.size(), T.getCloseLocation(),
EllipsisLoc);
}
@@ -2388,7 +2378,8 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange,
SourceLocation KeywordLoc = ConsumeToken();
if (Tok.is(tok::l_paren)) {
// There is an argument.
- SourceLocation LParenLoc = ConsumeParen();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
NoexceptType = EST_ComputedNoexcept;
NoexceptExpr = ParseConstantExpression();
// The argument must be contextually convertible to bool. We use
@@ -2396,8 +2387,8 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange,
if (!NoexceptExpr.isInvalid())
NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc,
NoexceptExpr.get());
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- NoexceptRange = SourceRange(KeywordLoc, RParenLoc);
+ T.consumeClose();
+ NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
} else {
// There is no argument.
NoexceptType = EST_BasicNoexcept;
@@ -2440,13 +2431,12 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
assert(Tok.is(tok::kw_throw) && "expected throw");
SpecificationRange.setBegin(ConsumeToken());
-
- if (!Tok.is(tok::l_paren)) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
Diag(Tok, diag::err_expected_lparen_after) << "throw";
SpecificationRange.setEnd(SpecificationRange.getBegin());
return EST_DynamicNone;
}
- SourceLocation LParenLoc = ConsumeParen();
// Parse throw(...), a Microsoft extension that means "this function
// can throw anything".
@@ -2454,8 +2444,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
SourceLocation EllipsisLoc = ConsumeToken();
if (!getLang().MicrosoftExt)
Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- SpecificationRange.setEnd(RParenLoc);
+ T.consumeClose();
+ SpecificationRange.setEnd(T.getCloseLocation());
return EST_MSAny;
}
@@ -2485,7 +2475,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
break;
}
- SpecificationRange.setEnd(MatchRHSPunctuation(tok::r_paren, LParenLoc));
+ T.consumeClose();
+ SpecificationRange.setEnd(T.getCloseLocation());
return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 738040103f..548a599f6e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1028,18 +1028,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
SourceLocation KeyLoc = ConsumeToken();
- SourceLocation LParen = Tok.getLocation();
- if (ExpectAndConsume(tok::l_paren,
- diag::err_expected_lparen_after, "noexcept"))
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept"))
return ExprError();
// C++ [expr.unary.noexcept]p1:
// The noexcept operator determines whether the evaluation of its operand,
// which is an unevaluated operand, can throw an exception.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
ExprResult Result = ParseExpression();
- SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ T.consumeClose();
+
if (!Result.isInvalid())
- Result = Actions.ActOnNoexceptExpr(KeyLoc, LParen, Result.take(), RParen);
+ Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
+ Result.take(), T.getCloseLocation());
return move(Result);
}
@@ -1198,8 +1201,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (getLang().ObjC1 && Tok.isAtStartOfLine() &&
isSimpleObjCMessageExpression())
return move(LHS);
-
- Loc = ConsumeBracket();
+
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+ Loc = T.getOpenLocation();
ExprResult Idx;
if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))
Idx = ParseBraceInitializer();
@@ -1215,7 +1220,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = ExprError();
// Match the ']'.
- MatchRHSPunctuation(tok::r_square, Loc);
+ T.consumeClose();
break;
}
@@ -1227,12 +1232,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
Expr *ExecConfig = 0;
+ BalancedDelimiterTracker LLLT(*this, tok::lesslessless);
+ BalancedDelimiterTracker PT(*this, tok::l_paren);
+
if (OpKind == tok::lesslessless) {
ExprVector ExecConfigExprs(Actions);
CommaLocsTy ExecConfigCommaLocs;
- SourceLocation LLLLoc, GGGLoc;
-
- LLLLoc = ConsumeToken();
+ LLLT.consumeOpen();
if (ParseExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
LHS = ExprError();
@@ -1240,11 +1246,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid()) {
SkipUntil(tok::greatergreatergreater);
- } else if (Tok.isNot(tok::greatergreatergreater)) {
- MatchRHSPunctuation(tok::greatergreatergreater, LLLLoc);
+ } else if (LLLT.consumeClose()) {
+ // There was an error closing the brackets
LHS = ExprError();
- } else {
- GGGLoc = ConsumeToken();
}
if (!LHS.isInvalid()) {
@@ -1256,14 +1260,17 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (!LHS.isInvalid()) {
ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
- LLLLoc, move_arg(ExecConfigExprs), GGGLoc);
+ LLLT.getOpenLocation(),
+ move_arg(ExecConfigExprs),
+ LLLT.getCloseLocation());
if (ECResult.isInvalid())
LHS = ExprError();
else
ExecConfig = ECResult.get();