]> granicus.if.org Git - clang/commitdiff
Whenever we have a BalancedDelimiterTracker, we have a 'nested' scope
authorDouglas Gregor <dgregor@apple.com>
Wed, 6 Jun 2012 21:18:07 +0000 (21:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 6 Jun 2012 21:18:07 +0000 (21:18 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/Parser.cpp
lib/Parse/RAIIObjectsForParser.h
test/CXX/temp/temp.names/p3-0x.cpp [new file with mode: 0644]

index 2222e781e80218d5e34544fc9790477282b444ff..c69e5cea7ddaeb266faa3915850a0f20b19fcb4d 100644 (file)
@@ -28,6 +28,7 @@
 namespace clang {
   class PragmaHandler;
   class Scope;
+  class BalancedDelimiterTracker;
   class DeclGroupRef;
   class DiagnosticBuilder;
   class Parser;
@@ -83,6 +84,7 @@ class Parser : public CodeCompletionHandler {
   friend class InMessageExpressionRAIIObject;
   friend class PoisonSEHIdentifiersRAIIObject;
   friend class ParenBraceBracketBalancer;
+  friend class BalancedDelimiterTracker;
 
   Preprocessor &PP;
 
@@ -97,7 +99,7 @@ class Parser : public CodeCompletionHandler {
   SourceLocation PrevTokLocation;
 
   unsigned short ParenCount, BracketCount, BraceCount;
-
+  
   /// Actions - These are the callbacks we invoke as we parse various constructs
   /// in the file.
   Sema &Actions;
@@ -438,78 +440,6 @@ private:
     return PP.LookAhead(0);
   }
 
-  /// \brief RAII class that helps handle the parsing of an open/close delimiter
-  /// pair, such as braces { ... } or parentheses ( ... ).
-  class BalancedDelimiterTracker {
-    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) : 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();
-  };
-
   /// getTypeAnnotation - Read a parsed type out of an annotation token.
   static ParsedType getTypeAnnotation(Token &Tok) {
     return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
index 6d31396cc0166d9d67e6b7562fa67f927fc0ffa3..2a1fba655acce11d5a1325ad176ca1f7b7b197ec 100644 (file)
@@ -1888,7 +1888,6 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
                              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();
index 715218448a3e90c07e0872e191196db1c39dd6de..68eff7cf5f84ce030151143403ed63f069fd720b 100644 (file)
@@ -1235,8 +1235,6 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
                                              MultiExprArg(&InitList, 1),
                                              SourceLocation());
   } else {
-    GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
-
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
 
index 56b6641bd80c6ed05898af6f1481289396e7dcb8..0d7d047e00ebf42918c443bfa81852ddf84b14b7 100644 (file)
@@ -1704,13 +1704,13 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
   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 @@ bool Parser::BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
   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 @@ bool Parser::BalancedDelimiterTracker::diagnoseMissingClose() {
   return true;
 }
 
-void Parser::BalancedDelimiterTracker::skipToEnd() {
+void BalancedDelimiterTracker::skipToEnd() {
   P.SkipUntil(Close, false);
 }
index 64431276bf7e321fee5849dc15598a5db2d3c6c5..e13c4cfeb31574c3f568cb3dd45e216ac1353d2f 100644 (file)
@@ -332,6 +332,81 @@ namespace clang {
     }
   };
 
+  /// \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
diff --git a/test/CXX/temp/temp.names/p3-0x.cpp b/test/CXX/temp/temp.names/p3-0x.cpp
new file mode 100644 (file)
index 0000000..85dc75e
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+template<int i> class X { /* ... */ };
+X< 1>2 > x1; // expected-error{{expected unqualified-id}}
+X<(1>2)> x2; // OK
+template<class T> class Y { /* ... */ };
+Y<X<1>> x3; // OK, same as Y<X<1> > x3; 
+Y<X<6>>1>> x4; // expected-error{{expected unqualified-id}}
+Y<X<(6>>1)>> x5;
+
+int a, b;
+Y<decltype(a < b)> x6;