Index: lib/Format/WhitespaceManager.cpp =================================================================== --- lib/Format/WhitespaceManager.cpp +++ lib/Format/WhitespaceManager.cpp @@ -100,14 +100,52 @@ Changes[0].PreviousEndOfTokenColumn = 0; Change *LastOutsideTokenChange = &Changes[0]; for (unsigned i = 1, e = Changes.size(); i != e; ++i) { - unsigned OriginalWhitespaceStart = - SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin()); - unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset( - Changes[i - 1].OriginalWhitespaceRange.getEnd()); - Changes[i - 1].TokenLength = OriginalWhitespaceStart - - PreviousOriginalWhitespaceEnd + - Changes[i].PreviousLinePostfix.size() + - Changes[i - 1].CurrentLinePrefix.size(); + SourceLocation OriginalWhitespaceStart = + Changes[i].OriginalWhitespaceRange.getBegin(); + SourceLocation PreviousOriginalWhitespaceEnd = + Changes[i - 1].OriginalWhitespaceRange.getEnd(); + unsigned OriginalWhitespaceStartOffset = + SourceMgr.getFileOffset(OriginalWhitespaceStart); + unsigned PreviousOriginalWhitespaceEndOffset = + SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd); + assert(PreviousOriginalWhitespaceEndOffset <= + OriginalWhitespaceStartOffset); + const char *const PreviousOriginalWhitespaceEndData = + SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd); + StringRef Text(PreviousOriginalWhitespaceEndData, + SourceMgr.getCharacterData(OriginalWhitespaceStart) - + PreviousOriginalWhitespaceEndData); + // Usually consecutive changes would occur in consecutive tokens. This is + // not the case however when analyzing some preprocessor runs of the + // annotated lines. For example, in this code: + // + // #if A // line 1 + // int i = 1; + // #else B // line 2 + // int i = 2; + // #endif // line 3 + // + // one of the runs will produce the sequence of lines marked with line 1, 2 + // and 3. So the two consecutive whitespace changes just before '// line 2' + // and before '#endif // line 3' span multiple lines and tokens: + // + // #else B{change X}[// line 2 + // int i = 2; + // ]{change Y}#endif // line 3 + // + // For this reason, if the text between consecutive changes spans multiple + // newlines, the token length must be adjusted to the end of the original + // line of the token. + auto NewlinePos = Text.find_first_of('\n'); + if (NewlinePos == StringRef::npos) { + Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset - + PreviousOriginalWhitespaceEndOffset + + Changes[i].PreviousLinePostfix.size() + + Changes[i - 1].CurrentLinePrefix.size(); + } else { + Changes[i - 1].TokenLength = + NewlinePos + Changes[i - 1].CurrentLinePrefix.size(); + } // If there are multiple changes in this token, sum up all the changes until // the end of the line. Index: unittests/Format/FormatTestComments.cpp =================================================================== --- unittests/Format/FormatTestComments.cpp +++ unittests/Format/FormatTestComments.cpp @@ -1052,6 +1052,30 @@ "}", getLLVMStyleWithColumns(80)); } +TEST_F(FormatTestComments, AlignsPPElseEndifComments) { + verifyFormat("#if A\n" + "#else // A\n" + "int iiii;\n" + "#endif // B", + getLLVMStyleWithColumns(20)); + verifyFormat("#if A\n" + "#else // A\n" + "int iiii; // CC\n" + "#endif // B", + getLLVMStyleWithColumns(20)); + EXPECT_EQ("#if A\n" + "#else // A1\n" + " // A2\n" + "int ii;\n" + "#endif // B", + format("#if A\n" + "#else // A1\n" + " // A2\n" + "int ii;\n" + "#endif // B", + getLLVMStyleWithColumns(20))); +} + TEST_F(FormatTestComments, CommentsInStaticInitializers) { EXPECT_EQ( "static SomeType type = {aaaaaaaaaaaaaaaaaaaa, /* comment */\n"