[cfe-commits] r65484 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.def lib/Parse/ParseExpr.cpp lib/Parse/ParseTemplate.cpp test/SemaTemplate/right-angle-brackets-0x.cpp test/SemaTemplate/right-angle-brackets-98.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 25 15:02:37 PST 2009


Author: dgregor
Date: Wed Feb 25 17:02:36 2009
New Revision: 65484

URL: http://llvm.org/viewvc/llvm-project?rev=65484&view=rev
Log:
Cope with use of the token '>>' inside a template argument list, e.g.,

  vector<vector<double>> Matrix;

In C++98/03, this token always means "right shift". However, if we're in
a context where we know that it can't mean "right shift", provide a
friendly reminder to put a space between the two >'s and then treat it
as two >'s as part of recovery.

In C++0x, this token is always broken into two '>' tokens.


Added:
    cfe/trunk/test/SemaTemplate/right-angle-brackets-0x.cpp
    cfe/trunk/test/SemaTemplate/right-angle-brackets-98.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def?rev=65484&r1=65483&r2=65484&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.def Wed Feb 25 17:02:36 2009
@@ -278,6 +278,8 @@
      "expected template name after 'template' keyword in nested name specifier")
 DIAG(err_less_after_template_name_in_nested_name_spec, ERROR,
      "expected '<' after 'template %0' in nested name specifier")
+DIAG(err_two_right_angle_brackets_need_space, ERROR,
+     "a space is required between consecutive right angle brackets (use '> >')")
 
 // Language specific pragmas
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=65484&r1=65483&r2=65484&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Feb 25 17:02:36 2009
@@ -56,16 +56,29 @@
 /// token.  This returns:
 ///
 static prec::Level getBinOpPrecedence(tok::TokenKind Kind, 
-                                      bool GreaterThanIsOperator) {
+                                      bool GreaterThanIsOperator,
+                                      bool CPlusPlus0x) {
   switch (Kind) {
   case tok::greater:
-    // The '>' token can act as either an operator or as the ending
-    // token for a template argument list.  
-    // FIXME: '>>' is similar, for error recovery and C++0x.
+    // C++ [temp.names]p3:
+    //   [...] When parsing a template-argument-list, the first
+    //   non-nested > is taken as the ending delimiter rather than a
+    //   greater-than operator. [...]
     if (GreaterThanIsOperator)
       return prec::Relational;
     return prec::Unknown;
       
+  case tok::greatergreater:
+    // C++0x [temp.names]p3:
+    //
+    //   [...] Similarly, the first non-nested >> is treated as two
+    //   consecutive but distinct > tokens, the first of which is
+    //   taken as the end of the template-argument-list and completes
+    //   the template-id. [...]
+    if (GreaterThanIsOperator || !CPlusPlus0x)
+      return prec::Shift;
+    return prec::Unknown;
+
   default:                        return prec::Unknown;
   case tok::comma:                return prec::Comma;
   case tok::equal:
@@ -90,8 +103,7 @@
   case tok::lessequal:
   case tok::less:
   case tok::greaterequal:         return prec::Relational;
-  case tok::lessless:
-  case tok::greatergreater:       return prec::Shift;
+  case tok::lessless:             return prec::Shift;
   case tok::plus:
   case tok::minus:                return prec::Additive;
   case tok::percent:
@@ -274,7 +286,9 @@
 /// LHS and has a precedence of at least MinPrec.
 Parser::OwningExprResult
 Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
-  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(), 
+                                            GreaterThanIsOperator,
+                                            getLang().CPlusPlus0x);
   SourceLocation ColonLoc;
 
   while (1) {
@@ -324,7 +338,8 @@
     // Remember the precedence of this operator and get the precedence of the
     // operator immediately to the right of the RHS.
     unsigned ThisPrec = NextTokPrec;
-    NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+    NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                     getLang().CPlusPlus0x);
 
     // Assignment and conditional expressions are right-associative.
     bool isRightAssoc = ThisPrec == prec::Conditional ||
@@ -343,7 +358,8 @@
       if (RHS.isInvalid())
         return move(RHS);
 
-      NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+      NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                       getLang().CPlusPlus0x);
     }
     assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=65484&r1=65483&r2=65484&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Feb 25 17:02:36 2009
@@ -431,14 +431,24 @@
     }
   }
 
-  if (Tok.isNot(tok::greater))
+  if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater))
     return true;
 
-  // Determine the location of the '>'. Only consume this token if the
-  // caller asked us to.
+  // Determine the location of the '>' or '>>'. Only consume this
+  // token if the caller asked us to.
   RAngleLoc = Tok.getLocation();
 
-  if (ConsumeLastToken)
+  if (Tok.is(tok::greatergreater)) {
+    if (!getLang().CPlusPlus0x)
+      Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space);
+
+    Tok.setKind(tok::greater);
+    if (!ConsumeLastToken) {
+      // Since we're not supposed to consume the '>>' token, we need
+      // to insert a second '>' token after the first.
+      PP.EnterToken(Tok);
+    }
+  } else if (ConsumeLastToken)
     ConsumeToken();
 
   return false;
@@ -670,6 +680,6 @@
     ConsumeToken();
   }
 
-  return Tok.isNot(tok::greater);
+  return Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater);
 }
 

Added: cfe/trunk/test/SemaTemplate/right-angle-brackets-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/right-angle-brackets-0x.cpp?rev=65484&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/right-angle-brackets-0x.cpp (added)
+++ cfe/trunk/test/SemaTemplate/right-angle-brackets-0x.cpp Wed Feb 25 17:02:36 2009
@@ -0,0 +1,22 @@
+// RUN: clang -fsyntax-only -std=c++0x -verify %s
+template<typename T> struct X;
+template<int I> struct Y;
+
+X<X<int>> *x1;
+
+Y<(1 >> 2)> *y1;
+Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}}
+
+X<X<X<X<X<int>>>>> *x2;
+
+template<> struct X<int> { };
+typedef X<int> X_int;
+struct Z : X_int { };
+
+void f(const X<int> x) {
+  (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}}
+  (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}}
+
+  X<X<int>> *x1;
+}
+

Added: cfe/trunk/test/SemaTemplate/right-angle-brackets-98.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/right-angle-brackets-98.cpp?rev=65484&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/right-angle-brackets-98.cpp (added)
+++ cfe/trunk/test/SemaTemplate/right-angle-brackets-98.cpp Wed Feb 25 17:02:36 2009
@@ -0,0 +1,13 @@
+// RUN: clang -fsyntax-only -std=c++98 -verify %s
+template<typename T> struct X;
+template<int I> struct Y;
+
+X<X<int> > *x1;
+X<X<int>> *x2; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}}
+
+X<X<X<X<int>> // expected-error{{a space is required between consecutive right angle brackets (use '> >')}}
+    >> *x3;   // expected-error{{a space is required between consecutive right angle brackets (use '> >')}}
+
+Y<(1 >> 2)> *y1;
+Y<1 >> 2> *y2;
+// FIXME: when we get a -Wc++0x mode, warn about the use above





More information about the cfe-commits mailing list