Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -32,6 +32,7 @@ UnusedParametersCheck.cpp UnusedRAIICheck.cpp UniqueptrResetReleaseCheck.cpp + UseBoolLiteralsCheck.cpp VirtualNearMissCheck.cpp LINK_LIBS Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -40,6 +40,7 @@ #include "UnusedAliasDeclsCheck.h" #include "UnusedParametersCheck.h" #include "UnusedRAIICheck.h" +#include "UseBoolLiteralsCheck.h" #include "VirtualNearMissCheck.h" namespace clang { @@ -106,6 +107,8 @@ CheckFactories.registerCheck( "misc-unused-parameters"); CheckFactories.registerCheck("misc-unused-raii"); + CheckFactories.registerCheck( + "misc-use-bool-literals"); CheckFactories.registerCheck( "misc-virtual-near-miss"); } Index: clang-tidy/misc/UseBoolLiteralsCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/UseBoolLiteralsCheck.h @@ -0,0 +1,35 @@ +//===--- UseBoolLiteralsCheck.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_USE_BOOL_LITERALS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USE_BOOL_LITERALS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace misc { + +/// Finds integer literals, which are implicitly casted to bool. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/misc-use-bool-literals.html +class UseBoolLiteralsCheck : public ClangTidyCheck { +public: + UseBoolLiteralsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace misc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USE_BOOL_LITERALS_H Index: clang-tidy/misc/UseBoolLiteralsCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/UseBoolLiteralsCheck.cpp @@ -0,0 +1,52 @@ +//===--- UseBoolLiteralsCheck.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 "UseBoolLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace misc { + +void UseBoolLiteralsCheck::registerMatchers(MatchFinder* Finder) { + Finder->addMatcher( + implicitCastExpr(has(integerLiteral().bind("literal"))), + this); +} + +/// Checks, if integer \p Literal is preprocessor dependent +static bool isPreprocessorIndependent(const IntegerLiteral* Literal, const MatchFinder::MatchResult& Result) { + const LangOptions& Opts = Result.Context->getLangOpts(); + std::string LiteralSource = Lexer::getSourceText( + CharSourceRange::getTokenRange(Literal->getSourceRange()), + *Result.SourceManager, Opts); + + return LiteralSource.size() >= 1 && isDigit(LiteralSource.front()); +} + +void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult& Result) { + const auto* Literal = Result.Nodes.getNodeAs("literal"); + + if (isPreprocessorIndependent(Literal, Result)) { + bool LiteralBooleanValue = Literal->getValue().getBoolValue(); + diag(Literal->getLocation(), "implicitly converting integer literal to bool, use bool literal instead") + << FixItHint::CreateReplacement(Literal->getSourceRange(), LiteralBooleanValue ? "true" : "false"); + } + else { + diag(Literal->getLocation(), "implicitly converting integer literal to bool"); + } +} + +} // namespace misc +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -108,6 +108,11 @@ Finds most instances of stray semicolons that unexpectedly alter the meaning of the code. +- New `misc-use-bool-literals + `_ check + + Finds integer literals, which are implicitly casted to bool. + - New `modernize-deprecated-headers `_ check Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -75,6 +75,7 @@ misc-unused-alias-decls misc-unused-parameters misc-unused-raii + misc-use-bool-literals misc-virtual-near-miss modernize-deprecated-headers modernize-loop-convert Index: docs/clang-tidy/checks/misc-use-bool-literals.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/misc-use-bool-literals.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - misc-use-bool-literals + +misc-use-bool-literals +====================== + +Finds places, where integer literal is implict casted to boolean. + +.. code-block:: c++ + + bool p = 1; + std::ios_base::sync_with_stdio(0); + + // transforms to + + bool p = true; + std::ios_base::sync_with_stdio(false); Index: test/clang-tidy/misc-use-bool-literals.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-use-bool-literals.cpp @@ -0,0 +1,38 @@ +// RUN: %check_clang_tidy %s misc-use-bool-literals %t + +bool bar1 = 1; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: implicitly converting integer literal to bool, use bool literal instead [misc-use-bool-literals] +// CHECK-FIXES: {{^}}bool bar1 = true;{{$}} + +bool bar2 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} +// CHECK-FIXES: {{^}}bool bar2 = false;{{$}} + +bool bar3 = 0x123ABCLL; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} +// CHECK-FIXES: {{^}}bool bar3 = true;{{$}} + +#define TRUE_FALSE 1 + +bool bar4 = TRUE_FALSE; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: implicitly converting integer literal to bool [misc-use-bool-literals] + +#define TRUE_FALSE2 bool(1) // OK + +bool bar6 = true; // OK + +void foo4(bool bar) { + +} + +int main() { + foo4(1); + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}} + // CHECK-FIXES: {{^}} foo4(true);{{$}} + + foo4(false); // OK + + bar1 = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: {{.*}} + // CHECK-FIXES: {{^}} bar1 = false;{{$}} +}