forked from OSchip/llvm-project
[clang-tidy] Add terminating continue check
Patch by: Daniel Kolozsvari! Differential Revision: https://reviews.llvm.org/D33844 llvm-svn: 332223
This commit is contained in:
parent
9d777984cf
commit
a49a91b555
|
@ -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"
|
||||
|
@ -115,6 +116,8 @@ public:
|
|||
"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>(
|
||||
|
|
|
@ -32,6 +32,7 @@ add_clang_library(clangTidyBugproneModule
|
|||
SuspiciousSemicolonCheck.cpp
|
||||
SuspiciousStringCompareCheck.cpp
|
||||
SwappedArgumentsCheck.cpp
|
||||
TerminatingContinueCheck.cpp
|
||||
ThrowKeywordMissingCheck.cpp
|
||||
UndefinedMemoryManipulationCheck.cpp
|
||||
UndelegatedConstructorCheck.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
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue