From 03a22479124b82461b476d2fd88a3fdc420224e9 Mon Sep 17 00:00:00 2001 From: Jakub Staron Date: Wed, 11 May 2016 11:33:16 +0000 Subject: [PATCH] [clang-tidy] Adds modernize-use-bool-literals check. Review link: http://reviews.llvm.org/D18745 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@269171 91177308-0d34-0410-b5e6-96231b3b80d8 --- clang-tidy/modernize/CMakeLists.txt | 1 + clang-tidy/modernize/ModernizeTidyModule.cpp | 3 + clang-tidy/modernize/UseBoolLiteralsCheck.cpp | 55 ++++++++ clang-tidy/modernize/UseBoolLiteralsCheck.h | 35 +++++ docs/ReleaseNotes.rst | 5 + docs/clang-tidy/checks/list.rst | 1 + .../checks/modernize-use-bool-literals.rst | 18 +++ .../modernize-use-bool-literals.cpp | 122 ++++++++++++++++++ 8 files changed, 240 insertions(+) create mode 100644 clang-tidy/modernize/UseBoolLiteralsCheck.cpp create mode 100644 clang-tidy/modernize/UseBoolLiteralsCheck.h create mode 100644 docs/clang-tidy/checks/modernize-use-bool-literals.rst create mode 100644 test/clang-tidy/modernize-use-bool-literals.cpp diff --git a/clang-tidy/modernize/CMakeLists.txt b/clang-tidy/modernize/CMakeLists.txt index 3c8add4..3a9ad54 100644 --- a/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tidy/modernize/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_library(clangTidyModernizeModule ReplaceAutoPtrCheck.cpp ShrinkToFitCheck.cpp UseAutoCheck.cpp + UseBoolLiteralsCheck.cpp UseDefaultCheck.cpp UseNullptrCheck.cpp UseOverrideCheck.cpp diff --git a/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tidy/modernize/ModernizeTidyModule.cpp index 93866ba..529e905 100644 --- a/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/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 @@ public: "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"); diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tidy/modernize/UseBoolLiteralsCheck.cpp new file mode 100644 index 0000000..f772801 --- /dev/null +++ b/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 diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.h b/clang-tidy/modernize/UseBoolLiteralsCheck.h new file mode 100644 index 0000000..46d7879 --- /dev/null +++ b/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 diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 2220e01..94ba16d 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -196,6 +196,11 @@ identified. The improvements since the 3.8 release include: 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 diff --git a/docs/clang-tidy/checks/list.rst b/docs/clang-tidy/checks/list.rst index 8c9ab42..c864436 100644 --- a/docs/clang-tidy/checks/list.rst +++ b/docs/clang-tidy/checks/list.rst @@ -101,6 +101,7 @@ Clang-Tidy Checks modernize-replace-auto-ptr modernize-shrink-to-fit modernize-use-auto + modernize-use-bool-literals modernize-use-default modernize-use-nullptr modernize-use-override diff --git a/docs/clang-tidy/checks/modernize-use-bool-literals.rst b/docs/clang-tidy/checks/modernize-use-bool-literals.rst new file mode 100644 index 0000000..a8d73c3 --- /dev/null +++ b/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); diff --git a/test/clang-tidy/modernize-use-bool-literals.cpp b/test/clang-tidy/modernize-use-bool-literals.cpp new file mode 100644 index 0000000..dbbb162 --- /dev/null +++ b/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;{{$}} +}