Introduce BalancedDelimiterTracker, to better track open/close

delimiter pairs and detect when we exceed the implementation limit for
nesting depth, from Aaron Ballman!

llvm-svn: 141782
This commit is contained in:
Douglas Gregor 2011-10-12 16:37:45 +00:00
parent d74c0e7c14
commit e7a8e3b612
12 changed files with 597 additions and 404 deletions

View File

@ -1810,7 +1810,7 @@ focus on expressions, but statements are similar.</p>
<li>Write tests for all of the "bad" parsing cases, to make sure
your recovery is good. If you have matched delimiters (e.g.,
parentheses, square brackets, etc.), use
<tt>Parser::MatchRHSPunctuation</tt> to give nice diagnostics when
<tt>Parser::BalancedDelimiterTracker</tt> to give nice diagnostics when
things go wrong.</li>
</ul>
</li>

View File

@ -354,6 +354,8 @@ def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<
"unexpected end of default argument expression">;
def err_parser_impl_limit_overflow : Error<
"parser recursion limit reached, program too complex">, DefaultFatal;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;

View File

@ -409,6 +409,84 @@ private:
return PP.LookAhead(0);
}
/// \brief Tracks information about the current nesting depth of
/// opening delimiters of each kind.
class DelimiterTracker {
private:
friend class Parser;
unsigned Paren, Brace, Square, Less, LLLess;
unsigned& get(tok::TokenKind t) {
switch (t) {
default: llvm_unreachable("Unexpected balanced token");
case tok::l_brace: return Brace;
case tok::l_paren: return Paren;
case tok::l_square: return Square;
case tok::less: return Less;
case tok::lesslessless: return LLLess;
}
}
void push(tok::TokenKind t) {
get(t)++;
}
void pop(tok::TokenKind t) {
get(t)--;
}
unsigned getDepth(tok::TokenKind t) {
return get(t);
}
public:
DelimiterTracker() : Paren(0), Brace(0), Square(0), Less(0), LLLess(0) { }
};
/// \brief RAII class that helps handle the parsing of an open/close delimiter
/// pair, such as braces { ... } or parentheses ( ... ).
class BalancedDelimiterTracker {
tok::TokenKind Kind, Close;
Parser& P;
bool Cleanup;
const unsigned MaxDepth;
SourceLocation LOpen, LClose;
void assignClosingDelimiter() {
switch (Kind) {
default: llvm_unreachable("Unexpected balanced token");
case tok::l_brace: Close = tok::r_brace; break;
case tok::l_paren: Close = tok::r_paren; break;
case tok::l_square: Close = tok::r_square; break;
case tok::less: Close = tok::greater; break;
case tok::lesslessless: Close = tok::greatergreatergreater; break;
}
}
public:
BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
: Kind(k), P(p), Cleanup(false), MaxDepth(256) {
assignClosingDelimiter();
}
~BalancedDelimiterTracker() {
if (Cleanup)
P.QuantityTracker.pop(Kind);
}
SourceLocation getOpenLocation() const { return LOpen; }
SourceLocation getCloseLocation() const { return LClose; }
SourceRange getRange() const { return SourceRange(LOpen, LClose); }
bool consumeOpen();
bool expectAndConsume(unsigned DiagID,
const char *Msg = "",
tok::TokenKind SkipToTok = tok::unknown);
bool consumeClose();
};
DelimiterTracker QuantityTracker;
/// getTypeAnnotation - Read a parsed type out of an annotation token.
static ParsedType getTypeAnnotation(Token &Tok) {
return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
@ -531,9 +609,6 @@ private:
}
};
SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok,
SourceLocation LHSLoc);
/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
/// input. If so, it is consumed and false is returned.
///
@ -1220,10 +1295,8 @@ private:
SourceLocation &RParenLoc);
ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParsedType &CastTy,
SourceLocation LParenLoc,
SourceLocation &RParenLoc);
ParsedType &CastTy,
BalancedDelimiterTracker &Tracker);
ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
@ -1826,8 +1899,9 @@ private:
bool CXX0XAttributesAllowed = true);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
void ParseFunctionDeclarator(Declarator &D,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker,
bool RequiresArg = false);
bool isFunctionDeclaratorIdentifierList();
void ParseFunctionDeclaratorIdentifierList(
@ -1852,8 +1926,8 @@ private:
std::vector<IdentifierInfo*>& Ident,
std::vector<SourceLocation>& NamespaceLoc,
unsigned int index, SourceLocation& InlineLoc,
SourceLocation& LBrace, ParsedAttributes& attrs,
SourceLocation& RBraceLoc);
ParsedAttributes& attrs,
BalancedDelimiterTracker &Tracker);
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
const ParsedTemplateInfo &TemplateInfo,

