From c86c40b912e53fb11ff8f745ed616035b8b7259c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 6 Jun 2012 21:18:07 +0000 Subject: [PATCH] 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 --- include/clang/Parse/Parser.h | 76 ++---------------------------- lib/Parse/ParseExpr.cpp | 1 - lib/Parse/ParseExprCXX.cpp | 2 - lib/Parse/Parser.cpp | 8 ++-- lib/Parse/RAIIObjectsForParser.h | 75 +++++++++++++++++++++++++++++ test/CXX/temp/temp.names/p3-0x.cpp | 12 +++++ 6 files changed, 94 insertions(+), 80 deletions(-) create mode 100644 test/CXX/temp/temp.names/p3-0x.cpp diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 2222e781e8..c69e5cea7d 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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()); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 6d31396cc0..2a1fba655a 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -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(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 715218448a..68eff7cf5f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 56b6641bd8..0d7d047e00 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -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); } diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index 64431276bf..e13c4cfeb3 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -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 index 0000000000..85dc75e301 --- /dev/null +++ b/test/CXX/temp/temp.names/p3-0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +template class X { /* ... */ }; +X< 1>2 > x1; // expected-error{{expected unqualified-id}} +X<(1>2)> x2; // OK +template class Y { /* ... */ }; +Y> x3; // OK, same as Y > x3; +Y>1>> x4; // expected-error{{expected unqualified-id}} +Y>1)>> x5; + +int a, b; +Y x6; -- 2.40.0