[clang-tools-extra] r295041 - [clang-tidy] Add readability-misleading-indentation check.

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 14 02:03:27 PST 2017


Author: xazax
Date: Tue Feb 14 04:03:27 2017
New Revision: 295041

URL: http://llvm.org/viewvc/llvm-project?rev=295041&view=rev
Log:
[clang-tidy] Add readability-misleading-indentation check.

Differential Revision: https://reviews.llvm.org/D19586

Added:
    clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.cpp
    clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/readability-misleading-indentation.rst
    clang-tools-extra/trunk/test/clang-tidy/readability-misleading-indentation.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=295041&r1=295040&r2=295041&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Tue Feb 14 04:03:27 2017
@@ -11,6 +11,7 @@ add_clang_library(clangTidyReadabilityMo
   IdentifierNamingCheck.cpp
   ImplicitBoolCastCheck.cpp
   InconsistentDeclarationParameterNameCheck.cpp
+  MisleadingIndentationCheck.cpp
   MisplacedArrayIndexCheck.cpp
   NamedParameterCheck.cpp
   NamespaceCommentCheck.cpp

Added: clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.cpp?rev=295041&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.cpp Tue Feb 14 04:03:27 2017
@@ -0,0 +1,103 @@
+//===--- MisleadingIndentationCheck.cpp - clang-tidy-----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MisleadingIndentationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM,
+                                                   const IfStmt *If) {
+  SourceLocation IfLoc = If->getIfLoc();
+  SourceLocation ElseLoc = If->getElseLoc();
+
+  if (IfLoc.isMacroID() || ElseLoc.isMacroID())
+    return;
+
+  if (SM.getExpansionLineNumber(If->getThen()->getLocEnd()) ==
+      SM.getExpansionLineNumber(ElseLoc))
+    return;
+
+  if (SM.getExpansionColumnNumber(IfLoc) !=
+      SM.getExpansionColumnNumber(ElseLoc))
+    diag(ElseLoc, "different indentation for 'if' and corresponding 'else'");
+}
+
+void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM,
+                                                    const CompoundStmt *CStmt) {
+  const static StringRef StmtNames[] = {"if", "for", "while"};
+  for (unsigned int i = 0; i < CStmt->size() - 1; i++) {
+    const Stmt *CurrentStmt = CStmt->body_begin()[i];
+    const Stmt *Inner = nullptr;
+    int StmtKind = 0;
+
+    if (const auto *CurrentIf = dyn_cast<IfStmt>(CurrentStmt)) {
+      StmtKind = 0;
+      Inner =
+          CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen();
+    } else if (const auto *CurrentFor = dyn_cast<ForStmt>(CurrentStmt)) {
+      StmtKind = 1;
+      Inner = CurrentFor->getBody();
+    } else if (const auto *CurrentWhile = dyn_cast<WhileStmt>(CurrentStmt)) {
+      StmtKind = 2;
+      Inner = CurrentWhile->getBody();
+    } else {
+      continue;
+    }
+
+    if (isa<CompoundStmt>(Inner))
+      continue;
+
+    SourceLocation InnerLoc = Inner->getLocStart();
+    SourceLocation OuterLoc = CurrentStmt->getLocStart();
+
+    if (SM.getExpansionLineNumber(InnerLoc) ==
+        SM.getExpansionLineNumber(OuterLoc))
+      continue;
+
+    const Stmt *NextStmt = CStmt->body_begin()[i + 1];
+    SourceLocation NextLoc = NextStmt->getLocStart();
+
+    if (InnerLoc.isMacroID() || OuterLoc.isMacroID() || NextLoc.isMacroID())
+      continue;
+
+    if (SM.getExpansionColumnNumber(InnerLoc) ==
+        SM.getExpansionColumnNumber(NextLoc)) {
+      diag(NextLoc, "misleading indentation: statement is indented too deeply");
+      diag(OuterLoc, "did you mean this line to be inside this '%0'",
+           DiagnosticIDs::Note)
+          << StmtNames[StmtKind];
+    }
+  }
+}
+
+void MisleadingIndentationCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(ifStmt(hasElse(stmt())).bind("if"), this);
+  Finder->addMatcher(
+      compoundStmt(has(stmt(anyOf(ifStmt(), forStmt(), whileStmt()))))
+          .bind("compound"),
+      this);
+}
+
+void MisleadingIndentationCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *If = Result.Nodes.getNodeAs<IfStmt>("if"))
+    danglingElseCheck(*Result.SourceManager, If);
+
+  if (const auto *CStmt = Result.Nodes.getNodeAs<CompoundStmt>("compound"))
+    missingBracesCheck(*Result.SourceManager, CStmt);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.h?rev=295041&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/MisleadingIndentationCheck.h Tue Feb 14 04:03:27 2017
@@ -0,0 +1,41 @@
+//===--- MisleadingIndentationCheck.h - clang-tidy---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks the code for dangling else, and possible misleading indentations due
+/// to missing braces. Note that this check only works as expected when the tabs
+/// or spaces are used consistently and not mixed.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-misleading-indentation.html
+class MisleadingIndentationCheck : public ClangTidyCheck {
+public:
+  MisleadingIndentationCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void danglingElseCheck(const SourceManager &SM, const IfStmt *If);
+  void missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H

Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=295041&r1=295040&r2=295041&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Tue Feb 14 04:03:27 2017
@@ -20,6 +20,7 @@
 #include "IdentifierNamingCheck.h"
 #include "ImplicitBoolCastCheck.h"
 #include "InconsistentDeclarationParameterNameCheck.h"
+#include "MisleadingIndentationCheck.h"
 #include "MisplacedArrayIndexCheck.h"
 #include "NamedParameterCheck.h"
 #include "NonConstParameterCheck.h"
@@ -61,6 +62,8 @@ public:
         "readability-implicit-bool-cast");
     CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
         "readability-inconsistent-declaration-parameter-name");
