Pajesz created this revision.
Pajesz added a reviewer: alexfh.
Pajesz added subscribers: cfe-commits, xazax.hun.

This is a clang-tidy check for llvm. It checks for dangling else and for 
possible misleading indentation due to omitted braces. 


http://reviews.llvm.org/D19586

Files:
  clang-tidy/readability/CMakeLists.txt
  clang-tidy/readability/Mislead
  clang-tidy/readability/Misleadin
  clang-tidy/readability/ReadabilityT
  docs/clang-tidy/checks
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/readability-m

Index: test/clang-tidy/readability-m
===================================================================
--- /dev/null
+++ test/clang-tidy/readability-m
@@ -0,0 +1,62 @@
+// RUN: %check_clang_tidy %s readability-misleading-indentation %t
+
+void foo1() {}
+void foo2() {}
+
+int main()
+{
+   bool cond1 = true;
+   bool cond2 = true;
+
+   if (cond1)
+      if (cond2)
+         foo1();
+   else
+     foo2();  // comment
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: wrong indentation, else belongs to if(cond2) statement
+// CHECK-FIXES: {{^}}  // comment
+
+   if (cond1) {
+      if (cond2)
+         foo1();
+   }
+   else
+      foo2();  // ok, else belongs to if(cond1) statement
+
+   if (cond1)
+     if (cond2)
+        foo1();
+     else
+        foo2();  // ok, indentation matches to syntactical structure
+
+   if (cond1)
+      foo1();
+      foo2(); // comment
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: not part of if(cond1)
+// CHECK-FIXES: {{^}}  // comment
+
+   if (cond2)
+      foo1();
+      foo2(); // comment
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: not part of if(cond2)
+// CHECK-FIXES: {{^}}  // comment
+
+   if (cond1)
+   {
+      foo1();
+   }
+      foo2();  // ok
+
+   if (cond1)
+      foo1();
+   foo2();  // ok
+
+  if (cond1)
+      foo1();
+      foo2(); // comment
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: not part of if(cond1)
+// CHECK-FIXES: {{^}}  // comment
+      foo2(); // no need for redundant warning
+
+   return 0;
+}
Index: docs/clang-tidy/checks
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - readability-misleading-indentation
+
+readability-misleading-indentation
+==================================
+
+Description
+
+Correct indentation helps to understand code. Mismatch of the syntactical structure and the indent
+
+The way to avoid dangling else is to always check that an else belongs to the if that begins in th
+
+You can omit braces when your inner part of e.g. an IF statement has only one statement in it. Alt
+
+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 part of if(cond1)
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -93,6 +93,7 @@
    readability-identifier-naming
    readability-implicit-bool-cast
    readability-inconsistent-declaration-parameter-name
+   readability-misleading-indentation
    readability-named-parameter
    readability-redundant-control-flow
    readability-redundant-smartptr-get
Index: clang-tidy/readability/ReadabilityT
===================================================================
--- clang-tidy/readability/ReadabilityT
+++ clang-tidy/readability/ReadabilityT
@@ -17,6 +17,7 @@
 #include "IdentifierNamingCheck.h"
 #include "ImplicitBoolCastCheck.h"
 #include "InconsistentDeclarationParameterNameCheck.h"
+#include "MisleadingIndentationCheck.h"
 #include "NamedParameterCheck.h"
 #include "RedundantControlFlowCheck.h"
 #include "RedundantSmartptrGetCheck.h"
@@ -45,6 +46,8 @@
         "readability-implicit-bool-cast");
     CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
         "readability-inconsistent-declaration-parameter-name");
+    CheckFactories.registerCheck<MisleadingIndentationCheck>(
+        "readability-misleading-indentation");
     CheckFactories.registerCheck<readability::NamedParameterCheck>(
         "readability-named-parameter");
     CheckFactories.registerCheck<RedundantControlFlowCheck>(
Index: clang-tidy/readability/Misleadin
===================================================================
--- /dev/null
+++ clang-tidy/readability/Misleadin
@@ -0,0 +1,38 @@
+//===--- 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.
+///
+/// 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;
+  void danglingElseCheck(const ast_matchers::MatchFinder::MatchResult &Result);
+  void missingBracesCheck(const ast_matchers::MatchFinder::MatchResult &Result);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
Index: clang-tidy/readability/Mislead
===================================================================
--- /dev/null
+++ clang-tidy/readability/Mislead
@@ -0,0 +1,77 @@
+//===--- 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 MatchFinder::MatchResult &Result) {
+  auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+  if (!If->getElse())
+    return;
+
+  SourceLocation IfLoc = If->getIfLoc();
+  SourceLocation ElseLoc = If->getElseLoc();
+
+  if (Result.SourceManager->getExpansionColumnNumber(IfLoc) !=
+      Result.SourceManager->getExpansionColumnNumber(ElseLoc))
+    diag(ElseLoc, "potentional dangling else");
+}
+
+void MisleadingIndentationCheck::missingBracesCheck(
+    const MatchFinder::MatchResult &Result) {
+  auto *CStmt = Result.Nodes.getNodeAs<CompoundStmt>("stmt");
+  for (unsigned int i = 0; i < CStmt->size() - 1; i++) {
+    Stmt *CurrentStmt = CStmt->body_begin()[i];
+
+    if (!isa<IfStmt>(CurrentStmt))
+      continue;
+
+    IfStmt *CurrentIf = dyn_cast<IfStmt>(CurrentStmt);
+    Stmt *InIf =
+        CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen();
+
+    if (isa<CompoundStmt>(InIf))
+      continue;
+
+    SourceLocation StmtLoc = InIf->getLocStart();
+    Stmt *NextStmt = CStmt->body_begin()[i + 1];
+    SourceLocation NextLoc = NextStmt->getLocStart();
+
+    if (Result.SourceManager->getExpansionColumnNumber(StmtLoc) ==
+        Result.SourceManager->getExpansionColumnNumber(NextLoc))
+      diag(NextLoc, "Wrong Indentation - statement is indentated as a member "
+                    "of if statement");
+  }
+}
+
+void MisleadingIndentationCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(ifStmt().bind("if"), this);
+  Finder->addMatcher(compoundStmt(has(ifStmt())).bind("stmt"), this);
+}
+
+void MisleadingIndentationCheck::check(const MatchFinder::MatchResult &Result) {
+
+  if (Result.Nodes.getNodeAs<IfStmt>("if"))
+    danglingElseCheck(Result);
+
+  if (Result.Nodes.getNodeAs<CompoundStmt>("stmt"))
+    missingBracesCheck(Result);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tidy/readability/CMakeLists.txt
+++ clang-tidy/readability/CMakeLists.txt
@@ -8,6 +8,7 @@
   IdentifierNamingCheck.cpp
   ImplicitBoolCastCheck.cpp
   InconsistentDeclarationParameterNameCheck.cpp
+  MisleadingIndentationCheck.cpp
   NamedParameterCheck.cpp
   NamespaceCommentCheck.cpp
   ReadabilityTidyModule.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to