diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-12 16:37:45 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-12 16:37:45 +0000 |
commit | 4a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41b (patch) | |
tree | 51429fab5effd4a81368c423996e314d702e1bad | |
parent | d41679d6881d2b424d8b3600fc774308087735a7 (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
-rw-r--r-- | docs/InternalsManual.html | 2 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 94 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 148 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 125 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 113 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 231 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 23 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 65 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 82 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 107 | ||||
-rw-r--r-- | test/Parser/parser_overflow.c | 7 |
12 files changed, 596 insertions, 403 deletions
diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html index 2829dbdd75..da83d89acc 100644 --- a/docs/InternalsManual.html +++ b/docs/InternalsManual.html @@ -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> diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 77573065ab..733eccc7b5 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -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">; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e1e2402a2c..eed8862159 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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, 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(); |