View File

@ -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;

View File

@ -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;
}

View File

@ -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();
}
} else {
Loc = ConsumeParen();
PT.consumeOpen();
Loc = PT.getOpenLocation();
}
ExprVector ArgExprs(Actions);
@ -1288,7 +1295,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid()) {
SkipUntil(tok::r_paren);
} else if (Tok.isNot(tok::r_paren)) {
MatchRHSPunctuation(tok::r_paren, Loc);
PT.consumeClose();
LHS = ExprError();
} else {
assert((ArgExprs.size() == 0 ||
@ -1297,7 +1304,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
move_arg(ArgExprs), Tok.getLocation(),
ExecConfig);
ConsumeParen();
PT.consumeClose();
}
break;
@ -1490,11 +1497,14 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
IdentifierInfo *Name = 0;
SourceLocation NameLoc;
if (Tok.is(tok::l_paren)) {
LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
LParenLoc = T.getOpenLocation();
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
if (RParenLoc.isInvalid())
RParenLoc = PP.getLocForEndOfToken(NameLoc);
} else {
@ -1581,7 +1591,9 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
<< BuiltinII);
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker PT(*this, tok::l_paren);
PT.consumeOpen();
// TODO: Build AST.
switch (T) {
@ -1651,7 +1663,9 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
// offsetof-member-designator: offsetof-member-design '[' expression ']'
Comps.push_back(Sema::OffsetOfComponent());
Comps.back().isBrackets = true;
Comps.back().LocStart = ConsumeBracket();
BalancedDelimiterTracker ST(*this, tok::l_square);
ST.consumeOpen();
Comps.back().LocStart = ST.getOpenLocation();
Res = ParseExpression();
if (Res.isInvalid()) {
SkipUntil(tok::r_paren);
@ -1659,18 +1673,19 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
}
Comps.back().U.E = Res.release();
Comps.back().LocEnd =
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
ST.consumeClose();
Comps.back().LocEnd = ST.getCloseLocation();
} else {
if (Tok.isNot(tok::r_paren)) {
MatchRHSPunctuation(tok::r_paren, LParenLoc);
PT.consumeClose();
Res = ExprError();
} else if (Ty.isInvalid()) {
Res = ExprError();
} else {
PT.consumeClose();
Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,
Ty.get(), &Comps[0],
Comps.size(), ConsumeParen());
Ty.get(), &Comps[0], Comps.size(),
PT.getCloseLocation());
}
break;
}
@ -1770,7 +1785,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
SourceLocation OpenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen())
return ExprError();
SourceLocation OpenLoc = T.getOpenLocation();
ExprResult Result(true);
bool isAmbiguousTypeId;
CastTy = ParsedType();
@ -1823,7 +1842,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
TypeResult Ty = ParseTypeName();
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, OpenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
if (Ty.isInvalid() || SubExpr.isInvalid())
@ -1842,9 +1862,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// in which case we should treat it as type-id.
// if stopIfCastExpr is false, we need to determine the context past the
// parens, so we defer to ParseCXXAmbiguousParenExpression for that.
if (isAmbiguousTypeId && !stopIfCastExpr)
return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
OpenLoc, RParenLoc);
if (isAmbiguousTypeId && !stopIfCastExpr) {
ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T);
RParenLoc = T.getCloseLocation();
return res;
}
// Parse the type declarator.
DeclSpec DS(AttrFactory);
@ -1868,11 +1890,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Ty.get(), 0);
} else {
// Match the ')'.
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
MatchRHSPunctuation(tok::r_paren, OpenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
if (Tok.is(tok::l_brace)) {
ExprType = CompoundLiteral;
TypeResult Ty;
@ -1956,11 +1975,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
return ExprError();
}
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
MatchRHSPunctuation(tok::r_paren, OpenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
return move(Result);
}
@ -2024,8 +2040,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
if (!getLang().C1X)
Diag(KeyLoc, diag::ext_c1x_generic_selection);
SourceLocation LParenLoc = 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 ExprError();
ExprResult ControllingExpr;
@ -2091,11 +2107,12 @@ ExprResult Parser::ParseGenericSelectionExpression() {
ConsumeToken();
}
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (RParenLoc.isInvalid())
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return ExprError();
return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
T.getCloseLocation(),
ControllingExpr.release(),
move_arg(Types), move_arg(Exprs));
}

View File

