From 355094ef06a3d47f0600e85744f6e995706b12d3 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 17 Jun 2010 10:52:18 +0000 Subject: [PATCH] Make sure parens/braces/brackets are correctly balanced. In a line like: (; the semicolon leaves Parser:ParenCount unbalanced (it's 1 even though we stopped looking for a right paren). This may affect later parsing and result in bad recovery for parsing errors. llvm-svn: 106213 --- clang/include/clang/Parse/Parser.h | 1 + clang/lib/Parse/ParseDecl.cpp | 2 ++ clang/lib/Parse/ParseStmt.cpp | 2 ++ clang/lib/Parse/Parser.cpp | 13 ++++++++++++- clang/lib/Parse/RAIIObjectsForParser.h | 17 +++++++++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 233ed1c0b83b..0ba348159ff1 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -72,6 +72,7 @@ namespace prec { class Parser { friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; + friend class ParenBraceBracketBalancer; PrettyStackTraceParserEntry CrashInfo; Preprocessor &PP; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 65c42193f66e..ad1a690b4246 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -309,6 +309,8 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, CXX0XAttributeList Attr) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::kw_template: diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f0930a0a1a44..266b858109fa 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -77,6 +77,8 @@ Parser::OwningStmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) { const char *SemiError = 0; OwningStmtResult Res(Actions); + + ParenBraceBracketBalancer BalancerRAIIObj(*this); CXX0XAttributeList Attr; if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 225a793af53a..7d999ac40846 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -127,7 +127,16 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok, } Diag(Tok, DID); Diag(LHSLoc, diag::note_matching) << LHSName; - SkipUntil(RHSTok); + if (!SkipUntil(RHSTok)) { + // We stopped before finding a RHS token, e.g. we encountered a ';'. + // Balance Paren/Brace/Bracket counting. + switch (RHSTok) { + default: break; + case tok::r_paren : assert(ParenCount > 0); --ParenCount; break; + case tok::r_brace : assert(BraceCount > 0); --BraceCount; break; + case tok::r_square: assert(BracketCount > 0); --BracketCount; break; + } + } return R; } @@ -401,6 +410,8 @@ void Parser::ParseTranslationUnit() { /// /// [C++0x/GNU] 'extern' 'template' declaration Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::semi: diff --git a/clang/lib/Parse/RAIIObjectsForParser.h b/clang/lib/Parse/RAIIObjectsForParser.h index 06bbbc23a010..addc79508399 100644 --- a/clang/lib/Parse/RAIIObjectsForParser.h +++ b/clang/lib/Parse/RAIIObjectsForParser.h @@ -80,6 +80,23 @@ namespace clang { } }; + /// \brief RAII object that makes sure paren/bracket/brace count is correct + /// after declaration/statement parsing, even when there's a parsing error. + class ParenBraceBracketBalancer { + Parser &P; + unsigned short ParenCount, BracketCount, BraceCount; + public: + ParenBraceBracketBalancer(Parser &p) + : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount), + BraceCount(p.BraceCount) { } + + ~ParenBraceBracketBalancer() { + P.ParenCount = ParenCount; + P.BracketCount = BracketCount; + P.BraceCount = BraceCount; + } + }; + } // end namespace clang #endif