Skip to content

Commit

Permalink
[clang-tidy] Add terminating continue check
Browse files Browse the repository at this point in the history
Patch by: Daniel Kolozsvari!

Differential Revision: https://reviews.llvm.org/D33844

llvm-svn: 332223
  • Loading branch information
Xazax-hun committed May 14, 2018
1 parent 9d77798 commit a49a91b
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
Expand Up @@ -40,6 +40,7 @@
#include "SuspiciousSemicolonCheck.h"
#include "SuspiciousStringCompareCheck.h"
#include "SwappedArgumentsCheck.h"
#include "TerminatingContinueCheck.h"
#include "ThrowKeywordMissingCheck.h"
#include "UndefinedMemoryManipulationCheck.h"
#include "UndelegatedConstructorCheck.h"
Expand Down Expand Up @@ -115,6 +116,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-suspicious-string-compare");
CheckFactories.registerCheck<SwappedArgumentsCheck>(
"bugprone-swapped-arguments");
CheckFactories.registerCheck<TerminatingContinueCheck>(
"bugprone-terminating-continue");
CheckFactories.registerCheck<ThrowKeywordMissingCheck>(
"bugprone-throw-keyword-missing");
CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
Expand Up @@ -32,6 +32,7 @@ add_clang_library(clangTidyBugproneModule
SuspiciousSemicolonCheck.cpp
SuspiciousStringCompareCheck.cpp
SwappedArgumentsCheck.cpp
TerminatingContinueCheck.cpp
ThrowKeywordMissingCheck.cpp
UndefinedMemoryManipulationCheck.cpp
UndelegatedConstructorCheck.cpp
Expand Down
49 changes: 49 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp
@@ -0,0 +1,49 @@
//===--- TerminatingContinueCheck.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 "TerminatingContinueCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/FixIt.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace bugprone {

void TerminatingContinueCheck::registerMatchers(MatchFinder *Finder) {
const auto doWithFalse =
doStmt(hasCondition(ignoringImpCasts(
anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)),
cxxNullPtrLiteralExpr(), gnuNullExpr()))),
equalsBoundNode("closestLoop"));

Finder->addMatcher(
continueStmt(hasAncestor(stmt(anyOf(forStmt(), whileStmt(),
cxxForRangeStmt(), doStmt()))
.bind("closestLoop")),
hasAncestor(doWithFalse))
.bind("continue"),
this);
}

void TerminatingContinueCheck::check(const MatchFinder::MatchResult &Result) {
const auto *ContStmt = Result.Nodes.getNodeAs<ContinueStmt>("continue");

auto Diag =
diag(ContStmt->getLocStart(),
"'continue' in loop with false condition is equivalent to 'break'")
<< tooling::fixit::createReplacement(*ContStmt, "break");
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
36 changes: 36 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.h
@@ -0,0 +1,36 @@
//===--- TerminatingContinueCheck.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_BUGPRONE_TERMINATINGCONTINUECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TERMINATINGCONTINUECHECK_H

#include "../ClangTidy.h"

namespace clang {
namespace tidy {
namespace bugprone {

/// Checks if a 'continue' statement terminates the loop (i.e. the loop has
/// a condition which always evaluates to false).
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-terminating-continue.html
class TerminatingContinueCheck : public ClangTidyCheck {
public:
TerminatingContinueCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

} // namespace bugprone
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TERMINATINGCONTINUECHECK_H
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Expand Up @@ -146,6 +146,11 @@ Improvements to clang-tidy
Warns or suggests alternatives if SIMD intrinsics are used which can be replaced by
``std::experimental::simd`` operations.

- New :doc:`bugprone-terminating-continue
<clang-tidy/checks/bugprone-terminating-continue>` check

Checks if a ``continue`` statement terminates the loop.

- New :doc:`zircon-temporary-objects
<clang-tidy/checks/zircon-temporary-objects>` check.

Expand Down
@@ -0,0 +1,17 @@
.. title:: clang-tidy - bugprone-terminating-continue

bugprone-terminating-continue
=============================

Detects `do while` loops with a condition always evaluating to false that
have a `continue` statement, as this `continue` terminates the loop
effectively.

.. code-block:: c++

void f() {
do {
// some code
continue; // terminating continue
// some other code
} while(false);
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Expand Up @@ -49,6 +49,7 @@ Clang-Tidy Checks
bugprone-suspicious-semicolon
bugprone-suspicious-string-compare
bugprone-swapped-arguments
bugprone-terminating-continue
bugprone-throw-keyword-missing
bugprone-undefined-memory-manipulation
bugprone-undelegated-constructor
Expand Down
@@ -0,0 +1,65 @@
// RUN: %check_clang_tidy %s bugprone-terminating-continue %t

void f() {
do {
continue;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
// CHECK-FIXES: break;
} while(false);

do {
continue;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
// CHECK-FIXES: break;
} while(0);

do {
continue;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
// CHECK-FIXES: break;
} while(nullptr);

do {
continue;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
// CHECK-FIXES: break;
} while(__null);


do {
int x = 1;
if (x > 0) continue;
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
// CHECK-FIXES: if (x > 0) break;
} while (false);
}

void g() {
do {
do {
continue;
int x = 1;
} while (1 == 1);
} while (false);

do {
for (int i = 0; i < 1; ++i) {
continue;
int x = 1;
}
} while (false);

do {
while (true) {
continue;
int x = 1;
}
} while (false);

int v[] = {1,2,3,34};
do {
for (int n : v) {
if (n>2) continue;
}
} while (false);
}

0 comments on commit a49a91b

Please sign in to comment.