@ -594,7 +594,10 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro)
typedef llvm::Optional<unsigned> DiagResult;
assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['.");
Intro.Range.setBegin(ConsumeBracket());
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
Intro.Range.setBegin(T.getOpenLocation());
bool first = true;
@ -649,8 +652,8 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro)
Intro.addCapture(Kind, Loc, Id);
}
Intro.Range.setEnd(MatchRHSPunctuation(tok::r_square,
Intro.Range.getBegin()));
T.consumeClose();
Intro.Range.setEnd(T.getCloseLocation());
return DiagResult();
}
@ -685,7 +688,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
Scope::FunctionPrototypeScope |
Scope::DeclScope);
SourceLocation DeclLoc = ConsumeParen(), DeclEndLoc;
SourceLocation DeclLoc, DeclEndLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
DeclLoc = T.getOpenLocation();
// Parse parameter-declaration-clause.
ParsedAttributes Attr(AttrFactory);
@ -695,7 +701,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
if (Tok.isNot(tok::r_paren))
ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
DeclEndLoc = MatchRHSPunctuation(tok::r_paren, DeclLoc);
T.consumeClose();
DeclEndLoc = T.getCloseLocation();
// Parse 'mutable'[opt].
SourceLocation MutableLoc;
@ -816,21 +823,23 @@ ExprResult Parser::ParseCXXCasts() {
if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
SourceLocation LParenLoc, RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
if (T.expectAndConsume(diag::err_expected_lparen_after, CastName))
return ExprError();
ExprResult Result = ParseExpression();
// Match the ')'.
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
if (!Result.isInvalid() && !DeclaratorInfo.isInvalidType())
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
LAngleBracketLoc, DeclaratorInfo,
RAngleBracketLoc,
LParenLoc, Result.take(), RParenLoc);
T.getOpenLocation(), Result.take(),
T.getCloseLocation());
return move(Result);
}
@ -845,13 +854,13 @@ ExprResult Parser::ParseCXXTypeid() {
assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
SourceLocation OpLoc = ConsumeToken();
SourceLocation LParenLoc = Tok.getLocation();
SourceLocation RParenLoc;
SourceLocation LParenLoc, RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
// typeid expressions are always parenthesized.
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"typeid"))
if (T.expectAndConsume(diag::err_expected_lparen_after, "typeid"))
return ExprError();
LParenLoc = T.getOpenLocation();
ExprResult Result;
@ -859,8 +868,8 @@ ExprResult Parser::ParseCXXTypeid() {
TypeResult Ty = ParseTypeName();
// Match the ')'.
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
if (Ty.isInvalid() || RParenLoc.isInvalid())
return ExprError();
@ -883,7 +892,8 @@ ExprResult Parser::ParseCXXTypeid() {
if (Result.isInvalid())
SkipUntil(tok::r_paren);
else {
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
RParenLoc = T.getCloseLocation();
if (RParenLoc.isInvalid())
return ExprError();
@ -904,12 +914,10 @@ ExprResult Parser::ParseCXXUuidof() {
assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!");
SourceLocation OpLoc = ConsumeToken();
SourceLocation LParenLoc = Tok.getLocation();
SourceLocation RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
// __uuidof expressions are always parenthesized.
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"__uuidof"))
if (T.expectAndConsume(diag::err_expected_lparen_after, "__uuidof"))
return ExprError();
ExprResult Result;
@ -918,13 +926,14 @@ ExprResult Parser::ParseCXXUuidof() {
TypeResult Ty = ParseTypeName();
// Match the ')'.
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
if (Ty.isInvalid())
return ExprError();
Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true,
Ty.get().getAsOpaquePtr(), RParenLoc);
Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), /*isType=*/true,
Ty.get().getAsOpaquePtr(),
T.getCloseLocation());
} else {
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
Result = ParseExpression();
@ -933,10 +942,11 @@ ExprResult Parser::ParseCXXUuidof() {
if (Result.isInvalid())
SkipUntil(tok::r_paren);
else {
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false,
Result.release(), RParenLoc);
Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(),
/*isType=*/false,
Result.release(), T.getCloseLocation());
}
}
@ -1093,7 +1103,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
} else {
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprVector Exprs(Actions);
CommaLocsTy CommaLocs;
@ -1106,7 +1117,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
}
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
// TypeRep could be null, if it references an invalid typedef.
if (!TypeRep)
@ -1114,8 +1125,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs),
RParenLoc);
return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(),
move_arg(Exprs),
T.getCloseLocation());
}
}
@ -1651,16 +1663,15 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Consume the 'new' or 'delete'.
SymbolLocations[SymbolIdx++] = ConsumeToken();
if (Tok.is(tok::l_square)) {
// Consume the '['.
SourceLocation LBracketLoc = ConsumeBracket();
// Consume the ']'.
SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
LBracketLoc);
if (RBracketLoc.isInvalid())
// Consume the '[' and ']'.
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
SymbolLocations[SymbolIdx++] = LBracketLoc;
SymbolLocations[SymbolIdx++] = RBracketLoc;
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = isNew? OO_Array_New : OO_Array_Delete;
} else {
Op = isNew? OO_New : OO_Delete;
@ -1677,31 +1688,29 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
#include "clang/Basic/OperatorKinds.def"
case tok::l_paren: {
// Consume the '('.
SourceLocation LParenLoc = ConsumeParen();
// Consume the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
LParenLoc);
if (RParenLoc.isInvalid())
// Consume the '(' and ')'.
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
SymbolLocations[SymbolIdx++] = LParenLoc;
SymbolLocations[SymbolIdx++] = RParenLoc;
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = OO_Call;
break;
}
case tok::l_square: {
// Consume the '['.
SourceLocation LBracketLoc = ConsumeBracket();
// Consume the ']'.
SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
LBracketLoc);
if (RBracketLoc.isInvalid())
// Consume the '[' and ']'.
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
SymbolLocations[SymbolIdx++] = LBracketLoc;
SymbolLocations[SymbolIdx++] = RBracketLoc;
SymbolLocations[SymbolIdx++] = T.getOpenLocation();
SymbolLocations[SymbolIdx++] = T.getCloseLocation();
Op = OO_Subscript;
break;
}
@ -2012,13 +2021,16 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
Declarator DeclaratorInfo(DS, Declarator::CXXNewContext);
if (Tok.is(tok::l_paren)) {
// If it turns out to be a placement, we change the type location.
PlacementLParen = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
PlacementLParen = T.getOpenLocation();
if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return ExprError();
}
PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
T.consumeClose();
PlacementRParen = T.getCloseLocation();
if (PlacementRParen.isInvalid()) {
SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return ExprError();
@ -2026,18 +2038,19 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
if (PlacementArgs.empty()) {
// Reset the placement locations. There was no placement.
TypeIdParens = SourceRange(PlacementLParen, PlacementRParen);
TypeIdParens = T.getRange();
PlacementLParen = PlacementRParen = SourceLocation();
} else {
// We still need the type.
if (Tok.is(tok::l_paren)) {
TypeIdParens.setBegin(ConsumeParen());
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
MaybeParseGNUAttributes(DeclaratorInfo);
ParseSpecifierQualifierList(DS);
DeclaratorInfo.SetSourceRange(DS.getSourceRange());
ParseDeclarator(DeclaratorInfo);
TypeIdParens.setEnd(MatchRHSPunctuation(tok::r_paren,
TypeIdParens.getBegin()));
T.consumeClose();
TypeIdParens = T.getRange();
} else {
MaybeParseGNUAttributes(DeclaratorInfo);
if (ParseCXXTypeSpecifierSeq(DS))
@ -2070,7 +2083,9 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
SourceLocation ConstructorLParen, ConstructorRParen;
if (Tok.is(tok::l_paren)) {
ConstructorLParen = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ConstructorLParen = T.getOpenLocation();
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
@ -2078,7 +2093,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
return ExprError();
}
}
ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
T.consumeClose();
ConstructorRParen = T.getCloseLocation();
if (ConstructorRParen.isInvalid()) {
SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return ExprError();
@ -2105,7 +2121,9 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
// Parse the array dimensions.
bool first = true;
while (Tok.is(tok::l_square)) {
SourceLocation LLoc = ConsumeBracket();
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
ExprResult Size(first ? ParseExpression()
: ParseConstantExpression());
if (Size.isInvalid()) {
@ -2115,15 +2133,17 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
}
first = false;
SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
T.consumeClose();
ParsedAttributes attrs(AttrFactory);
D.AddTypeInfo(DeclaratorChunk::getArray(0,
/*static=*/false, /*star=*/false,
Size.release(), LLoc, RLoc),
attrs, RLoc);
Size.release(),
T.getOpenLocation(),
T.getCloseLocation()),
attrs, T.getCloseLocation());
if (RLoc.isInvalid())
if (T.getCloseLocation().isInvalid())
return;
}
}
@ -2175,9 +2195,11 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
bool ArrayDelete = false;
if (Tok.is(tok::l_square)) {
ArrayDelete = true;
SourceLocation LHS = ConsumeBracket();
SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
if (RHS.isInvalid())
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return ExprError();
}
@ -2275,8 +2297,8 @@ ExprResult Parser::ParseUnaryTypeTrait() {
UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
SourceLocation LParen = 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 ExprError();
// FIXME: Error reporting absolutely sucks! If the this fails to parse a type
@ -2284,12 +2306,12 @@ ExprResult Parser::ParseUnaryTypeTrait() {
// specifiers.
TypeResult Ty = ParseTypeName();
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
T.consumeClose();
if (Ty.isInvalid())
return ExprError();
return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation());
}
/// ParseBinaryTypeTrait - Parse the built-in binary type-trait
@ -2303,8 +2325,8 @@ ExprResult Parser::ParseBinaryTypeTrait() {
BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
SourceLocation LParen = 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 ExprError();
TypeResult LhsTy = ParseTypeName();
@ -2324,9 +2346,10 @@ ExprResult Parser::ParseBinaryTypeTrait() {
return ExprError();
}
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
T.consumeClose();
return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen);
return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(),
T.getCloseLocation());
}
/// ParseArrayTypeTrait - Parse the built-in array type-trait
@ -2340,8 +2363,8 @@ ExprResult Parser::ParseArrayTypeTrait() {
ArrayTypeTrait ATT = ArrayTypeTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
SourceLocation LParen = 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 ExprError();
TypeResult Ty = ParseTypeName();
@ -2353,8 +2376,9 @@ ExprResult Parser::ParseArrayTypeTrait() {
switch (ATT) {
case ATT_ArrayRank: {
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, RParen);
T.consumeClose();
return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL,
T.getCloseLocation());
}
case ATT_ArrayExtent: {
if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
@ -2363,9 +2387,10 @@ ExprResult Parser::ParseArrayTypeTrait() {
}
ExprResult DimExpr = ParseExpression();
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
T.consumeClose();
return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), RParen);
return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(),
T.getCloseLocation());
}
default:
break;
@ -2383,15 +2408,16 @@ ExprResult Parser::ParseExpressionTrait() {
ExpressionTrait ET = ExpressionTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
SourceLocation LParen = 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 ExprError();
ExprResult Expr = ParseExpression();
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
T.consumeClose();
return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(), RParen);
return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(),
T.getCloseLocation());
}
@ -2401,8 +2427,7 @@ ExprResult Parser::ParseExpressionTrait() {
ExprResult
Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParsedType &CastTy,
SourceLocation LParenLoc,
SourceLocation &RParenLoc) {
BalancedDelimiterTracker &Tracker) {
assert(getLang().CPlusPlus && "Should only be called for C++!");
assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
assert(isTypeIdInParens() && "Not a type-id!");
@ -2436,7 +2461,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// the context that follows them.
if (!ConsumeAndStoreUntil(tok::r_paren, Toks)) {
// We didn't find the ')' we expected.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
Tracker.consumeClose();
return ExprError();
}
@ -2481,15 +2506,14 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParseDeclarator(DeclaratorInfo);
// Match the ')'.
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
MatchRHSPunctuation(tok::r_paren, LParenLoc);
Tracker.consumeClose();
if (ParseAs == CompoundLiteral) {
ExprType = CompoundLiteral;
TypeResult Ty = ParseTypeName();
return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
return ParseCompoundLiteralExpression(Ty.get(),
Tracker.getOpenLocation(),
Tracker.getCloseLocation());
}
// We parsed '(' type-id ')' and the thing after it wasn't a '{'.
@ -2500,9 +2524,9 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// Result is what ParseCastExpression returned earlier.
if (!Result.isInvalid())
Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc,
DeclaratorInfo, CastTy,
RParenLoc, Result.take());
Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(),
DeclaratorInfo, CastTy,
Tracker.getCloseLocation(), Result.take());
return move(Result);
}
@ -2512,7 +2536,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ExprType = SimpleExpr;
Result = ParseExpression();
if (!Result.isInvalid() && Tok.is(tok::r_paren))
Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), Result.take());
Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(),
Tok.getLocation(), Result.take());
// Match the ')'.
if (Result.isInvalid()) {
@ -2520,10 +2545,6 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
return ExprError();
}
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
MatchRHSPunctuation(tok::r_paren, LParenLoc);
Tracker.consumeClose();
return move(Result);
}

