Commit 16b04ba2 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r311792:

------------------------------------------------------------------------
r311792 | djasper | 2017-08-25 12:14:53 -0700 (Fri, 25 Aug 2017) | 9 lines

[Format] Invert nestingAndIndentLevel pair in WhitespaceManager used for
alignments

Indent should be compared before nesting level to determine if a token
is on the same scope as the one we align with. Because it was inverted,
clang-format sometimes tried to align tokens with tokens from outer
scopes, causing the assert(Shift >= 0) to fire.

This fixes bug #33507. Patch by Beren Minor, thank you!
------------------------------------------------------------------------

llvm-svn: 311800
parent 6493242f
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -246,12 +246,12 @@ AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,

  for (unsigned i = Start; i != End; ++i) {
    if (ScopeStack.size() != 0 &&
        Changes[i].nestingAndIndentLevel() <
            Changes[ScopeStack.back()].nestingAndIndentLevel())
        Changes[i].indentAndNestingLevel() <
            Changes[ScopeStack.back()].indentAndNestingLevel())
      ScopeStack.pop_back();

    if (i != Start && Changes[i].nestingAndIndentLevel() >
                          Changes[i - 1].nestingAndIndentLevel())
    if (i != Start && Changes[i].indentAndNestingLevel() >
                          Changes[i - 1].indentAndNestingLevel())
      ScopeStack.push_back(i);

    bool InsideNestedScope = ScopeStack.size() != 0;
@@ -327,8 +327,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,

  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
  // abort when we hit any token in a higher scope than the starting one.
  auto NestingAndIndentLevel = StartAt < Changes.size()
                                   ? Changes[StartAt].nestingAndIndentLevel()
  auto IndentAndNestingLevel = StartAt < Changes.size()
                                   ? Changes[StartAt].indentAndNestingLevel()
                                   : std::pair<unsigned, unsigned>(0, 0);

  // Keep track of the number of commas before the matching tokens, we will only
@@ -359,7 +359,7 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,

  unsigned i = StartAt;
  for (unsigned e = Changes.size(); i != e; ++i) {
    if (Changes[i].nestingAndIndentLevel() < NestingAndIndentLevel)
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
      break;

    if (Changes[i].NewlinesBefore != 0) {
@@ -375,7 +375,7 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,

    if (Changes[i].Tok->is(tok::comma)) {
      ++CommasBeforeMatch;
    } else if (Changes[i].nestingAndIndentLevel() > NestingAndIndentLevel) {
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
      // Call AlignTokens recursively, skipping over this scope block.
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i);
      i = StoppedAt - 1;
+3 −4
Original line number Diff line number Diff line
@@ -154,12 +154,11 @@ public:
    const Change *StartOfBlockComment;
    int IndentationOffset;

    // A combination of nesting level and indent level, which are used in
    // A combination of indent level and nesting level, which are used in
    // tandem to compute lexical scope, for the purposes of deciding
    // when to stop consecutive alignment runs.
    std::pair<unsigned, unsigned>
    nestingAndIndentLevel() const {
      return std::make_pair(Tok->NestingLevel, Tok->IndentLevel);
    std::pair<unsigned, unsigned> indentAndNestingLevel() const {
      return std::make_pair(Tok->IndentLevel, Tok->NestingLevel);
    }
  };

+10 −0
Original line number Diff line number Diff line
@@ -8860,6 +8860,16 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
               Alignment);
  Alignment.BinPackParameters = true;
  Alignment.ColumnLimit = 80;

  // Bug 33507
  Alignment.PointerAlignment = FormatStyle::PAS_Middle;
  verifyFormat(
      "auto found = range::find_if(vsProducts, [&](auto * aProduct) {\n"
      "  static const Version verVs2017;\n"
      "  return true;\n"
      "});\n",
      Alignment);
  Alignment.PointerAlignment = FormatStyle::PAS_Right;
}

TEST_F(FormatTest, LinuxBraceBreaking) {