Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3294,6 +3294,10 @@ return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd(); }; + // If the token is finalized don't touch it (as it could be in a clang-format-off section). + if (Left.Finalized) + return HasExistingWhitespace(); + if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo()) return true; // Never ever merge two identifiers. Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -21172,6 +21172,22 @@ verifyFormat("A< A< int > >();", Spaces); verifyFormat("A >();", Spaces); verifyFormat("A< A< int>>();", Spaces); + + Spaces.SpacesInAngles = FormatStyle::SIAS_Always; + EXPECT_EQ("// clang-format off\n" + "foo<<<1, 1>>>();\n" + "// clang-format on\n", + format("// clang-format off\n" + "foo<<<1, 1>>>();\n" + "// clang-format on\n", + Spaces)); + EXPECT_EQ("// clang-format off\n" + "foo< < <1, 1> > >();\n" + "// clang-format on\n", + format("// clang-format off\n" + "foo< < <1, 1> > >();\n" + "// clang-format on\n", + Spaces)); } TEST_F(FormatTest, SpaceAfterTemplateKeyword) {