View File

@ -139,7 +139,10 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
//
InMessageExpressionRAIIObject InMessage(*this, true);
SourceLocation StartLoc = ConsumeBracket();
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
SourceLocation StartLoc = T.getOpenLocation();
ExprResult Idx;
// If Objective-C is enabled and this is a typename (class message
@ -266,8 +269,9 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
StartLoc, EllipsisLoc));
}
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc);
T.consumeClose();
Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(
T.getCloseLocation());
}
// Okay, we're done with the designator sequence. We know that there must be
@ -316,7 +320,9 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
ExprResult Parser::ParseBraceInitializer() {
InMessageExpressionRAIIObject InMessage(*this, false);
SourceLocation LBraceLoc = ConsumeBrace();
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
SourceLocation LBraceLoc = T.getOpenLocation();
/// InitExprs - This is the actual list of expressions contained in the
/// initializer.
@ -376,12 +382,13 @@ ExprResult Parser::ParseBraceInitializer() {
// Handle trailing comma.
if (Tok.is(tok::r_brace)) break;
}
if (InitExprsOk && Tok.is(tok::r_brace))
return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs),
ConsumeBrace());
// Match the '}'.
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
bool closed = !T.consumeClose();
if (InitExprsOk && closed)
return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs),
T.getCloseLocation());
return ExprError(); // an error occurred.
}

