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 +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits