Whenever we have a BalancedDelimiterTracker, we have a 'nested' scope
where '>' is going to behave as an operator (and not as a '>' closing
a template argument list).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158111 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 6d31396..2a1fba6 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1888,7 +1888,6 @@
                              bool isTypeCast, ParsedType &CastTy,
                              SourceLocation &RParenLoc) {
   assert(Tok.is(tok::l_paren) && "Not a paren expr!");
-  GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
   BalancedDelimiterTracker T(*this, tok::l_paren);
   if (T.consumeOpen())
     return ExprError();
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 7152184..68eff7c 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1235,8 +1235,6 @@
                                              MultiExprArg(&InitList, 1),
                                              SourceLocation());
   } else {
-    GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
-
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
 
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 56b6641..0d7d047 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1704,13 +1704,13 @@
   return Actions.ConvertDeclToDeclGroup(Import.get());
 }
 
-bool Parser::BalancedDelimiterTracker::diagnoseOverflow() {
+bool BalancedDelimiterTracker::diagnoseOverflow() {
   P.Diag(P.Tok, diag::err_parser_impl_limit_overflow);
   P.SkipUntil(tok::eof);
   return true;  
 }
 
-bool Parser::BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, 
+bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
                                             const char *Msg,
                                             tok::TokenKind SkipToToc ) {
   LOpen = P.Tok.getLocation();
@@ -1723,7 +1723,7 @@
   return diagnoseOverflow();
 }
 
-bool Parser::BalancedDelimiterTracker::diagnoseMissingClose() {
+bool BalancedDelimiterTracker::diagnoseMissingClose() {
   assert(!P.Tok.is(Close) && "Should have consumed closing delimiter");
   
   const char *LHSName = "unknown";
@@ -1741,6 +1741,6 @@
   return true;
 }
 
-void Parser::BalancedDelimiterTracker::skipToEnd() {
+void BalancedDelimiterTracker::skipToEnd() {
   P.SkipUntil(Close, false);
 }
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index 6443127..e13c4cf 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -332,6 +332,81 @@
     }
   };
 
+  /// \brief RAII class that helps handle the parsing of an open/close delimiter
+  /// pair, such as braces { ... } or parentheses ( ... ).
+  class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
+    Parser& P;
+    tok::TokenKind Kind, Close;
+    SourceLocation (Parser::*Consumer)();
+    SourceLocation LOpen, LClose;
+    
+    unsigned short &getDepth() {
+      switch (Kind) {
+        case tok::l_brace: return P.BraceCount;
+        case tok::l_square: return P.BracketCount;
+        case tok::l_paren: return P.ParenCount;
+        default: llvm_unreachable("Wrong token kind");
+      }
+    }
+    
+    enum { MaxDepth = 256 };
+    
+    bool diagnoseOverflow();
+    bool diagnoseMissingClose();
+    
+  public:
+    BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
+      : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
+        P(p), Kind(k)
+    {
+      switch (Kind) {
+        default: llvm_unreachable("Unexpected balanced token");
+        case tok::l_brace:
+          Close = tok::r_brace; 
+          Consumer = &Parser::ConsumeBrace;
+          break;
+        case tok::l_paren:
+          Close = tok::r_paren; 
+          Consumer = &Parser::ConsumeParen;
+          break;
+          
+        case tok::l_square:
+          Close = tok::r_square; 
+          Consumer = &Parser::ConsumeBracket;
+          break;
+      }      
+    }
+    
+    SourceLocation getOpenLocation() const { return LOpen; }
+    SourceLocation getCloseLocation() const { return LClose; }
+    SourceRange getRange() const { return SourceRange(LOpen, LClose); }
+    
+    bool consumeOpen() {
+      if (!P.Tok.is(Kind))
+        return true;
+      
+      if (getDepth() < MaxDepth) {
+        LOpen = (P.*Consumer)();
+        return false;
+      }
+      
+      return diagnoseOverflow();
+    }
+    
+    bool expectAndConsume(unsigned DiagID,
+                          const char *Msg = "",
+                          tok::TokenKind SkipToTok = tok::unknown);
+    bool consumeClose() {
+      if (P.Tok.is(Close)) {
+        LClose = (P.*Consumer)();
+        return false;
+      } 
+      
+      return diagnoseMissingClose();
+    }
+    void skipToEnd();
+  };
+
 } // end namespace clang
 
 #endif