+    CheckFactories.registerCheck<MisleadingIndentationCheck>(
+        "readability-misleading-indentation");
     CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
         "readability-misplaced-array-index");
     CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=295041&r1=295040&r2=295041&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Feb 14 04:03:27 2017
@@ -57,6 +57,11 @@ The improvements are...
 Improvements to clang-tidy
 --------------------------
 
+- New `readability-misleading-indentation
+  <http://clang.llvm.org/extra/clang-tidy/checks/readability-misleading-indentation.html>`_ check
+
+  Finds misleading indentation where braces should be introduced or the code should be reformatted.
+
 - New `safety-no-assembler
   <http://clang.llvm.org/extra/clang-tidy/checks/safety-no-assembler.html>`_ check
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=295041&r1=295040&r2=295041&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Feb 14 04:03:27 2017
@@ -139,6 +139,7 @@ Clang-Tidy Checks
    readability-identifier-naming
    readability-implicit-bool-cast
    readability-inconsistent-declaration-parameter-name
+   readability-misleading-indentation
    readability-misplaced-array-index
    readability-named-parameter
    readability-non-const-parameter

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-misleading-indentation.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-misleading-indentation.rst?rev=295041&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-misleading-indentation.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-misleading-indentation.rst Tue Feb 14 04:03:27 2017
@@ -0,0 +1,38 @@
+.. title:: clang-tidy - readability-misleading-indentation
+
+readability-misleading-indentation
+==================================
+
+Correct indentation helps to understand code. Mismatch of the syntactical
+structure and the indentation of the code may hide serious problems.
+Missing braces can also make it significantly harder to read the code,
+therefore it is important to use braces. 
+
+The way to avoid dangling else is to always check that an ``else`` belongs
+to the ``if`` that begins in the same column.
+
+You can omit braces when your inner part of e.g. an ``if`` statement has only
+one statement in it. Although in that case you should begin the next statement
+in the same column with the ``if``.
+
+Examples:
+
+.. code-block:: c++
+
+  // Dangling else:
+  if (cond1)
+    if (cond2)
+      foo1();
+  else
+    foo2();  // Wrong indentation: else belongs to if(cond2) statement.
+
+  // Missing braces:
+  if (cond1)
+    foo1();
+    foo2();  // Not guarded by if(cond1).
+
+Limitations
+===========
+
+Note that this check only works as expected when the tabs or spaces are used
+consistently and not mixed.

Added: clang-tools-extra/trunk/test/clang-tidy/readability-misleading-indentation.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-misleading-indentation.cpp?rev=295041&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-misleading-indentation.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-misleading-indentation.cpp Tue Feb 14 04:03:27 2017
@@ -0,0 +1,80 @@
+// RUN: %check_clang_tidy %s readability-misleading-indentation %t
+
+void foo1();
+void foo2();
+
+#define BLOCK \
+  if (cond1)  \
+    foo1();   \
+    foo2();
+
+int main()
+{
+  bool cond1 = true;
+  bool cond2 = true;
+
+  if (cond1)
+    if (cond2)
+      foo1();
+  else
+    foo2();
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
+
+  if (cond1) {
+    if (cond2)
+      foo1();
+  }
+  else
+    foo2();
+
+  if (cond1)
+    if (cond2)
+      foo1();
+    else
+      foo2();
+
+  if (cond2)
+    foo1();
+    foo2();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: misleading indentation: statement is indented too deeply [readability-misleading-indentation]
+    // CHECK-MESSAGES: :[[@LINE-4]]:3: note: did you mean this line to be inside this 'if'
+    foo2(); // No redundant warning.
+
+  if (cond1)
+  {
+    foo1();
+  }
+    foo2();
+
+  if (cond1)
+    foo1();
+  foo2();
+
+  if (cond2)
+    if (cond1) foo1(); else foo2();
+
+  if (cond1) {
+  } else {
+  }
+
+  if (cond1) {
+  }
+  else {
+  }
+
+  if (cond1)
+  {
+  }
+  else
+  {
+  }
+
+  if (cond1)
+    {
+    }
+  else
+    {
+    }
+
+  BLOCK
+}




More information about the cfe-commits mailing list