Index: clang-tidy/readability/MisleadingIndentationCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/MisleadingIndentationCheck.h @@ -0,0 +1,40 @@ +//===--- 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; + +private: + 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/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -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( "readability-inconsistent-declaration-parameter-name"); + CheckFactories.registerCheck( + "readability-misleading-indentation"); CheckFactories.registerCheck( "readability-named-parameter"); CheckFactories.registerCheck( 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: docs/clang-tidy/checks/readability-misleading-indentation.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-misleading-indentation.rst @@ -0,0 +1,36 @@ +.. title:: clang-tidy - readability-misleading-indentation + +readability-misleading-indentation +================================== + +Description + +Correct indentation helps to understand code. Mismatch of the syntactical +structure and the indentation of the code may reveal serious problems. +Missing braces can also cause some problems in analyzing 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 part of if(cond1) Index: test/clang-tidy/readability-misleading-indentation.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-misleading-indentation.cpp @@ -0,0 +1,131 @@ +// 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 + + if (cond1) { // ok + foo1(); + } else { + foo2(); + } + + if (cond1) + foo1(); + else + foo2(); // ok + + if (cond1) { // ok + foo1(); + } else { + foo2(); + } + + if (cond1) // ok + { + foo1(); + } else { + foo2(); + } + + if (cond1) // ok + { + foo1(); + } else { + foo2(); + } + + while (cond1) { + foo1(); + } + foo2(); // ok + + while (cond1) + foo1(); + foo2(); // comment + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: not part of while(cond1) + // CHECK-FIXES: {{^}} // comment + + while (cond1) { + foo1(); + } + foo2(); // ok + + while (cond1) + foo1(); + foo2(); // ok + + for (;;) { + foo1(); + } + foo2(); // ok + + for (;;) + foo1(); + foo2(); // comment + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: not part of for(;;) + // CHECK-FIXES: {{^}} // comment + + for (;;) { + foo1(); + } + foo2(); // ok + + for (;;) + foo1(); + foo2(); // ok + + return 0; +}