- Fix: BracesAroundStatementsCheck.
http://reviews.llvm.org/D5395
Files:
clang-tidy/misc/BracesAroundStatementsCheck.cpp
clang-tidy/misc/BracesAroundStatementsCheck.h
clang-tidy/misc/CMakeLists.txt
clang-tidy/misc/MiscTidyModule.cpp
test/clang-tidy/misc-braces-around-statements.cpp
unittests/clang-tidy/MiscModuleTest.cpp
Index: clang-tidy/misc/BracesAroundStatementsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/BracesAroundStatementsCheck.cpp
@@ -0,0 +1,87 @@
+//===--- BracesAroundStatementsCheck.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 "BracesAroundStatementsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+
+namespace tidy {
+
+void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(ifStmt().bind("if"), this);
+ Finder->addMatcher(whileStmt().bind("while"), this);
+ Finder->addMatcher(doStmt().bind("do"), this);
+ Finder->addMatcher(forStmt().bind("for"), this);
+ Finder->addMatcher(forRangeStmt().bind("for-range"), this);
+}
+
+void BracesAroundStatementsCheck::check(
+ const ast_matchers::MatchFinder::MatchResult &Result) {
+ // to put opening brace, get location after closing parenthesis or 'do'
+ if (const ForStmt *FS = Result.Nodes.getNodeAs<ForStmt>("for")) {
+ checkStmt(Result, FS->getBody(), FS->getRParenLoc().getLocWithOffset(1));
+ } else if (const CXXForRangeStmt *FRS =
+ Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
+ checkStmt(Result, FRS->getBody(), FRS->getRParenLoc().getLocWithOffset(1));
+ } else if (const DoStmt *DS = Result.Nodes.getNodeAs<DoStmt>("do")) {
+ SourceLocation AfterDo =
+ Lexer::getLocForEndOfToken(DS->getDoLoc(), 0, *Result.SourceManager,
+ Result.Context->getLangOpts());
+ checkStmt(Result, DS->getBody(), AfterDo);
+ } else if (const WhileStmt *WS = Result.Nodes.getNodeAs<WhileStmt>("while")) {
+ SourceLocation AfterCond =
+ Lexer::getLocForEndOfToken(
+ WS->getCond()->getLocEnd(), 0, *Result.SourceManager,
+ Result.Context->getLangOpts()).getLocWithOffset(1);
+ checkStmt(Result, WS->getBody(), AfterCond);
+ } else if (const IfStmt *IS = Result.Nodes.getNodeAs<IfStmt>("if")) {
+ SourceLocation AfterCond =
+ Lexer::getLocForEndOfToken(
+ IS->getCond()->getLocEnd(), 0, *Result.SourceManager,
+ Result.Context->getLangOpts()).getLocWithOffset(1);
+ checkStmt(Result, IS->getThen(), AfterCond);
+ const Stmt* Else = IS->getElse();
+ if (Else && !IfStmt::classof(Else)) {
+ // omit 'else if' statements here, they will be handled directly
+ SourceLocation AfterElse =
+ Lexer::getLocForEndOfToken(IS->getElseLoc(), 0, *Result.SourceManager,
+ Result.Context->getLangOpts());
+ checkStmt(Result, Else, AfterElse);
+ }
+ }
+}
+
+void BracesAroundStatementsCheck::checkStmt(
+ const ast_matchers::MatchFinder::MatchResult &Result, const Stmt *S,
+ SourceLocation StartLoc) {
+ if (!S || CompoundStmt::classof(S)) {
+ // already inside braces
+ return;
+ }
+ SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+ S->getLocEnd(), 0, *Result.SourceManager, Result.Context->getLangOpts());
+ // EndLoc points past ";" only if S was a no-op ";" operation
+ if (S->getLocStart() != S->getLocEnd() ||
+ EndLoc != S->getLocEnd().getLocWithOffset(1)) {
+ // EndLoc points at ";"
+ EndLoc = EndLoc.getLocWithOffset(1);
+ }
+ auto Diag = diag(StartLoc, "statement should be inside braces");
+ // add braces
+ Diag << FixItHint::CreateInsertion(StartLoc, "{")
+ << FixItHint::CreateInsertion(EndLoc, "}");
+}
+
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/BracesAroundStatementsCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/BracesAroundStatementsCheck.h
@@ -0,0 +1,33 @@
+//===--- BracesAroundStatementsCheck.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_MISC_BRACES_AROUND_STATEMENTS_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+class BracesAroundStatementsCheck : public ClangTidyCheck {
+public:
+ BracesAroundStatementsCheck(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 checkStmt(const ast_matchers::MatchFinder::MatchResult &Result,
+ const Stmt *S, SourceLocation StartLoc);
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -3,6 +3,7 @@
add_clang_library(clangTidyMiscModule
ArgumentCommentCheck.cpp
BoolPointerImplicitConversion.cpp
+ BracesAroundStatementsCheck.cpp
FunctionSize.cpp
MiscTidyModule.cpp
RedundantSmartptrGet.cpp
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -12,6 +12,7 @@
#include "../ClangTidyModuleRegistry.h"
#include "ArgumentCommentCheck.h"
#include "BoolPointerImplicitConversion.h"
+#include "BracesAroundStatementsCheck.h"
#include "FunctionSize.h"
#include "RedundantSmartptrGet.h"
#include "SwappedArgumentsCheck.h"
@@ -28,6 +29,8 @@
CheckFactories.registerCheck<ArgumentCommentCheck>("misc-argument-comment");
CheckFactories.registerCheck<BoolPointerImplicitConversion>(
"misc-bool-pointer-implicit-conversion");
+ CheckFactories.registerCheck<BracesAroundStatementsCheck>(
+ "misc-braces-around-statements");
CheckFactories.registerCheck<FunctionSizeCheck>("misc-function-size");
CheckFactories.registerCheck<RedundantSmartptrGet>(
"misc-redundant-smartptr-get");
Index: test/clang-tidy/misc-braces-around-statements.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-braces-around-statements.cpp
@@ -0,0 +1,125 @@
+// RUN: $(dirname %s)/check_clang_tidy_fix.sh %s misc-braces-around-statements %t
+// REQUIRES: shell
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+ return false;
+}
+
+void test() {
+ // if
+ if (cond("if1"))
+ // some comment
+ do_something("if");
+ // CHECK-MESSAGES: :[[@LINE-3]]:19: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if1")){
+ // CHECK-FIXES: do_something("if");}
+ if (cond("if2")) {
+ do_something("if");
+ }
+ if (cond("if3"))
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if3")){
+ // CHECK-FIXES: ;}
+
+ // if-else
+ if (cond("if-else1"))
+ do_something("if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if-else1")){
+ // CHECK-FIXES: do_something("if");}
+ else
+ do_something("else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: else{
+ // CHECK-FIXES: do_something("else");}
+ if (cond("if-else2")) {
+ do_something("if");
+ } else {
+ do_something("else");
+ }
+
+ // if-else if-else
+ if (cond("if-else if-else1"))
+ do_something("if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if-else if-else1")){
+ else if (cond("else if1"))
+ do_something("else if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: statement should be inside braces
+ // CHECK-FIXES: else if (cond("else if1")){
+ else
+ do_something("else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: do_something("else");}
+ if (cond("if-else if-else2")) {
+ do_something("if");
+ } else if (cond("else if2")) {
+ do_something("else if");
+ } else {
+ do_something("else");
+ }
+
+ for (;;)
+ do_something("for");
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;){
+ // CHECK-FIXES: do_something("for");}
+ for (;;) {
+ do_something("for");
+ }
+ for (;;)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;){
+ // CHECK-FIXES: ;}
+
+ int arr[4] = {1, 2, 3, 4};
+ for (int a : arr)
+ do_something("for-range");
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+ // CHECK-FIXES: for (int a : arr){
+ // CHECK-FIXES: do_something("for-range");}
+ for (int a : arr) {
+ do_something("for-range");
+ }
+ for (int a : arr)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+ // CHECK-FIXES: for (int a : arr){
+ // CHECK-FIXES: ;}
+
+ while (cond("while1"))
+ do_something("while");
+ // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: statement should be inside braces
+ // CHECK-FIXES: while (cond("while1")){
+ // CHECK-FIXES: do_something("while");}
+ while (cond("while2")) {
+ do_something("while");
+ }
+ while (false)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: statement should be inside braces
+ // CHECK-FIXES: while (false){
+ // CHECK-FIXES: ;}
+
+ do
+ do_something("do");
+ while (cond("do1"));
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do{
+ // CHECK-FIXES: do_something("do");}
+ do {
+ do_something("do");
+ } while (cond("do2"));
+
+ do
+ ;
+ while (false);
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do{
+ // CHECK-FIXES: ;}
+}
+
Index: unittests/clang-tidy/MiscModuleTest.cpp
===================================================================
--- unittests/clang-tidy/MiscModuleTest.cpp
+++ unittests/clang-tidy/MiscModuleTest.cpp
@@ -1,5 +1,6 @@
#include "ClangTidyTest.h"
#include "misc/ArgumentCommentCheck.h"
+#include "misc/BracesAroundStatementsCheck.h"
#include "gtest/gtest.h"
namespace clang {
@@ -35,6 +36,189 @@
"void f(int xxx, int yyy); void g() { f(/*xxy=*/0, 0); }");
}
+TEST(BracesAroundStatementsCheck, IfWithComments) {
+ // if only
+ EXPECT_EQ("int main() {\n"
+ " if (false){\n"
+ " // comment\n"
+ " return -1;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " // comment\n"
+ " return -1;\n"
+ " return 0;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, If) {
+ // if only
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ " }\n"
+ " return 0;\n"
+ "}");
+ // if else
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ " } else {\n"
+ " return 0;\n"
+ " }\n"
+ "}");
+ // if only
+ EXPECT_EQ("int main() {\n"
+ " if (false){\n"
+ " return -1;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " return 0;\n"
+ "}"));
+ // if else
+ EXPECT_EQ("int main() {\n"
+ " if (false){\n"
+ " return -1;}\n"
+ " else{\n"
+ " return 0;}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else\n"
+ " return 0;\n"
+ "}"));
+ // if else if else
+ EXPECT_EQ("int main() {\n"
+ " if (false){\n"
+ " return -1;}\n"
+ " else if (1 == 2){\n"
+ " return -2;}\n"
+ " else{\n"
+ " return 0;}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else if (1 == 2)\n"
+ " return -2;\n"
+ " else\n"
+ " return 0;\n"
+ "}"));
+ // if else if {} else
+ EXPECT_EQ("int main() {\n"
+ " if (false){\n"
+ " return -1;}\n"
+ " else if (1 == 2) {\n"
+ " return -2;\n"
+ " } else{\n"
+ " return 0;}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else if (1 == 2) {\n"
+ " return -2;\n"
+ " } else\n"
+ " return 0;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, For) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " for (;;) {\n"
+ " ;\n"
+ " }\n"
+ " return 0;\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " for (;;){\n"
+ " ;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " for (;;)\n"
+ " ;\n"
+ " return 0;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, ForRange) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr) {\n"
+ " ;\n"
+ " }\n"
+ " return 0;\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr){\n"
+ " ;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr)\n"
+ " ;\n"
+ " return 0;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, DoWhile) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " do {\n"
+ " ;\n"
+ " } while (false);\n"
+ " return 0;\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " do{\n"
+ " ;}\n"
+ " while (false);\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " do\n"
+ " ;\n"
+ " while (false);\n"
+ " return 0;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, While) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " while (false) {\n"
+ " ;\n"
+ " }\n"
+ " return 0;\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " while (false){\n"
+ " ;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " ;\n"
+ " return 0;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (false){\n"
+ " break;}\n"
+ " return 0;\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " break;\n"
+ " return 0;\n"
+ "}"));
+}
+
} // namespace test
} // namespace tidy
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits