(!ColonRequired || (Next && Next->is(tok::colon)));
}
+ bool isLiteral() const {
+ return Tok.isLiteral() || isOneOf(tok::kw_true, tok::kw_false);
+ }
+
/// \brief Determine whether the token is a simple-type-specifier.
bool isSimpleTypeSpecifier() const;
// parameters.
// FIXME: This is getting out of hand, write a decent parser.
if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
- (CurrentToken->Previous->Type == TT_BinaryOperator ||
+ ((CurrentToken->Previous->Type == TT_BinaryOperator &&
+ // Toplevel bool expressions do not make lots of sense;
+ // If we're on the top level, it contains only the base context and
+ // the context for the current opening angle bracket.
+ Contexts.size() > 2) ||
Contexts[Contexts.size() - 2].IsExpression) &&
Line.First->isNot(tok::kw_template))
return false;
PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
return TT_PointerOrReference;
- if (PrevToken->Tok.isLiteral() ||
+ if (PrevToken->isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
- NextToken->Tok.isLiteral() || NextToken->isUnaryOperator() ||
+ NextToken->isLiteral() || NextToken->isUnaryOperator() ||
// If we know we're in a template argument, there are no named
// declarations. Thus, having an identifier on the right-hand side
// indicates a binary operator.
verifyFormat("vector<int *const **const *> v;");
verifyFormat("vector<int *volatile> v;");
verifyFormat("vector<a * b> v;");
+ verifyFormat("foo<b && false>();");
+ verifyFormat("foo<b & 1>();");
+
+ // FIXME: We cannot handle this case yet; we might be able to figure out that
+ // foo<x> d > v; doesn't make sense.
+ verifyFormat("foo<a < b && c> d > v;");
}
TEST_F(FormatTest, UnderstandsAttributes) {