Commit b47b35ff authored by Tyker's avatar Tyker
Browse files

[Diagnostic] Add ftabstop to -Wmisleading-indentation

Summary:
this allow much better support of codebases like the linux kernel that mix tabs and spaces.

-ftabstop=//Width// allow specifying how large tabs are considered to be.

Reviewers: xbolva00, aaron.ballman, rsmith

Reviewed By: aaron.ballman

Subscribers: jyknight, riccibruno, rsmith, nathanchance

Differential Revision: https://reviews.llvm.org/D71037
parent 65661908
Loading
Loading
Loading
Loading
+38 −3
Original line number Diff line number Diff line
@@ -1214,6 +1214,41 @@ struct MisleadingIndentationChecker {
    if (Kind == MSK_else && !ShouldSkip)
      P.MisleadingIndentationElseLoc = SL;
  }

  /// Compute the column number will aligning tabs on TabStop (-ftabstop), this
  /// gives the visual indentation of the SourceLocation.
  static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
    unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;

    unsigned ColNo = SM.getSpellingColumnNumber(Loc);
    if (ColNo == 0 || TabStop == 1)
      return ColNo;

    std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);

    bool Invalid;
    StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
    if (Invalid)
      return 0;

    const char *EndPos = BufData.data() + FIDAndOffset.second;
    assert(FIDAndOffset.second > ColNo &&
           "Column number smaller than file offset?");

    unsigned VisualColumn = 0; // Stored as 0-based column, here.
    // Loop from beginning of line up to Loc's file position, counting columns,
    // expanding tabs.
    for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
         ++CurPos) {
      if (*CurPos == '\t')
        // Advance visual column to next tabstop.
        VisualColumn += (TabStop - VisualColumn % TabStop);
      else
        VisualColumn++;
    }
    return VisualColumn + 1;
  }

  void Check() {
    Token Tok = P.getCurToken();
    if (P.getActions().getDiagnostics().isIgnored(
@@ -1230,9 +1265,9 @@ struct MisleadingIndentationChecker {
      P.MisleadingIndentationElseLoc = SourceLocation();

    SourceManager &SM = P.getPreprocessor().getSourceManager();
    unsigned PrevColNum = SM.getSpellingColumnNumber(PrevLoc);
    unsigned CurColNum = SM.getSpellingColumnNumber(Tok.getLocation());
    unsigned StmtColNum = SM.getSpellingColumnNumber(StmtLoc);
    unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
    unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
    unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);

    if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
        ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
+81 −2
Original line number Diff line number Diff line
// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wmisleading-indentation -DWITH_WARN %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN -DCXX17 %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -Wno-misleading-indentation -DCXX17 %s
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wmisleading-indentation -DWITH_WARN -ftabstop 8 -DTAB_SIZE=8 %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN  -ftabstop 4 -DTAB_SIZE=4 -DCXX17 %s
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN -ftabstop 1 -DTAB_SIZE=1 %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -Wmisleading-indentation -DCXX17 -DWITH_WARN -ftabstop 2 -DTAB_SIZE=2 %s

#ifndef WITH_WARN
// expected-no-diagnostics
@@ -225,3 +227,80 @@ void s(int num) {
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
#endif
}
int a4()
{
	if (0)
		return 1;
 	return 0;
#if (TAB_SIZE == 1)
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
// expected-note@-5 {{here}}
#endif 
}

int a5()
{
	if (0)
		return 1;
		return 0;
#if WITH_WARN
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
// expected-note@-5 {{here}}
#endif
}

int a6()
{
	if (0)
		return 1;
      		return 0;
#if (TAB_SIZE == 8)
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
// expected-note@-5 {{here}}
#endif
}

#define FOO \
 goto fail

int main(int argc, char* argv[]) {
  if (5 != 0)
    goto fail;
  else
    goto fail;

  if (1) {
    if (1)
      goto fail;
    else if (1)
      goto fail;
    else if (1)
      goto fail;
    else
      goto fail;
  } else if (1) {
    if (1)
      goto fail;
  }

  if (1) {
    if (1)
      goto fail;
  } else if (1)
    goto fail;


  if (1) goto fail; goto fail;

    if (0)
        goto fail;

    goto fail;

    if (0)
        FOO;

    goto fail;

fail:;
}