]> granicus.if.org Git - clang/commitdiff
Make sure parens/braces/brackets are correctly balanced.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 17 Jun 2010 10:52:18 +0000 (10:52 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 17 Jun 2010 10:52:18 +0000 (10:52 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106213 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
lib/Parse/RAIIObjectsForParser.h

index 233ed1c0b83b45539a6eb840171a1b83e0119895..0ba348159ff1f1a98613ec2b6762f92276ebc283 100644 (file)
@@ -72,6 +72,7 @@ namespace prec {
 class Parser {
   friend class PragmaUnusedHandler;
   friend class ColonProtectionRAIIObject;
+  friend class ParenBraceBracketBalancer;
   PrettyStackTraceParserEntry CrashInfo;
 
   Preprocessor &PP;
index 65c42193f66e9d6a98d7514d6e14ff3ceeaa10bb..ad1a690b4246b9d9dbc1f772ecd6ebeda32f1e71 100644 (file)
@@ -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:
index f0930a0a1a4441f825fdf4dfc77bf175d6090cee..266b858109fa8dc89d7a0d85d415138bf104b7c8 100644 (file)
@@ -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())
index 225a793af53a559422ddef33eb491a8502f10d85..7d999ac408467521f57baab98072d29de7227bc1 100644 (file)
@@ -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:
index 06bbbc23a01016573ac0303cfa67fbe3aa0014e0..addc79508399820fd3d03356031149b5e3c8a4bf 100644 (file)
@@ -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