/// 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:
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:
/// 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) {
// 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 ||
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!");
}
}
- 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;
ConsumeToken();
}
- return Tok.isNot(tok::greater);
+ return Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater);
}