Index: clang-tidy/readability/MisleadingIndentationCheck.h =================================================================== --- clang-tidy/readability/MisleadingIndentationCheck.h +++ clang-tidy/readability/MisleadingIndentationCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H #include "../ClangTidy.h" +#include "llvm/ADT/DenseMap.h" namespace clang { namespace tidy { @@ -32,6 +33,10 @@ private: void danglingElseCheck(const SourceManager &SM, const IfStmt *If); void missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt); + + /// Key: Chained If + /// Value: Preceding If + llvm::DenseMap ChainedIfs; }; } // namespace readability Index: clang-tidy/readability/MisleadingIndentationCheck.cpp =================================================================== --- clang-tidy/readability/MisleadingIndentationCheck.cpp +++ clang-tidy/readability/MisleadingIndentationCheck.cpp @@ -25,10 +25,22 @@ if (IfLoc.isMacroID() || ElseLoc.isMacroID()) return; + if (const auto *ChainedIf = dyn_cast(If->getElse())) { + if (SM.getExpansionLineNumber(ElseLoc) == + SM.getExpansionLineNumber(ChainedIf->getIfLoc())) + ChainedIfs.insert({ ChainedIf, If }); + } + if (SM.getExpansionLineNumber(If->getThen()->getLocEnd()) == SM.getExpansionLineNumber(ElseLoc)) return; + // Find location of first 'if' in a 'if else if' chain. + // Works because parent nodes will be matched before child nodes. + for (auto Iter = ChainedIfs.find(If); Iter != ChainedIfs.end(); + Iter = ChainedIfs.find(Iter->second)) + IfLoc = Iter->second->getIfLoc(); + if (SM.getExpansionColumnNumber(IfLoc) != SM.getExpansionColumnNumber(ElseLoc)) diag(ElseLoc, "different indentation for 'if' and corresponding 'else'"); Index: test/clang-tidy/readability-misleading-indentation.cpp =================================================================== --- test/clang-tidy/readability-misleading-indentation.cpp +++ test/clang-tidy/readability-misleading-indentation.cpp @@ -76,5 +76,31 @@ { } + if(cond1) { + } + else if (cond2) { + } + else { + } + + if(cond1) { + } + else if (cond2) { + } + else { + } + // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation] + + if (cond1) { + if (cond1) { + } + else if (cond2) { + } + else { + } + } + else if (cond2) { + } + BLOCK }