Index: clang-tidy/modernize/CMakeLists.txt =================================================================== --- clang-tidy/modernize/CMakeLists.txt +++ clang-tidy/modernize/CMakeLists.txt @@ -14,6 +14,7 @@ ReplaceAutoPtrCheck.cpp ShrinkToFitCheck.cpp UseAutoCheck.cpp + UseBoolLiteralsCheck.cpp UseDefaultCheck.cpp UseNullptrCheck.cpp UseOverrideCheck.cpp Index: clang-tidy/modernize/ModernizeTidyModule.cpp =================================================================== --- clang-tidy/modernize/ModernizeTidyModule.cpp +++ clang-tidy/modernize/ModernizeTidyModule.cpp @@ -20,6 +20,7 @@ #include "ReplaceAutoPtrCheck.h" #include "ShrinkToFitCheck.h" #include "UseAutoCheck.h" +#include "UseBoolLiteralsCheck.h" #include "UseDefaultCheck.h" #include "UseNullptrCheck.h" #include "UseOverrideCheck.h" @@ -47,6 +48,8 @@ "modernize-replace-auto-ptr"); CheckFactories.registerCheck("modernize-shrink-to-fit"); CheckFactories.registerCheck("modernize-use-auto"); + CheckFactories.registerCheck( + "modernize-use-bool-literals"); CheckFactories.registerCheck("modernize-use-default"); CheckFactories.registerCheck("modernize-use-nullptr"); CheckFactories.registerCheck("modernize-use-override"); Index: clang-tidy/modernize/UseBoolLiteralsCheck.h =================================================================== --- /dev/null +++ clang-tidy/modernize/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_MODERNIZE_USE_BOOL_LITERALS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_BOOL_LITERALS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace modernize { + +/// Finds integer literals which are cast to bool. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-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 modernize +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_BOOL_LITERALS_H Index: clang-tidy/modernize/UseBoolLiteralsCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/modernize/UseBoolLiteralsCheck.cpp @@ -0,0 +1,55 @@ +//===--- 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 modernize { + +void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + Finder->addMatcher( + implicitCastExpr( + has(integerLiteral().bind("literal")), + hasImplicitDestinationType(qualType(booleanType())), + unless(isInTemplateInstantiation()), + anyOf(hasParent(explicitCastExpr().bind("cast")), anything())), + this); +} + +void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Literal = Result.Nodes.getNodeAs("literal"); + const auto *Cast = Result.Nodes.getNodeAs("cast"); + bool LiteralBooleanValue = Literal->getValue().getBoolValue(); + + if (Literal->isInstantiationDependent()) + return; + + const Expr *Expression = Cast ? Cast : Literal; + + auto Diag = + diag(Expression->getExprLoc(), + "converting integer literal to bool, use bool literal instead"); + + if (!Expression->getLocStart().isMacroID()) + Diag << FixItHint::CreateReplacement( + Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false"); +} + +} // namespace modernize +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -191,6 +191,11 @@ Selectively replaces string literals containing escaped characters with raw string literals. +- New `modernize-use-bool-literals + `_ check + + Finds integer literals which are cast to bool. + - New `performance-faster-string-find `_ check Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -100,6 +100,7 @@ modernize-replace-auto-ptr modernize-shrink-to-fit modernize-use-auto + modernize-use-bool-literals modernize-use-default modernize-use-nullptr modernize-use-override Index: docs/clang-tidy/checks/modernize-use-bool-literals.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/modernize-use-bool-literals.rst @@ -0,0 +1,18 @@ +.. title:: clang-tidy - modernize-use-bool-literals + +modernize-use-bool-literals +=========================== + +Finds integer literals which are cast to bool. + +.. code-block:: c++ + + bool p = 1; + bool f = static_cast(1); + std::ios_base::sync_with_stdio(0); + + // transforms to + + bool p = true; + bool f = true; + std::ios_base::sync_with_stdio(false); Index: test/clang-tidy/modernize-use-bool-literals.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-use-bool-literals.cpp @@ -0,0 +1,122 @@ +// RUN: %check_clang_tidy %s modernize-use-bool-literals %t + +bool IntToTrue = 1; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals] +// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}} + +bool IntToFalse(0); +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} +// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}} + +bool LongLongToTrue{0x1LL}; +// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} +// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}} + +bool ExplicitCStyleIntToFalse = (bool)0; +// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} +// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}} + +bool ExplicitFunctionalIntToFalse = bool(0); +// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: {{.*}} +// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}} + +bool ExplicitStaticIntToFalse = static_cast(0); +// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} +// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}} + +#define TRUE_MACRO 1 +// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}} + +bool MacroIntToTrue = TRUE_MACRO; +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals] +// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}} + +#define FALSE_MACRO bool(0) +// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}} + + +bool TrueBool = true; // OK + +bool FalseBool = bool(FALSE_MACRO); +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: {{.*}} +// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}} + +void boolFunction(bool bar) { + +} + +char Character = 0; // OK + +unsigned long long LongInteger = 1; // OK + +#define MACRO_DEPENDENT_CAST(x) static_cast(x) +// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast(x){{$}} + +bool MacroDependentBool = MACRO_DEPENDENT_CAST(0); +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} +// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}} + +bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO); +// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: {{.*}} +// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}} + +class FooClass { + public: + FooClass() : JustBool(0) {} + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} + // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}} + FooClass(int) : JustBool{0} {} + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: {{.*}} + // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}} + private: + bool JustBool; + bool BoolWithBraces{0}; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: {{.*}} + // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}} + bool BoolFromInt = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: {{.*}} + // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}} + bool SimpleBool = true; // OK +}; + +template +void templateFunction(type) { + type TemplateType = 0; + // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}} + return; +} + +template +void valueDependentTemplateFunction() { + bool Boolean = c; + // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}} + return; +} + +template +void anotherTemplateFunction(type) { + bool JustBool = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} + // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}} + return; +} + +int main() { + boolFunction(1); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} + // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}} + + boolFunction(false); + + templateFunction(0); + + templateFunction(false); + + valueDependentTemplateFunction<1>(); + + anotherTemplateFunction(1); + + IntToTrue = 1; + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} + // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}} +}