View File

@ -164,8 +164,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
SourceLocation nameLoc = ConsumeToken();
if (Tok.is(tok::l_paren) &&
!isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
SourceLocation LParenLoc = ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
SourceLocation categoryLoc;
IdentifierInfo *categoryId = 0;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
@ -182,9 +185,9 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
Diag(Tok, diag::err_expected_ident); // missing category name.
return 0;
}
rparenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (rparenLoc.isInvalid())
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return 0;
if (!attrs.empty()) { // categories don't support attributes.
@ -497,7 +500,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
///
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
assert(Tok.getKind() == tok::l_paren);
SourceLocation LHSLoc = ConsumeParen(); // consume '('
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
while (1) {
if (Tok.is(tok::code_completion)) {
@ -508,7 +512,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
// If this is not an identifier at all, bail out early.
if (II == 0) {
MatchRHSPunctuation(tok::r_paren, LHSLoc);
T.consumeClose();
return;
}
@ -587,7 +591,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
ConsumeToken();
}
MatchRHSPunctuation(tok::r_paren, LHSLoc);
T.consumeClose();
}
/// objc-method-proto:
@ -828,7 +832,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
assert(Tok.is(tok::l_paren) && "expected (");
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
SourceLocation TypeStartLoc = Tok.getLocation();
ObjCDeclContextSwitch ObjCDC(*this);
@ -867,7 +873,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
}
if (Tok.is(tok::r_paren))
ConsumeParen();
T.consumeClose();
else if (Tok.getLocation() == TypeStartLoc) {
// If we didn't eat any tokens, then this isn't a type.
Diag(Tok, diag::err_expected_type);
@ -875,7 +881,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
} else {
// Otherwise, we found *something*, but didn't get a ')' in the right
// place. Emit an error then return what we have as the type.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
}
return Ty;
}
@ -1196,7 +1202,8 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
ObjCDeclContextSwitch ObjCDC(*this);
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
// While we still have something to read, read the instance variables.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@ -1276,15 +1283,16 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
SkipUntil(tok::r_brace, true, true);
}
}
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
T.consumeClose();
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
Actions.ActOnLastBitfield(RBraceLoc, AllIvarDecls);
Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
Actions.ActOnObjCContainerFinishDefinition();
// Call ActOnFields() even if we don't have any decls. This is useful
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
AllIvarDecls,
LBraceLoc, RBraceLoc, 0);
T.getOpenLocation(), T.getCloseLocation(), 0);
return;
}
@ -2407,17 +2415,19 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
if (Tok.isNot(tok::l_paren))
return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
TypeResult Ty = ParseTypeName();
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
if (Ty.isInvalid())
return ExprError();
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
Ty.get(), RParenLoc));
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc,
T.getOpenLocation(), Ty.get(),
T.getCloseLocation()));
}
/// objc-protocol-expression
@ -2429,7 +2439,8 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
if (Tok.isNot(tok::l_paren))
return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (Tok.isNot(tok::identifier))
return ExprError(Diag(Tok, diag::err_expected_ident));
@ -2437,10 +2448,11 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
IdentifierInfo *protocolId = Tok.getIdentifierInfo();
ConsumeToken();
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
LParenLoc, RParenLoc));
T.getOpenLocation(),
T.getCloseLocation()));
}
/// objc-selector-expression
@ -2452,9 +2464,11 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
SmallVector<IdentifierInfo *, 12> KeyIdents;
SourceLocation LParenLoc = ConsumeParen();
SourceLocation sLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(),
KeyIdents.size());
@ -2497,10 +2511,11 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
break;
}
}
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
LParenLoc, RParenLoc));
T.getOpenLocation(),
T.getCloseLocation()));
}
Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) {

View File

@ -708,8 +708,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
Tok.getLocation(),
"in compound statement ('{}')");
InMessageExpressionRAIIObject InMessage(*this, false);
SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
BalancedDelimiterTracker T(*this, tok::l_brace);
if (T.consumeOpen())
return StmtError();
StmtVector Stmts(Actions);
@ -807,13 +808,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// We broke out of the while loop because we found a '}' or EOF.
if (Tok.isNot(tok::r_brace)) {
Diag(Tok, diag::err_expected_rbrace);
Diag(LBraceLoc, diag::note_matching) << "{";
Diag(T.getOpenLocation(), diag::note_matching) << "{";
return StmtError();
}
SourceLocation RBraceLoc = ConsumeBrace();
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
isStmtExpr);
if (T.consumeClose())
return StmtError();
return Actions.ActOnCompoundStmt(T.getOpenLocation(), T.getCloseLocation(),
move_arg(Stmts), isStmtExpr);
}
/// ParseParenExprOrCondition:
@ -831,7 +834,9 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean) {
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (getLang().CPlusPlus)
ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
else {
@ -856,7 +861,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
}
// Otherwise the condition is valid or the rparen is present.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
return false;
}
@ -1204,16 +1209,17 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
}
// Parse the parenthesized condition.
SourceLocation LPLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprResult Cond = ParseExpression();
SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
T.consumeClose();
DoScope.Exit();
if (Cond.isInvalid() || Body.isInvalid())
return StmtError();
return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc,
Cond.get(), RPLoc);
return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
Cond.get(), T.getCloseLocation());
}
/// ParseForStatement
@ -1273,7 +1279,9 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
ParseScope ForScope(this, ScopeFlags);
SourceLocation LParenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprResult Value;
bool ForEach = false, ForRange = false;
@ -1413,18 +1421,18 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
}
}
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
T.consumeClose();
// We need to perform most of the semantic analysis for a C++0x for-range
// statememt before parsing the body, in order to be able to deduce the type
// of an auto-typed loop variable.
StmtResult ForRangeStmt;
if (ForRange) {
ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc,
ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, T.getOpenLocation(),
FirstPart.take(),
ForRangeInit.ColonLoc,
ForRangeInit.RangeExpr.get(),
RParenLoc);
T.getCloseLocation());
// Similarly, we need to do the semantic analysis for a for-range
@ -1462,16 +1470,18 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
return StmtError();
if (ForEach)
return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
FirstPart.take(),
Collection.take(), RParenLoc,
Body.take());
return Actions.ActOnObjCForCollectionStmt(ForLoc, T.getOpenLocation(),
FirstPart.take(),
Collection.take(),
T.getCloseLocation(),
Body.take());
if (ForRange)
return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take());
return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart,
SecondVar, ThirdPart, RParenLoc, Body.take());
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(),
SecondPart, SecondVar, ThirdPart,
T.getCloseLocation(), Body.take());
}
/// ParseGotoStatement
@ -1742,7 +1752,8 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
SkipUntil(tok::r_paren);
return StmtError();
}
Loc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprResult AsmString(ParseAsmStringLiteral());
if (AsmString.isInvalid())
@ -1755,12 +1766,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
if (Tok.is(tok::r_paren)) {
// We have a simple asm expression like 'asm("foo")'.
SourceLocation RParenLoc = ConsumeParen();
T.consumeClose();
return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
/*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
move_arg(Constraints), move_arg(Exprs),
AsmString.take(), move_arg(Clobbers),
RParenLoc);
T.getCloseLocation());
}
// Parse Outputs, if present.
@ -1820,12 +1831,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
}
}
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
T.consumeClose();
return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
NumOutputs, NumInputs, Names.data(),
move_arg(Constraints), move_arg(Exprs),
AsmString.take(), move_arg(Clobbers),
RParenLoc);
T.getCloseLocation());
}
/// ParseAsmOperands - Parse the asm-operands production as used by
@ -1851,7 +1862,8 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
while (1) {
// Read the [id] if present.
if (Tok.is(tok::l_square)) {
SourceLocation Loc = ConsumeBracket();
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
@ -1863,7 +1875,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
ConsumeToken();
Names.push_back(II);
MatchRHSPunctuation(tok::r_square, Loc);
T.consumeClose();
} else
Names.push_back(0);
@ -1881,9 +1893,10 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
}
// Read the parenthesized expression.
SourceLocation OpenLoc = ConsumeParen();
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprResult Res(ParseExpression());
MatchRHSPunctuation(tok::r_paren, OpenLoc);
T.consumeClose();
if (Res.isInvalid()) {
SkipUntil(tok::r_paren);
return true;
@ -2078,8 +2091,8 @@ StmtResult Parser::ParseCXXCatchBlock() {
SourceLocation CatchLoc = ConsumeToken();
SourceLocation LParenLoc = 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 StmtError();
// C++ 3.3.2p3:
@ -2100,7 +2113,8 @@ StmtResult Parser::ParseCXXCatchBlock() {
} else
ConsumeToken();
if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return StmtError();
if (Tok.isNot(tok::l_brace))

View File

@ -122,34 +122,6 @@ void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
<< FixItHint::CreateInsertion(EndLoc, ")");
}
/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
/// this helper function matches and consumes the specified RHS token if
/// present. If not present, it emits a corresponding diagnostic indicating
/// that the parser failed to match the RHS of the token at LHSLoc.
SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
SourceLocation LHSLoc) {
if (Tok.is(RHSTok))
return ConsumeAnyToken();
SourceLocation R = Tok.getLocation();
const char *LHSName = "unknown";
diag::kind DID = diag::err_parse_error;
switch (RHSTok) {
default: break;
case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
case tok::greatergreatergreater:
LHSName = "<<<"; DID = diag::err_expected_ggg; break;
}
Diag(Tok, DID);
Diag(LHSLoc, diag::note_matching) << LHSName;
SkipUntil(RHSTok);
return R;
}
static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
switch (ExpectedTok) {
case tok::semi: return Tok.is(tok::colon); // : for ;
@ -1147,13 +1119,12 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
ConsumeToken();
}
if (Tok.isNot(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
Diag(Tok, diag::err_expected_lparen_after) << "asm";
return ExprError();
}
Loc = ConsumeParen();
ExprResult Result(ParseAsmStringLiteral());
if (Result.isInvalid()) {
@ -1162,9 +1133,10 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
*EndLoc = Tok.getLocation();
ConsumeAnyToken();
} else {
Loc = MatchRHSPunctuation(tok::r_paren, Loc);
// Close the paren and get the location of the end bracket
T.consumeClose();
if (EndLoc)
*EndLoc = Loc;
*EndLoc = T.getCloseLocation();
}
return move(Result);
@ -1489,13 +1461,12 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) {
Token Condition = Tok;
SourceLocation IfExistsLoc = ConsumeToken();
SourceLocation LParenLoc = Tok.getLocation();
if (Tok.isNot(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc;
SkipUntil(tok::semi);
return true;
}
ConsumeParen(); // eat the '('.
// Parse nested-name-specifier.
CXXScopeSpec SS;
@ -1514,7 +1485,8 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) {
return true;
}
if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return true;
// Check if the symbol exists.
@ -1581,3 +1553,64 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport() {
return Actions.ConvertDeclToDeclGroup(Import.get());
}
bool Parser::BalancedDelimiterTracker::consumeOpen() {
// Try to consume the token we are holding
if (P.Tok.is(Kind)) {
P.QuantityTracker.push(Kind);
Cleanup = true;
if (P.QuantityTracker.getDepth(Kind) < MaxDepth) {
LOpen = P.ConsumeAnyToken();
return false;
} else {
P.Diag(P.Tok, diag::err_parser_impl_limit_overflow);
P.SkipUntil(tok::eof);
}
}
return true;
}
bool Parser::BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
const char *Msg,
tok::TokenKind SkipToToc ) {
LOpen = P.Tok.getLocation();
if (!P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc)) {
P.QuantityTracker.push(Kind);
Cleanup = true;
if (P.QuantityTracker.getDepth(Kind) < MaxDepth) {
return false;
} else {
P.Diag(P.Tok, diag::err_parser_impl_limit_overflow);
P.SkipUntil(tok::eof);
}
}
return true;
}
bool Parser::BalancedDelimiterTracker::consumeClose() {
if (P.Tok.is(Close)) {
LClose = P.ConsumeAnyToken();
if (Cleanup)
P.QuantityTracker.pop(Kind);
Cleanup = false;
return false;
} else {
const char *LHSName = "unknown";
diag::kind DID = diag::err_parse_error;
switch (Close) {
default: break;
case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
case tok::greatergreatergreater:
LHSName = "<<<"; DID = diag::err_expected_ggg; break;
}
P.Diag(P.Tok, DID);
P.Diag(LOpen, diag::note_matching) << LHSName;
if (P.SkipUntil(Close))
LClose = P.Tok.getLocation();
}
return true;
}

File diff suppressed because one or more lines are too long