Index: clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.h =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.h +++ clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.h @@ -43,9 +43,10 @@ void check(const ast_matchers::MatchFinder::MatchResult &Result) override; private: - void checkStmt(const ast_matchers::MatchFinder::MatchResult &Result, + bool checkStmt(const ast_matchers::MatchFinder::MatchResult &Result, const Stmt *S, SourceLocation StartLoc, - SourceLocation EndLocHint = SourceLocation()); + SourceLocation EndLocHint = SourceLocation(), + bool ForceBraces = false); template SourceLocation findRParenLoc(const IfOrWhileStmt *S, const SourceManager &SM, const ASTContext *Context); Index: clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/readability/BracesAroundStatementsCheck.cpp @@ -151,11 +151,11 @@ SourceLocation StartLoc = findRParenLoc(S, SM, Context); if (StartLoc.isInvalid()) return; - checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc()); + bool BracedIf = checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc()); const Stmt *Else = S->getElse(); if (Else && !isa(Else)) { // Omit 'else if' statements here, they will be handled directly. - checkStmt(Result, Else, S->getElseLoc()); + checkStmt(Result, Else, S->getElseLoc(), SourceLocation(), BracedIf); } } else { llvm_unreachable("Invalid match"); @@ -199,10 +199,11 @@ return RParenLoc; } -void -BracesAroundStatementsCheck::checkStmt(const MatchFinder::MatchResult &Result, - const Stmt *S, SourceLocation InitialLoc, - SourceLocation EndLocHint) { +/// Determine if the statement needs braces around it, and add them if it does. +/// Returns true if braces where added. +bool BracesAroundStatementsCheck::checkStmt( + const MatchFinder::MatchResult &Result, const Stmt *S, + SourceLocation InitialLoc, SourceLocation EndLocHint, bool ForceBraces) { // 1) If there's a corresponding "else" or "while", the check inserts "} " // right before that token. // 2) If there's a multi-line block comment starting on the same line after @@ -212,11 +213,11 @@ // line comments) and inserts "\n}" right before that EOL. if (!S || isa(S)) { // Already inside braces. - return; + return false; } // Skip macros. if (S->getLocStart().isMacroID()) - return; + return false; const SourceManager &SM = *Result.SourceManager; const ASTContext *Context = Result.Context; @@ -240,16 +241,17 @@ assert(EndLoc.isValid()); // Don't require braces for statements spanning less than certain number of // lines. - if (ShortStatementLines) { + if (ShortStatementLines && !ForceBraces) { unsigned StartLine = SM.getSpellingLineNumber(StartLoc); unsigned EndLine = SM.getSpellingLineNumber(EndLoc); if (EndLine - StartLine < ShortStatementLines) - return; + return false; } auto Diag = diag(StartLoc, "statement should be inside braces"); Diag << FixItHint::CreateInsertion(StartLoc, " {") << FixItHint::CreateInsertion(EndLoc, ClosingInsertion); + return true; } } // namespace readability Index: clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h =================================================================== --- clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h +++ clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h @@ -42,11 +42,12 @@ }; template -std::string runCheckOnCode(StringRef Code, - std::vector *Errors = nullptr, - const Twine &Filename = "input.cc", - ArrayRef ExtraArgs = None) { - ClangTidyOptions Options; +std::string +runCheckOnCode(StringRef Code, std::vector *Errors = nullptr, + const Twine &Filename = "input.cc", + ArrayRef ExtraArgs = None, + const ClangTidyOptions &ExtraOptions = ClangTidyOptions()) { + ClangTidyOptions Options = ExtraOptions; Options.Checks = "*"; ClangTidyContext Context(llvm::make_unique( ClangTidyGlobalOptions(), Options)); Index: clang-tools-extra/trunk/unittests/clang-tidy/ReadabilityModuleTest.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clang-tidy/ReadabilityModuleTest.cpp +++ clang-tools-extra/trunk/unittests/clang-tidy/ReadabilityModuleTest.cpp @@ -235,6 +235,27 @@ "}")); } +TEST(BracesAroundStatementsCheck, IfElseWithShortStatements) { + ClangTidyOptions Options; + Options.CheckOptions["test-check.ShortStatementLines"] = "1"; + + EXPECT_EQ("int main() {\n" + " if (true) return 1;\n" + " if (false) { return -1;\n" + " } else if (1 == 2) { return -2;\n" + " } else { return -3;\n" + "}\n" + "}", + runCheckOnCode( + "int main() {\n" + " if (true) return 1;\n" + " if (false) return -1;\n" + " else if (1 == 2) return -2;\n" + " else return -3;\n" + "}", + nullptr, "input.cc", None, Options)); +} + TEST(BracesAroundStatementsCheck, For) { EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" " for (;;) {\n"