Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1711,6 +1711,10 @@ return true; } +static bool noPrecedingWhitespace(const FormatToken &Tok) { + return Tok.WhitespaceRange.getBegin() == Tok.WhitespaceRange.getEnd(); +} + bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Right) { const FormatToken &Left = *Right.Previous; @@ -1792,6 +1796,26 @@ Left.isOneOf(TT_TemplateCloser, TT_TemplateOpener)); if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser))) return Style.SpacesInAngles; + // No space needed between "<<" and "<" in "<<<". + if (Left.is(tok::lessless) && Right.is(tok::less) && + noPrecedingWhitespace(Right)) + return false; + // No space needed between identifier and "<<<". This avoids changing "f<<<" + // to "f <<<" + if (Left.Tok.getIdentifierInfo() && Right.is(tok::lessless) && Right.Next && + Right.Next->is(tok::less) && noPrecedingWhitespace(*Right.Next)) + return false; + // No space needed between ">" and "<<<". Avoids changing "f<<<" to + // "f <<<". + if (Left.is(tok::greater) && Right.is(tok::lessless) && Right.Next && + Right.Next->is(tok::less) && noPrecedingWhitespace(*Right.Next)) + return false; + // No space needed between ">>>" and "(" + if (Right.is(tok::l_paren) && Left.is(tok::greater) && Left.Previous && + Left.Previous->is(tok::greater) && Left.Previous->Previous && + Left.Previous->Previous->is(tok::greater) && + noPrecedingWhitespace(Left) && noPrecedingWhitespace(*Left.Previous)) + return false; if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) || Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) return true; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -9613,6 +9613,15 @@ verifyFormat("A>();", Spaces); } +TEST_F(FormatTest, TrippleAngleBraces) { + verifyFormat("f<<<1, 1>>>();"); + EXPECT_EQ("f<<<1, 1>>>();", + format("f <<< 1, 1 >>> ();")); + verifyFormat("f<<<1, 1>>>();"); + EXPECT_EQ("f<<<1, 1>>>();", + format("f< param > <<< 1, 1 >>> ();")); +} + TEST_F(FormatTest, HandleUnbalancedImplicitBracesAcrossPPBranches) { std::string code = "#if A\n" "#if B\n"