Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -119,7 +119,16 @@ (Style.Language == FormatStyle::LK_Proto && Left->Previous && Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) CurrentToken->Type = TT_DictLiteral; - else + // In if/for/while (i < x >> 1) ensure we don't see the <> as + // TemplateOpener/Closer + else if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) && + CurrentToken->Next->Next && + !CurrentToken->Next->Next->isOneOf(tok::l_paren, + tok::coloncolon) && + Line.First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_while)) { + Left->Type = TT_BinaryOperator; + return false; + } else CurrentToken->Type = TT_TemplateCloser; next(); return true; @@ -145,6 +154,10 @@ Contexts[Contexts.size() - 2].IsExpression && !Line.startsWith(tok::kw_template)) return false; + // If we see a ; then likely this is a for loop and not the template + if (CurrentToken->is(tok::semi)) + return false; + updateParameterCount(Left, CurrentToken); if (Style.Language == FormatStyle::LK_Proto) { if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) { @@ -1523,7 +1536,8 @@ if (Current.is(tok::exclaim)) { if (Current.Previous && (Keywords.IsJavaScriptIdentifier( - *Current.Previous, /* AcceptIdentifierName= */ true) || + *Current.Previous, + /* AcceptIdentifierName= */ true) || Current.Previous->isOneOf( tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) || @@ -1970,7 +1984,7 @@ // same decision irrespective of the decisions for tokens leading up to it. // Store this information to prevent this from causing exponential runtime. llvm::SmallPtrSet NonTemplateLess; -}; +}; // namespace static const int PrecedenceUnaryOperator = prec::PointerToMember + 1; static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2; @@ -2174,7 +2188,7 @@ FormatToken *Current; }; -} // end anonymous namespace +} // namespace void TokenAnnotator::setCommentLineLevels( SmallVectorImpl &Lines) { Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -7067,6 +7067,19 @@ verifyFormat("< < < < < < < < < < < < < < < < < < < < < < < < < < < < < <"); } +TEST_F(FormatTest, UnderstandsShiftOperators) { + verifyFormat("if (i < x >> 1)"); + verifyFormat("while (i < x >> 1)"); + verifyFormat("for (unsigned i = 0; i < i; ++i, v = v >> 1)"); + verifyFormat("for (unsigned i = 0; i < x >> 1; ++i, v = v >> 1)"); + verifyFormat( + "for (std::vector::iterator i = 0; i < x >> 1; ++i, v = v >> 1)"); + verifyFormat("Foo.call>()"); + verifyFormat("if (Foo.call>() == 0)"); + verifyFormat("for (std::vector>::iterator i = 0; i < x >> 1; " + "++i, v = v >> 1)"); +} + TEST_F(FormatTest, BitshiftOperatorWidth) { EXPECT_EQ("int a = 1 << 2; /* foo\n" " bar */",