Fixed treating macros and variable declarations in conditions.
- [clang-tidy] Skipping macros. Refactoring. Fixed treating variable
declarations inside conditions.
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,260 @@
+//===--- 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 {
+namespace {
+
+tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
+ const ASTContext *Context) {
+ Token Tok;
+ SourceLocation Beginning =
+ Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
+ const bool Invalid =
+ Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
+ assert(!Invalid && "Expected a valid token.");
+
+ if (Invalid) {
+ return tok::NUM_TOKENS;
+ }
+ return Tok.getKind();
+}
+
+SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
+ const SourceManager &SM,
+ const ASTContext *Context) {
+ assert(Loc.isValid());
+ for (;;) {
+ while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
+ Loc = Loc.getLocWithOffset(1);
+ }
+
+ tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+ if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment) {
+ return Loc;
+ }
+ // Fast-forward current token
+ Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+ }
+}
+
+bool isBlockComment(SourceRange R, const SourceManager &SM,
+ const ASTContext *Context) {
+ assert(R.isValid());
+ StringRef Comment = Lexer::getSourceText(CharSourceRange::getTokenRange(R),
+ SM, Context->getLangOpts());
+ return Comment.startswith("/*");
+}
+
+bool hasNewLine(SourceRange R, const SourceManager &SM,
+ const ASTContext *Context) {
+ assert(R.isValid());
+ StringRef Code = Lexer::getSourceText(CharSourceRange::getTokenRange(R), SM,
+ Context->getLangOpts());
+ return Code.find('\n') != StringRef::npos;
+}
+
+SourceLocation findEndLocation(SourceLocation LastTokenLoc,
+ const SourceManager &SM,
+ const ASTContext *Context) {
+ SourceLocation Loc = LastTokenLoc;
+ // Loc points to the beginning of the last (non-comment non-ws) token
+ // before end or ';'.
+ assert(Loc.isValid());
+ bool SkipEndWhitespaceAndComments = true;
+ tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+ if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
+ TokKind == tok::r_brace) {
+ // If we are at ";" or "}", we found the last token. We could use as well
+ // `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
+ SkipEndWhitespaceAndComments = false;
+ }
+
+ Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+ // Loc points past the last token before end or after ';'
+
+ if (SkipEndWhitespaceAndComments) {
+ Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
+ tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+ if (TokKind == tok::semi) {
+ Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+ }
+ }
+
+ for (;;) {
+ assert(Loc.isValid());
+ while (isHorizontalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
+ Loc = Loc.getLocWithOffset(1);
+ }
+ if (isVerticalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
+ // EOL, brace before
+ break;
+ }
+ tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+ if (TokKind != tok::comment) {
+ // Non-comment token, brace before
+ break;
+ }
+
+ assert(TokKind == tok::comment);
+ SourceLocation TokEndLoc =
+ Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+ SourceRange TokRange(Loc, TokEndLoc);
+ if (isBlockComment(TokRange, SM, Context)) {
+ if (hasNewLine(TokRange, SM, Context)) {
+ // Multi-line block comment, brace before
+ break;
+ }
+ // else: One-line block comment, brace after new line
+ }
+ // else: Trailing comment, brace after new line
+
+ // Fast-forward current token
+ Loc = TokEndLoc;
+ }
+ return Loc;
+}
+
+} // namespace
+
+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 MatchFinder::MatchResult &Result) {
+ const SourceManager &SM = *Result.SourceManager;
+ const ASTContext *Context = Result.Context;
+
+ // Get location of closing parenthesis or 'do' to put opening brace
+ if (auto S = Result.Nodes.getNodeAs<ForStmt>("for")) {
+ checkStmt(Result, S->getBody(), S->getRParenLoc());
+ } else if (auto S = Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
+ checkStmt(Result, S->getBody(), S->getRParenLoc());
+ } else if (auto S = Result.Nodes.getNodeAs<DoStmt>("do")) {
+ checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
+ } else if (auto S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
+ // FIXME: WhileStmt should store RParenLoc
+ SourceLocation StartLoc = findRParenLoc(S, SM, Context);
+ if (StartLoc.isInvalid()) {
+ return;
+ }
+ checkStmt(Result, S->getBody(), StartLoc);
+ } else if (auto S = Result.Nodes.getNodeAs<IfStmt>("if")) {
+ // FIXME: IfStmt should store RParenLoc
+ SourceLocation StartLoc = findRParenLoc(S, SM, Context);
+ if (StartLoc.isInvalid()) {
+ return;
+ }
+ checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc());
+ const Stmt *Else = S->getElse();
+ if (Else && !isa<IfStmt>(Else)) {
+ // Omit 'else if' statements here, they will be handled directly
+ checkStmt(Result, Else, S->getElseLoc());
+ }
+ } else {
+ llvm_unreachable("Invalid match");
+ }
+}
+
+/// Find location of right parenthesis closing condition
+template <typename IfOrWhileStmt>
+SourceLocation
+BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
+ const SourceManager &SM,
+ const ASTContext *Context) {
+ // Skip macros
+ if (S->getLocStart().isMacroID()) {
+ return SourceLocation();
+ }
+
+ static const char *const ErrorMessage =
+ "cannot find location of closing parenthesis ')'";
+ SourceLocation CondEndLoc = S->getCond()->getLocEnd();
+ if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt()) {
+ CondEndLoc = CondVar->getLocEnd();
+ }
+ assert(CondEndLoc.isValid());
+ SourceLocation PastCondEndLoc =
+ Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
+ if (PastCondEndLoc.isInvalid()) {
+ diag(CondEndLoc, ErrorMessage);
+ return SourceLocation();
+ }
+ SourceLocation RParenLoc =
+ forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
+ if (RParenLoc.isInvalid()) {
+ diag(PastCondEndLoc, ErrorMessage);
+ return SourceLocation();
+ }
+ tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
+ if (TokKind != tok::r_paren) {
+ diag(RParenLoc, ErrorMessage);
+ return SourceLocation();
+ }
+ return RParenLoc;
+}
+
+void
+BracesAroundStatementsCheck::checkStmt(const MatchFinder::MatchResult &Result,
+ const Stmt *S, SourceLocation InitialLoc,
+ SourceLocation EndLocHint) {
+ // 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
+ // the location we're inserting the closing brace at, or there's a non-comment
+ // token, the check inserts "\n}" right before that token.
+ // 3) Otherwise the check finds the end of line (possibly after some block or
+ // line comments) and inserts "\n}" right before that EOL.
+ if (!S || isa<CompoundStmt>(S)) {
+ // Already inside braces
+ return;
+ }
+ // Skip macros
+ if (S->getLocStart().isMacroID()) {
+ return;
+ }
+
+ const SourceManager &SM = *Result.SourceManager;
+ const ASTContext *Context = Result.Context;
+
+ // InitialLoc points at the last token before opening brace to be inserted
+ assert(InitialLoc.isValid());
+ SourceLocation StartLoc =
+ Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts());
+ // StartLoc points at the location of the opening brace to be inserted
+ SourceLocation EndLoc;
+ std::string ClosingInsertion = "\n}";
+ if (EndLocHint.isValid()) {
+ EndLoc = EndLocHint;
+ ClosingInsertion = "} ";
+ } else {
+ EndLoc = findEndLocation(S->getLocEnd(), SM, Context);
+ }
+
+ assert(StartLoc.isValid());
+ auto Diag = diag(StartLoc, "statement should be inside braces");
+ // Add braces
+ Diag << FixItHint::CreateInsertion(StartLoc, " {")
+ << FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
+}
+
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/BracesAroundStatementsCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/BracesAroundStatementsCheck.h
@@ -0,0 +1,37 @@
+//===--- 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,
+ SourceLocation EndLocHint = SourceLocation());
+ template <typename IfOrWhileStmt>
+ SourceLocation findRParenLoc(const IfOrWhileStmt *S, const SourceManager &SM,
+ const ASTContext *Context);
+};
+
+} // 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");
@@ -42,7 +45,7 @@
// Register the MiscTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<MiscModule>
-X("misc-module", "Adds miscellaneous lint checks.");
+ X("misc-module", "Adds miscellaneous lint checks.");
// This anchor is used to force the linker to link in the generated object file
// and thus register the MiscModule.
Index: test/clang-tidy/misc-braces-around-statements.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-braces-around-statements.cpp
@@ -0,0 +1,178 @@
+// 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;
+}
+
+#define EMPTY_MACRO
+#define EMPTY_MACRO_FUN()
+
+void test() {
+ // CHECK-NOT: warning
+ // if
+ if (cond("if1") /*comment*/)
+ // some comment
+ do_something("if1");
+ // CHECK-MESSAGES: :[[@LINE-3]]:31: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if1") /*comment*/) {
+ // CHECK-FIXES: }
+ if (cond("if2")) {
+ do_something("if2");
+ }
+ 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-else1");
+ // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("if-else1")) {
+ // CHECK-FIXES: } else {
+ else
+ do_something("if-else1 else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: }
+ if (cond("if-else2")) {
+ do_something("if-else2");
+ } else {
+ do_something("if-else2 else");
+ }
+
+ // CHECK-NOT: warning
+ // 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: } else if (cond("else if1")) {
+ else if (cond("else if1"))
+ do_something("else if");
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: statement should be inside braces
+ else
+ do_something("else");
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+ // CHECK-FIXES: }
+ if (cond("if-else if-else2")) {
+ do_something("if");
+ } else if (cond("else if2")) {
+ do_something("else if");
+ } else {
+ do_something("else");
+ }
+
+ // CHECK-NOT: warning
+ for (;;)
+ do_something("for");
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;) {
+ // CHECK-FIXES: }
+ for (;;) {
+ do_something("for");
+ }
+ for (;;)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+ // CHECK-FIXES: for (;;) {
+ // CHECK-FIXES: }
+
+ // CHECK-NOT: warning
+ 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: }
+ 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: }
+
+ // CHECK-NOT: warning
+ while (cond("while1"))
+ do_something("while");
+ // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: statement should be inside braces
+ // CHECK-FIXES: while (cond("while1")) {
+ // CHECK-FIXES: }
+ 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: }
+
+ // CHECK-NOT: warning
+ do
+ do_something("do1");
+ while (cond("do1"));
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do {
+ // CHECK-FIXES: } while (cond("do1"));
+ do {
+ do_something("do2");
+ } while (cond("do2"));
+
+ do
+ ;
+ while (false);
+ // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+ // CHECK-FIXES: do {
+ // CHECK-FIXES: } while (false);
+
+ // CHECK-NOT: warning
+ if (cond("ifif1"))
+ // comment
+ if (cond("ifif2"))
+ // comment
+ /*comment*/ ; // comment
+ // CHECK-MESSAGES: :[[@LINE-5]]:21: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-4]]:23: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif1")) {
+ // CHECK-FIXES: if (cond("ifif2")) {
+ // CHECK-FIXES: }
+ // CHECK-FIXES-NEXT: }
+
+ if (cond("ifif3"))
+ // comment
+ if (cond("ifif4")) {
+ // comment
+ /*comment*/; // comment
+ }
+ // CHECK-MESSAGES: :[[@LINE-6]]:21: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif3")) {
+ // CHECK-FIXES: }
+
+ if (cond("ifif5"))
+ ; /* multi-line
+ comment */
+ // CHECK-MESSAGES: :[[@LINE-3]]:21: warning: statement should be inside braces
+ // CHECK-FIXES: if (cond("ifif5")) {
+ // CHECK-FIXES: }/* multi-line
+
+ // CHECK-NOT: warning
+ if (1) while (2) if (3) for (;;) do ; while(false) /**/;/**/
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-4]]:35: warning: statement should be inside braces
+ // CHECK-MESSAGES: :[[@LINE-5]]:38: warning: statement should be inside braces
+ // CHECK-FIXES: if (1) { while (2) { if (3) { for (;;) { do { ; } while(false) /**/;/**/
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+ // CHECK-FIXES-NEXT: }
+
+ // CHECK-NOT: warning
+
+ // CHECK-MESSAGES: {{clang-tidy applied [0-9]+ of [0-9]+ suggested 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,346 @@
"void f(int xxx, int yyy); void g() { f(/*xxy=*/0, 0); }");
}
+TEST(BracesAroundStatementsCheck, IfWithComments) {
+ // if only
+ EXPECT_EQ("int main() {\n"
+ " if (false /*dummy token*/) {\n"
+ " // comment\n"
+ " return -1; /**/\n"
+ "}\n"
+ " if (false) {\n"
+ " return -1; // comment\n"
+ "}\n"
+ " if (false) {\n"
+ " return -1; \n"
+ "}/* multi-line \n comment */\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " if (false /*dummy token*/)\n"
+ " // comment\n"
+ " return -1; /**/\n"
+ " if (false)\n"
+ " return -1; // comment\n"
+ " if (false)\n"
+ " return -1; /* multi-line \n comment */\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " if (false /*dummy token*/) {\n"
+ " // comment\n"
+ " return -1 /**/ ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " if (false /*dummy token*/)\n"
+ " // comment\n"
+ " return -1 /**/ ;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, If) {
+ // if only
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ " }\n"
+ "}");
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " if (auto Cond = false) {\n"
+ " return -1;\n"
+ " }\n"
+ "}");
+ // if else
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ " } else {\n"
+ " return -2;\n"
+ " }\n"
+ "}");
+ // if only
+ EXPECT_EQ("int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " if (auto Cond = false /**/ ) {\n"
+ " return -1;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " if (auto Cond = false /**/ )\n"
+ " return -1;\n"
+ "}"));
+//EXPECT_EQ("#define EMPTY_MACRO\n"
+// "int main() {\n"
+// " if (auto Cond = false EMPTY_MACRO /**/ ) { EMPTY_MACRO\n"
+// " return -1;\n"
+// "}\n"
+// "}",
+// runCheckOnCode<BracesAroundStatementsCheck>(
+// "#define EMPTY_MACRO\n"
+// "int main() {\n"
+// " if (auto Cond = false EMPTY_MACRO /**/ ) EMPTY_MACRO\n"
+// " return -1;\n"
+// "}"));
+ EXPECT_EQ("int main() {\n"
+ " if (true) { return -1/**/ ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " if (true) return -1/**/ ;\n"
+ "}"));
+ // if else
+ EXPECT_EQ("int main() {\n"
+ " if (false) {\n"
+ " return -1;\n"
+ " } else {\n"
+ " return -2;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else\n"
+ " return -2;\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 -3;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else if (1 == 2)\n"
+ " return -2;\n"
+ " else\n"
+ " return -3;\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 -3;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (false)\n"
+ " return -1;\n"
+ " else if (1 == 2) {\n"
+ " return -2;\n"
+ " } else\n"
+ " return -3;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, For) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " for (;;) {\n"
+ " ;\n"
+ " }\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " for (;;) {\n"
+ " ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " for (;;)\n"
+ " ;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " for (;;) {\n"
+ " /**/ ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " for (;;)\n"
+ " /**/ ;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " for (;;) {\n"
+ " return -1 /**/ ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " for (;;)\n"
+ " return -1 /**/ ;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, ForRange) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr) {\n"
+ " ;\n"
+ " }\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr) {\n"
+ " ;\n"
+ "}\n"
+ " for (int i : arr) {\n"
+ " return -1 ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " int arr[4];\n"
+ " for (int i : arr)\n"
+ " ;\n"
+ " for (int i : arr)\n"
+ " return -1 ;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, DoWhile) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " do {\n"
+ " ;\n"
+ " } while (false);\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " do {\n"
+ " ;\n"
+ " } while (false);\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " do\n"
+ " ;\n"
+ " while (false);\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, While) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+ " while (false) {\n"
+ " ;\n"
+ " }\n"
+ "}");
+ EXPECT_EQ("int main() {\n"
+ " while (false) {\n"
+ " ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " ;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (auto Cond = false) {\n"
+ " ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " while (auto Cond = false)\n"
+ " ;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (false /*dummy token*/) {\n"
+ " ;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " while (false /*dummy token*/)\n"
+ " ;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (false) {\n"
+ " break;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " break;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (false) {\n"
+ " break /**/;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " break /**/;\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " while (false) {\n"
+ " /**/;\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " while (false)\n"
+ " /**/;\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, Nested) {
+ EXPECT_EQ("int main() {\n"
+ " do { if (true) {}} while (false);\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " do if (true) {}while (false);\n"
+ "}"));
+ EXPECT_EQ("int main() {\n"
+ " do { if (true) {}} while (false);\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>(
+ "int main() {\n"
+ " do if (true) {}while (false);\n"
+ "}"));
+ EXPECT_EQ(
+ "int main() {\n"
+ " if (true) {\n"
+ " // comment\n"
+ " if (false) {\n"
+ " // comment\n"
+ " /**/ ; // comment\n"
+ " }\n"
+ "}\n"
+ "}",
+ runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+ " if (true)\n"
+ " // comment\n"
+ " if (false) {\n"
+ " // comment\n"
+ " /**/ ; // comment\n"
+ " }\n"
+ "}"));
+}
+
+TEST(BracesAroundStatementsCheck, Macros) {
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck,
+ "#define IF(COND) if (COND) return -1;\n"
+ "int main() {\n"
+ " IF(false)\n"
+ "}");
+ EXPECT_NO_CHANGES(BracesAroundStatementsCheck,
+ "#define FOR(COND) for (COND) return -1;\n"
+ "int main() {\n"
+ " FOR(;;)\n"
+ "}");
+}
+
} // namespace test
} // namespace tidy
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits