forked from OSchip/llvm-project
[clang-tidy] 'implicit cast' -> 'implicit conversion'
Summary: This patch renames checks, check options and changes messages to use correct term "implicit conversion" instead of "implicit cast" (which has been in use in Clang AST since ~10 years, but it's still technically incorrect w.r.t. C++ standard). * performance-implicit-cast-in-loop -> performance-implicit-conversion-in-loop * readability-implicit-bool-cast -> readability-implicit-bool-conversion - readability-implicit-bool-cast.AllowConditionalIntegerCasts -> readability-implicit-bool-conversion.AllowIntegerConditions - readability-implicit-bool-cast.AllowConditionalPointerCasts -> readability-implicit-bool-conversion.AllowPointerConditions Reviewers: hokein, jdennett Reviewed By: hokein Subscribers: mgorny, JDevlieghere, xazax.hun, cfe-commits Differential Revision: https://reviews.llvm.org/D36456 llvm-svn: 310366
This commit is contained in:
parent
64d31edef3
commit
f1a6552a95
|
@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
|
||||||
add_clang_library(clangTidyPerformanceModule
|
add_clang_library(clangTidyPerformanceModule
|
||||||
FasterStringFindCheck.cpp
|
FasterStringFindCheck.cpp
|
||||||
ForRangeCopyCheck.cpp
|
ForRangeCopyCheck.cpp
|
||||||
ImplicitCastInLoopCheck.cpp
|
ImplicitConversionInLoopCheck.cpp
|
||||||
InefficientStringConcatenationCheck.cpp
|
InefficientStringConcatenationCheck.cpp
|
||||||
InefficientVectorOperationCheck.cpp
|
InefficientVectorOperationCheck.cpp
|
||||||
PerformanceTidyModule.cpp
|
PerformanceTidyModule.cpp
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//===--- ImplicitCastInLoopCheck.cpp - clang-tidy--------------------------===//
|
//===--- ImplicitConversionInLoopCheck.cpp - clang-tidy--------------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ImplicitCastInLoopCheck.h"
|
#include "ImplicitConversionInLoopCheck.h"
|
||||||
|
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
|
@ -21,30 +21,30 @@ namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
namespace performance {
|
namespace performance {
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Checks if the stmt is a ImplicitCastExpr with a CastKind that is not a NoOp.
|
// Checks if the stmt is a ImplicitCastExpr with a CastKind that is not a NoOp.
|
||||||
// The subtelty is that in some cases (user defined conversions), we can
|
// The subtelty is that in some cases (user defined conversions), we can
|
||||||
// get to ImplicitCastExpr inside each other, with the outer one a NoOp. In this
|
// get to ImplicitCastExpr inside each other, with the outer one a NoOp. In this
|
||||||
// case we skip the first cast expr.
|
// case we skip the first cast expr.
|
||||||
bool IsNonTrivialImplicitCast(const Stmt *ST) {
|
static bool IsNonTrivialImplicitCast(const Stmt *ST) {
|
||||||
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
|
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
|
||||||
return (ICE->getCastKind() != CK_NoOp) ||
|
return (ICE->getCastKind() != CK_NoOp) ||
|
||||||
IsNonTrivialImplicitCast(ICE->getSubExpr());
|
IsNonTrivialImplicitCast(ICE->getSubExpr());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ImplicitCastInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
// We look for const ref loop variables that (optionally inside an
|
// We look for const ref loop variables that (optionally inside an
|
||||||
// ExprWithCleanup) materialize a temporary, and contain a implicit cast. The
|
// ExprWithCleanup) materialize a temporary, and contain a implicit
|
||||||
// check on the implicit cast is done in check() because we can't access
|
// conversion. The check on the implicit conversion is done in check() because
|
||||||
// implicit cast subnode via matchers: has() skips casts and materialize!
|
// we can't access implicit conversion subnode via matchers: has() skips casts
|
||||||
// We also bind on the call to operator* to get the proper type in the
|
// and materialize! We also bind on the call to operator* to get the proper
|
||||||
// diagnostic message.
|
// type in the diagnostic message.
|
||||||
// Note that when the implicit cast is done through a user defined cast
|
//
|
||||||
// operator, the node is a CXXMemberCallExpr, not a CXXOperatorCallExpr, so
|
// Note that when the implicit conversion is done through a user defined
|
||||||
// it should not get caught by the cxxOperatorCallExpr() matcher.
|
// conversion operator, the node is a CXXMemberCallExpr, not a
|
||||||
|
// CXXOperatorCallExpr, so it should not get caught by the
|
||||||
|
// cxxOperatorCallExpr() matcher.
|
||||||
Finder->addMatcher(
|
Finder->addMatcher(
|
||||||
cxxForRangeStmt(hasLoopVariable(
|
cxxForRangeStmt(hasLoopVariable(
|
||||||
varDecl(hasType(qualType(references(qualType(isConstQualified())))),
|
varDecl(hasType(qualType(references(qualType(isConstQualified())))),
|
||||||
|
@ -55,7 +55,8 @@ void ImplicitCastInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitCastInLoopCheck::check(const MatchFinder::MatchResult &Result) {
|
void ImplicitConversionInLoopCheck::check(
|
||||||
|
const MatchFinder::MatchResult &Result) {
|
||||||
const auto *VD = Result.Nodes.getNodeAs<VarDecl>("faulty-var");
|
const auto *VD = Result.Nodes.getNodeAs<VarDecl>("faulty-var");
|
||||||
const auto *Init = Result.Nodes.getNodeAs<Expr>("init");
|
const auto *Init = Result.Nodes.getNodeAs<Expr>("init");
|
||||||
const auto *OperatorCall =
|
const auto *OperatorCall =
|
||||||
|
@ -76,7 +77,7 @@ void ImplicitCastInLoopCheck::check(const MatchFinder::MatchResult &Result) {
|
||||||
ReportAndFix(Result.Context, VD, OperatorCall);
|
ReportAndFix(Result.Context, VD, OperatorCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitCastInLoopCheck::ReportAndFix(
|
void ImplicitConversionInLoopCheck::ReportAndFix(
|
||||||
const ASTContext *Context, const VarDecl *VD,
|
const ASTContext *Context, const VarDecl *VD,
|
||||||
const CXXOperatorCallExpr *OperatorCall) {
|
const CXXOperatorCallExpr *OperatorCall) {
|
||||||
// We only match on const ref, so we should print a const ref version of the
|
// We only match on const ref, so we should print a const ref version of the
|
||||||
|
@ -85,8 +86,8 @@ void ImplicitCastInLoopCheck::ReportAndFix(
|
||||||
QualType ConstRefType = Context->getLValueReferenceType(ConstType);
|
QualType ConstRefType = Context->getLValueReferenceType(ConstType);
|
||||||
const char Message[] =
|
const char Message[] =
|
||||||
"the type of the loop variable %0 is different from the one returned "
|
"the type of the loop variable %0 is different from the one returned "
|
||||||
"by the iterator and generates an implicit cast; you can either "
|
"by the iterator and generates an implicit conversion; you can either "
|
||||||
"change the type to the correct one (%1 but 'const auto&' is always a "
|
"change the type to the matching one (%1 but 'const auto&' is always a "
|
||||||
"valid option) or remove the reference to make it explicit that you are "
|
"valid option) or remove the reference to make it explicit that you are "
|
||||||
"creating a new value";
|
"creating a new value";
|
||||||
diag(VD->getLocStart(), Message) << VD << ConstRefType;
|
diag(VD->getLocStart(), Message) << VD << ConstRefType;
|
|
@ -1,4 +1,4 @@
|
||||||
//===--- ImplicitCastInLoopCheck.h - clang-tidy------------------*- C++ -*-===//
|
//===--- ImplicitConversionInLoopCheck.h - clang-tidy------------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -7,8 +7,8 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
|
||||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
|
||||||
|
|
||||||
#include "../ClangTidy.h"
|
#include "../ClangTidy.h"
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ namespace performance {
|
||||||
// Checks that in a for range loop, if the provided type is a reference, then
|
// Checks that in a for range loop, if the provided type is a reference, then
|
||||||
// the underlying type is the one returned by the iterator (i.e. that there
|
// the underlying type is the one returned by the iterator (i.e. that there
|
||||||
// isn't any implicit conversion).
|
// isn't any implicit conversion).
|
||||||
class ImplicitCastInLoopCheck : public ClangTidyCheck {
|
class ImplicitConversionInLoopCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
ImplicitCastInLoopCheck(StringRef Name, ClangTidyContext *Context)
|
ImplicitConversionInLoopCheck(StringRef Name, ClangTidyContext *Context)
|
||||||
: ClangTidyCheck(Name, Context) {}
|
: ClangTidyCheck(Name, Context) {}
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||||
|
@ -35,4 +35,4 @@ private:
|
||||||
} // namespace tidy
|
} // namespace tidy
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
||||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
|
|
@ -12,7 +12,7 @@
|
||||||
#include "../ClangTidyModuleRegistry.h"
|
#include "../ClangTidyModuleRegistry.h"
|
||||||
#include "FasterStringFindCheck.h"
|
#include "FasterStringFindCheck.h"
|
||||||
#include "ForRangeCopyCheck.h"
|
#include "ForRangeCopyCheck.h"
|
||||||
#include "ImplicitCastInLoopCheck.h"
|
#include "ImplicitConversionInLoopCheck.h"
|
||||||
#include "InefficientStringConcatenationCheck.h"
|
#include "InefficientStringConcatenationCheck.h"
|
||||||
#include "InefficientVectorOperationCheck.h"
|
#include "InefficientVectorOperationCheck.h"
|
||||||
#include "TypePromotionInMathFnCheck.h"
|
#include "TypePromotionInMathFnCheck.h"
|
||||||
|
@ -30,8 +30,8 @@ public:
|
||||||
"performance-faster-string-find");
|
"performance-faster-string-find");
|
||||||
CheckFactories.registerCheck<ForRangeCopyCheck>(
|
CheckFactories.registerCheck<ForRangeCopyCheck>(
|
||||||
"performance-for-range-copy");
|
"performance-for-range-copy");
|
||||||
CheckFactories.registerCheck<ImplicitCastInLoopCheck>(
|
CheckFactories.registerCheck<ImplicitConversionInLoopCheck>(
|
||||||
"performance-implicit-cast-in-loop");
|
"performance-implicit-conversion-in-loop");
|
||||||
CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
|
CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
|
||||||
"performance-inefficient-string-concatenation");
|
"performance-inefficient-string-concatenation");
|
||||||
CheckFactories.registerCheck<InefficientVectorOperationCheck>(
|
CheckFactories.registerCheck<InefficientVectorOperationCheck>(
|
||||||
|
|
|
@ -9,7 +9,7 @@ add_clang_library(clangTidyReadabilityModule
|
||||||
ElseAfterReturnCheck.cpp
|
ElseAfterReturnCheck.cpp
|
||||||
FunctionSizeCheck.cpp
|
FunctionSizeCheck.cpp
|
||||||
IdentifierNamingCheck.cpp
|
IdentifierNamingCheck.cpp
|
||||||
ImplicitBoolCastCheck.cpp
|
ImplicitBoolConversionCheck.cpp
|
||||||
InconsistentDeclarationParameterNameCheck.cpp
|
InconsistentDeclarationParameterNameCheck.cpp
|
||||||
MisleadingIndentationCheck.cpp
|
MisleadingIndentationCheck.cpp
|
||||||
MisplacedArrayIndexCheck.cpp
|
MisplacedArrayIndexCheck.cpp
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//===--- ImplicitBoolCastCheck.cpp - clang-tidy----------------------------===//
|
//===--- ImplicitBoolConversionCheck.cpp - clang-tidy----------------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ImplicitBoolCastCheck.h"
|
#include "ImplicitBoolConversionCheck.h"
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||||
#include "clang/Lex/Lexer.h"
|
#include "clang/Lex/Lexer.h"
|
||||||
|
@ -218,7 +218,7 @@ StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
|
||||||
return BoolLiteral->getValue() ? "1" : "0";
|
return BoolLiteral->getValue() ? "1" : "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
|
bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
|
||||||
ASTContext &Context) {
|
ASTContext &Context) {
|
||||||
std::queue<const Stmt *> Q;
|
std::queue<const Stmt *> Q;
|
||||||
Q.push(Cast);
|
Q.push(Cast);
|
||||||
|
@ -245,22 +245,19 @@ bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
ImplicitBoolCastCheck::ImplicitBoolCastCheck(StringRef Name,
|
ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
|
||||||
ClangTidyContext *Context)
|
StringRef Name, ClangTidyContext *Context)
|
||||||
: ClangTidyCheck(Name, Context),
|
: ClangTidyCheck(Name, Context),
|
||||||
AllowConditionalIntegerCasts(
|
AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
|
||||||
Options.get("AllowConditionalIntegerCasts", false)),
|
AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
|
||||||
AllowConditionalPointerCasts(
|
|
||||||
Options.get("AllowConditionalPointerCasts", false)) {}
|
|
||||||
|
|
||||||
void ImplicitBoolCastCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
void ImplicitBoolConversionCheck::storeOptions(
|
||||||
Options.store(Opts, "AllowConditionalIntegerCasts",
|
ClangTidyOptions::OptionMap &Opts) {
|
||||||
AllowConditionalIntegerCasts);
|
Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
|
||||||
Options.store(Opts, "AllowConditionalPointerCasts",
|
Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
|
||||||
AllowConditionalPointerCasts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
|
void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
// This check doesn't make much sense if we run it on language without
|
// This check doesn't make much sense if we run it on language without
|
||||||
// built-in bool support.
|
// built-in bool support.
|
||||||
if (!getLangOpts().Bool) {
|
if (!getLangOpts().Bool) {
|
||||||
|
@ -326,7 +323,8 @@ void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitBoolCastCheck::check(const MatchFinder::MatchResult &Result) {
|
void ImplicitBoolConversionCheck::check(
|
||||||
|
const MatchFinder::MatchResult &Result) {
|
||||||
if (const auto *CastToBool =
|
if (const auto *CastToBool =
|
||||||
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
|
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
|
||||||
const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
|
const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
|
||||||
|
@ -341,23 +339,22 @@ void ImplicitBoolCastCheck::check(const MatchFinder::MatchResult &Result) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitBoolCastCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
||||||
const Stmt *Parent,
|
const Stmt *Parent,
|
||||||
ASTContext &Context) {
|
ASTContext &Context) {
|
||||||
if (AllowConditionalPointerCasts &&
|
if (AllowPointerConditions &&
|
||||||
(Cast->getCastKind() == CK_PointerToBoolean ||
|
(Cast->getCastKind() == CK_PointerToBoolean ||
|
||||||
Cast->getCastKind() == CK_MemberPointerToBoolean) &&
|
Cast->getCastKind() == CK_MemberPointerToBoolean) &&
|
||||||
isAllowedConditionalCast(Cast, Context)) {
|
isCastAllowedInCondition(Cast, Context)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AllowConditionalIntegerCasts &&
|
if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
|
||||||
Cast->getCastKind() == CK_IntegralToBoolean &&
|
isCastAllowedInCondition(Cast, Context)) {
|
||||||
isAllowedConditionalCast(Cast, Context)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Diag = diag(Cast->getLocStart(), "implicit cast %0 -> bool")
|
auto Diag = diag(Cast->getLocStart(), "implicit conversion %0 -> bool")
|
||||||
<< Cast->getSubExpr()->getType();
|
<< Cast->getSubExpr()->getType();
|
||||||
|
|
||||||
StringRef EquivalentLiteral =
|
StringRef EquivalentLiteral =
|
||||||
|
@ -369,12 +366,13 @@ void ImplicitBoolCastCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitBoolCastCheck::handleCastFromBool(
|
void ImplicitBoolConversionCheck::handleCastFromBool(
|
||||||
const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
|
const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
|
||||||
ASTContext &Context) {
|
ASTContext &Context) {
|
||||||
QualType DestType =
|
QualType DestType =
|
||||||
NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
|
NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
|
||||||
auto Diag = diag(Cast->getLocStart(), "implicit cast bool -> %0") << DestType;
|
auto Diag = diag(Cast->getLocStart(), "implicit conversion bool -> %0")
|
||||||
|
<< DestType;
|
||||||
|
|
||||||
if (const auto *BoolLiteral =
|
if (const auto *BoolLiteral =
|
||||||
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
|
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
|
|
@ -1,4 +1,4 @@
|
||||||
//===--- ImplicitBoolCastCheck.h - clang-tidy--------------------*- C++ -*-===//
|
//===--- ImplicitBoolConversionCheck.h - clang-tidy--------------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -7,8 +7,8 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
|
||||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
|
||||||
|
|
||||||
#include "../ClangTidy.h"
|
#include "../ClangTidy.h"
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ namespace clang {
|
||||||
namespace tidy {
|
namespace tidy {
|
||||||
namespace readability {
|
namespace readability {
|
||||||
|
|
||||||
/// \brief Checks for use of implicit bool casts in expressions.
|
/// \brief Checks for use of implicit bool conversions in expressions.
|
||||||
///
|
///
|
||||||
/// For the user-facing documentation see:
|
/// For the user-facing documentation see:
|
||||||
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-cast.html
|
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-conversion.html
|
||||||
class ImplicitBoolCastCheck : public ClangTidyCheck {
|
class ImplicitBoolConversionCheck : public ClangTidyCheck {
|
||||||
public:
|
public:
|
||||||
ImplicitBoolCastCheck(StringRef Name, ClangTidyContext *Context);
|
ImplicitBoolConversionCheck(StringRef Name, ClangTidyContext *Context);
|
||||||
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
||||||
|
|
||||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||||
|
@ -35,12 +35,12 @@ private:
|
||||||
const ImplicitCastExpr *FurtherImplicitCastExpression,
|
const ImplicitCastExpr *FurtherImplicitCastExpression,
|
||||||
ASTContext &Context);
|
ASTContext &Context);
|
||||||
|
|
||||||
bool AllowConditionalIntegerCasts;
|
const bool AllowIntegerConditions;
|
||||||
bool AllowConditionalPointerCasts;
|
const bool AllowPointerConditions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace readability
|
} // namespace readability
|
||||||
} // namespace tidy
|
} // namespace tidy
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
||||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
|
|
@ -18,7 +18,7 @@
|
||||||
#include "ElseAfterReturnCheck.h"
|
#include "ElseAfterReturnCheck.h"
|
||||||
#include "FunctionSizeCheck.h"
|
#include "FunctionSizeCheck.h"
|
||||||
#include "IdentifierNamingCheck.h"
|
#include "IdentifierNamingCheck.h"
|
||||||
#include "ImplicitBoolCastCheck.h"
|
#include "ImplicitBoolConversionCheck.h"
|
||||||
#include "InconsistentDeclarationParameterNameCheck.h"
|
#include "InconsistentDeclarationParameterNameCheck.h"
|
||||||
#include "MisleadingIndentationCheck.h"
|
#include "MisleadingIndentationCheck.h"
|
||||||
#include "MisplacedArrayIndexCheck.h"
|
#include "MisplacedArrayIndexCheck.h"
|
||||||
|
@ -58,8 +58,8 @@ public:
|
||||||
"readability-function-size");
|
"readability-function-size");
|
||||||
CheckFactories.registerCheck<IdentifierNamingCheck>(
|
CheckFactories.registerCheck<IdentifierNamingCheck>(
|
||||||
"readability-identifier-naming");
|
"readability-identifier-naming");
|
||||||
CheckFactories.registerCheck<ImplicitBoolCastCheck>(
|
CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
|
||||||
"readability-implicit-bool-cast");
|
"readability-implicit-bool-conversion");
|
||||||
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
|
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
|
||||||
"readability-inconsistent-declaration-parameter-name");
|
"readability-inconsistent-declaration-parameter-name");
|
||||||
CheckFactories.registerCheck<MisleadingIndentationCheck>(
|
CheckFactories.registerCheck<MisleadingIndentationCheck>(
|
||||||
|
|
|
@ -57,7 +57,19 @@ The improvements are...
|
||||||
Improvements to clang-tidy
|
Improvements to clang-tidy
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The improvements are...
|
* Renamed checks to use correct term "implicit conversion" instead of "implicit
|
||||||
|
cast" and modified messages and option names accordingly:
|
||||||
|
|
||||||
|
- **performance-implicit-cast-in-loop** was renamed to
|
||||||
|
`performance-implicit-conversion-in-loop
|
||||||
|
<http://clang.llvm.org/extra/clang-tidy/checks/performance-implicit-conversion-in-loop.html>`_
|
||||||
|
- **readability-implicit-bool-cast** was renamed to
|
||||||
|
`readability-implicit-bool-conversion
|
||||||
|
<http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-conversion.html>`_;
|
||||||
|
the check's options were renamed as follows:
|
||||||
|
``AllowConditionalIntegerCasts`` -> ``AllowIntegerConditions``,
|
||||||
|
``AllowConditionalPointerCasts`` -> ``AllowPointerConditions``.
|
||||||
|
|
||||||
|
|
||||||
Improvements to include-fixer
|
Improvements to include-fixer
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
|
@ -150,7 +150,7 @@ Clang-Tidy Checks
|
||||||
mpi-type-mismatch
|
mpi-type-mismatch
|
||||||
performance-faster-string-find
|
performance-faster-string-find
|
||||||
performance-for-range-copy
|
performance-for-range-copy
|
||||||
performance-implicit-cast-in-loop
|
performance-implicit-conversion-in-loop
|
||||||
performance-inefficient-string-concatenation
|
performance-inefficient-string-concatenation
|
||||||
performance-inefficient-vector-operation
|
performance-inefficient-vector-operation
|
||||||
performance-type-promotion-in-math-fn
|
performance-type-promotion-in-math-fn
|
||||||
|
@ -164,7 +164,7 @@ Clang-Tidy Checks
|
||||||
readability-else-after-return
|
readability-else-after-return
|
||||||
readability-function-size
|
readability-function-size
|
||||||
readability-identifier-naming
|
readability-identifier-naming
|
||||||
readability-implicit-bool-cast
|
readability-implicit-bool-conversion
|
||||||
readability-inconsistent-declaration-parameter-name
|
readability-inconsistent-declaration-parameter-name
|
||||||
readability-misleading-indentation
|
readability-misleading-indentation
|
||||||
readability-misplaced-array-index
|
readability-misplaced-array-index
|
||||||
|
|
|
@ -1,21 +1,12 @@
|
||||||
|
:orphan:
|
||||||
|
|
||||||
.. title:: clang-tidy - performance-implicit-cast-in-loop
|
.. title:: clang-tidy - performance-implicit-cast-in-loop
|
||||||
|
.. meta::
|
||||||
|
:http-equiv=refresh: 5;URL=performance-implicit-conversion-in-loop.html
|
||||||
|
|
||||||
performance-implicit-cast-in-loop
|
performance-implicit-cast-in-loop
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
This warning appears in a range-based loop with a loop variable of const ref
|
This check has been renamed to `performance-implicit-conversion-in-loop
|
||||||
type where the type of the variable does not match the one returned by the
|
<performance-implicit-conversion-in-loop.html>`_.
|
||||||
iterator. This means that an implicit cast has been added, which can for example
|
|
||||||
result in expensive deep copies.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: c++
|
|
||||||
|
|
||||||
map<int, vector<string>> my_map;
|
|
||||||
for (const pair<int, vector<string>>& p : my_map) {}
|
|
||||||
// The iterator type is in fact pair<const int, vector<string>>, which means
|
|
||||||
// that the compiler added a cast, resulting in a copy of the vectors.
|
|
||||||
|
|
||||||
The easiest solution is usually to use ``const auto&`` instead of writing the type
|
|
||||||
manually.
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
.. title:: clang-tidy - performance-implicit-conversion-in-loop
|
||||||
|
|
||||||
|
performance-implicit-conversion-in-loop
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
This warning appears in a range-based loop with a loop variable of const ref
|
||||||
|
type where the type of the variable does not match the one returned by the
|
||||||
|
iterator. This means that an implicit conversion happens, which can for example
|
||||||
|
result in expensive deep copies.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
map<int, vector<string>> my_map;
|
||||||
|
for (const pair<int, vector<string>>& p : my_map) {}
|
||||||
|
// The iterator type is in fact pair<const int, vector<string>>, which means
|
||||||
|
// that the compiler added a conversion, resulting in a copy of the vectors.
|
||||||
|
|
||||||
|
The easiest solution is usually to use ``const auto&`` instead of writing the
|
||||||
|
type manually.
|
|
@ -1,130 +1,11 @@
|
||||||
|
:orphan:
|
||||||
|
|
||||||
.. title:: clang-tidy - readability-implicit-bool-cast
|
.. title:: clang-tidy - readability-implicit-bool-cast
|
||||||
|
.. meta::
|
||||||
|
:http-equiv=refresh: 5;URL=readability-implicit-bool-conversion.html
|
||||||
|
|
||||||
readability-implicit-bool-cast
|
readability-implicit-bool-cast
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
This check can be used to find implicit conversions between built-in types and
|
This check has been renamed to `readability-implicit-bool-conversion
|
||||||
booleans. Depending on use case, it may simply help with readability of the code,
|
<readability-implicit-bool-conversion.html>`_.
|
||||||
or in some cases, point to potential bugs which remain unnoticed due to implicit
|
|
||||||
conversions.
|
|
||||||
|
|
||||||
The following is a real-world example of bug which was hiding behind implicit
|
|
||||||
``bool`` cast:
|
|
||||||
|
|
||||||
.. code-block:: c++
|
|
||||||
|
|
||||||
class Foo {
|
|
||||||
int m_foo;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setFoo(bool foo) { m_foo = foo; } // warning: implicit cast bool -> int
|
|
||||||
int getFoo() { return m_foo; }
|
|
||||||
};
|
|
||||||
|
|
||||||
void use(Foo& foo) {
|
|
||||||
bool value = foo.getFoo(); // warning: implicit cast int -> bool
|
|
||||||
}
|
|
||||||
|
|
||||||
This code is the result of unsuccessful refactoring, where type of ``m_foo``
|
|
||||||
changed from ``bool`` to ``int``. The programmer forgot to change all
|
|
||||||
occurrences of ``bool``, and the remaining code is no longer correct, yet it
|
|
||||||
still compiles without any visible warnings.
|
|
||||||
|
|
||||||
In addition to issuing warnings, fix-it hints are provided to help solve the
|
|
||||||
reported issues. This can be used for improving readability of code, for
|
|
||||||
example:
|
|
||||||
|
|
||||||
.. code-block:: c++
|
|
||||||
|
|
||||||
void conversionsToBool() {
|
|
||||||
float floating;
|
|
||||||
bool boolean = floating;
|
|
||||||
// ^ propose replacement: bool boolean = floating != 0.0f;
|
|
||||||
|
|
||||||
int integer;
|
|
||||||
if (integer) {}
|
|
||||||
// ^ propose replacement: if (integer != 0) {}
|
|
||||||
|
|
||||||
int* pointer;
|
|
||||||
if (!pointer) {}
|
|
||||||
// ^ propose replacement: if (pointer == nullptr) {}
|
|
||||||
|
|
||||||
while (1) {}
|
|
||||||
// ^ propose replacement: while (true) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
void functionTakingInt(int param);
|
|
||||||
|
|
||||||
void conversionsFromBool() {
|
|
||||||
bool boolean;
|
|
||||||
functionTakingInt(boolean);
|
|
||||||
// ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
|
|
||||||
|
|
||||||
functionTakingInt(true);
|
|
||||||
// ^ propose replacement: functionTakingInt(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
In general, the following cast types are checked:
|
|
||||||
|
|
||||||
- integer expression/literal to boolean,
|
|
||||||
|
|
||||||
- floating expression/literal to boolean,
|
|
||||||
|
|
||||||
- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
|
|
||||||
|
|
||||||
- boolean expression/literal to integer,
|
|
||||||
|
|
||||||
- boolean expression/literal to floating.
|
|
||||||
|
|
||||||
The rules for generating fix-it hints are:
|
|
||||||
|
|
||||||
- in case of casts from other built-in type to bool, an explicit comparison
|
|
||||||
is proposed to make it clear what exaclty is being compared:
|
|
||||||
|
|
||||||
- ``bool boolean = floating;`` is changed to
|
|
||||||
``bool boolean = floating == 0.0f;``,
|
|
||||||
|
|
||||||
- for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
|
|
||||||
``0.0``, ``nullptr``),
|
|
||||||
|
|
||||||
- in case of negated expressions cast to bool, the proposed replacement with
|
|
||||||
comparison is simplified:
|
|
||||||
|
|
||||||
- ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
|
|
||||||
|
|
||||||
- in case of casts from bool to other built-in types, an explicit ``static_cast``
|
|
||||||
is proposed to make it clear that a cast is taking place:
|
|
||||||
|
|
||||||
- ``int integer = boolean;`` is changed to
|
|
||||||
``int integer = static_cast<int>(boolean);``,
|
|
||||||
|
|
||||||
- if the cast is performed on type literals, an equivalent literal is proposed,
|
|
||||||
according to what type is actually expected, for example:
|
|
||||||
|
|
||||||
- ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
|
|
||||||
|
|
||||||
- ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
|
|
||||||
|
|
||||||
- for other types, appropriate literals are used (``false``, ``true``, ``0``,
|
|
||||||
``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
|
|
||||||
|
|
||||||
Some additional accommodations are made for pre-C++11 dialects:
|
|
||||||
|
|
||||||
- ``false`` literal cast to pointer is detected,
|
|
||||||
|
|
||||||
- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
|
|
||||||
|
|
||||||
Occurrences of implicit casts inside macros and template instantiations are
|
|
||||||
deliberately ignored, as it is not clear how to deal with such cases.
|
|
||||||
|
|
||||||
Options
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. option:: AllowConditionalIntegerCasts
|
|
||||||
|
|
||||||
When non-zero, the check will allow conditional integer casts. Default is
|
|
||||||
`0`.
|
|
||||||
|
|
||||||
.. option:: AllowConditionalPointerCasts
|
|
||||||
|
|
||||||
When non-zero, the check will allow conditional pointer casts. Default is `0`.
|
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
.. title:: clang-tidy - readability-implicit-bool-conversion
|
||||||
|
|
||||||
|
readability-implicit-bool-conversion
|
||||||
|
====================================
|
||||||
|
|
||||||
|
This check can be used to find implicit conversions between built-in types and
|
||||||
|
booleans. Depending on use case, it may simply help with readability of the code,
|
||||||
|
or in some cases, point to potential bugs which remain unnoticed due to implicit
|
||||||
|
conversions.
|
||||||
|
|
||||||
|
The following is a real-world example of bug which was hiding behind implicit
|
||||||
|
``bool`` conversion:
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
int m_foo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int
|
||||||
|
int getFoo() { return m_foo; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void use(Foo& foo) {
|
||||||
|
bool value = foo.getFoo(); // warning: implicit conversion int -> bool
|
||||||
|
}
|
||||||
|
|
||||||
|
This code is the result of unsuccessful refactoring, where type of ``m_foo``
|
||||||
|
changed from ``bool`` to ``int``. The programmer forgot to change all
|
||||||
|
occurrences of ``bool``, and the remaining code is no longer correct, yet it
|
||||||
|
still compiles without any visible warnings.
|
||||||
|
|
||||||
|
In addition to issuing warnings, fix-it hints are provided to help solve the
|
||||||
|
reported issues. This can be used for improving readability of code, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
void conversionsToBool() {
|
||||||
|
float floating;
|
||||||
|
bool boolean = floating;
|
||||||
|
// ^ propose replacement: bool boolean = floating != 0.0f;
|
||||||
|
|
||||||
|
int integer;
|
||||||
|
if (integer) {}
|
||||||
|
// ^ propose replacement: if (integer != 0) {}
|
||||||
|
|
||||||
|
int* pointer;
|
||||||
|
if (!pointer) {}
|
||||||
|
// ^ propose replacement: if (pointer == nullptr) {}
|
||||||
|
|
||||||
|
while (1) {}
|
||||||
|
// ^ propose replacement: while (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void functionTakingInt(int param);
|
||||||
|
|
||||||
|
void conversionsFromBool() {
|
||||||
|
bool boolean;
|
||||||
|
functionTakingInt(boolean);
|
||||||
|
// ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
|
||||||
|
|
||||||
|
functionTakingInt(true);
|
||||||
|
// ^ propose replacement: functionTakingInt(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
In general, the following conversion types are checked:
|
||||||
|
|
||||||
|
- integer expression/literal to boolean,
|
||||||
|
|
||||||
|
- floating expression/literal to boolean,
|
||||||
|
|
||||||
|
- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
|
||||||
|
|
||||||
|
- boolean expression/literal to integer,
|
||||||
|
|
||||||
|
- boolean expression/literal to floating.
|
||||||
|
|
||||||
|
The rules for generating fix-it hints are:
|
||||||
|
|
||||||
|
- in case of conversions from other built-in type to bool, an explicit
|
||||||
|
comparison is proposed to make it clear what exaclty is being compared:
|
||||||
|
|
||||||
|
- ``bool boolean = floating;`` is changed to
|
||||||
|
``bool boolean = floating == 0.0f;``,
|
||||||
|
|
||||||
|
- for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
|
||||||
|
``0.0``, ``nullptr``),
|
||||||
|
|
||||||
|
- in case of negated expressions conversion to bool, the proposed replacement
|
||||||
|
with comparison is simplified:
|
||||||
|
|
||||||
|
- ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
|
||||||
|
|
||||||
|
- in case of conversions from bool to other built-in types, an explicit
|
||||||
|
``static_cast`` is proposed to make it clear that a conversion is taking
|
||||||
|
place:
|
||||||
|
|
||||||
|
- ``int integer = boolean;`` is changed to
|
||||||
|
``int integer = static_cast<int>(boolean);``,
|
||||||
|
|
||||||
|
- if the conversion is performed on type literals, an equivalent literal is
|
||||||
|
proposed, according to what type is actually expected, for example:
|
||||||
|
|
||||||
|
- ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
|
||||||
|
|
||||||
|
- ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
|
||||||
|
|
||||||
|
- for other types, appropriate literals are used (``false``, ``true``, ``0``,
|
||||||
|
``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
|
||||||
|
|
||||||
|
Some additional accommodations are made for pre-C++11 dialects:
|
||||||
|
|
||||||
|
- ``false`` literal conversion to pointer is detected,
|
||||||
|
|
||||||
|
- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
|
||||||
|
|
||||||
|
Occurrences of implicit conversions inside macros and template instantiations
|
||||||
|
are deliberately ignored, as it is not clear how to deal with such cases.
|
||||||
|
|
||||||
|
Options
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. option:: AllowIntegerConditions
|
||||||
|
|
||||||
|
When non-zero, the check will allow conditional integer conversions. Default
|
||||||
|
is `0`.
|
||||||
|
|
||||||
|
.. option:: AllowPointerConditions
|
||||||
|
|
||||||
|
When non-zero, the check will allow conditional pointer conversions. Default
|
||||||
|
is `0`.
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %check_clang_tidy %s performance-implicit-cast-in-loop %t
|
// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
|
||||||
|
|
||||||
// ---------- Classes used in the tests ----------
|
// ---------- Classes used in the tests ----------
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ struct View {
|
||||||
T end();
|
T end();
|
||||||
};
|
};
|
||||||
|
|
||||||
// With this class, the implicit cast is a call to the (implicit) constructor of
|
// With this class, the implicit conversion is a call to the (implicit)
|
||||||
// the class.
|
// constructor of the class.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ImplicitWrapper {
|
class ImplicitWrapper {
|
||||||
public:
|
public:
|
||||||
|
@ -35,8 +35,8 @@ class ImplicitWrapper {
|
||||||
ImplicitWrapper(const T& t);
|
ImplicitWrapper(const T& t);
|
||||||
};
|
};
|
||||||
|
|
||||||
// With this class, the implicit cast is a call to the conversion operators of
|
// With this class, the implicit conversion is a call to the conversion
|
||||||
// SimpleClass and ComplexClass.
|
// operators of SimpleClass and ComplexClass.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class OperatorWrapper {
|
class OperatorWrapper {
|
||||||
public:
|
public:
|
||||||
|
@ -98,7 +98,7 @@ void ComplexClassRefIterator() {
|
||||||
|
|
||||||
void ImplicitSimpleClassIterator() {
|
void ImplicitSimpleClassIterator() {
|
||||||
for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
|
for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
|
||||||
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit cast; you can either change the type to the correct one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-cast-in-loop]
|
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
|
||||||
// for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
|
// for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
|
||||||
for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
|
for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
|
||||||
for (ImplicitWrapper<SimpleClass>foo : SimpleView()) {}
|
for (ImplicitWrapper<SimpleClass>foo : SimpleView()) {}
|
|
@ -1,7 +1,7 @@
|
||||||
// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t \
|
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \
|
||||||
// RUN: -config='{CheckOptions: \
|
// RUN: -config='{CheckOptions: \
|
||||||
// RUN: [{key: readability-implicit-bool-cast.AllowConditionalIntegerCasts, value: 1}, \
|
// RUN: [{key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1}, \
|
||||||
// RUN: {key: readability-implicit-bool-cast.AllowConditionalPointerCasts, value: 1}]}' \
|
// RUN: {key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1}]}' \
|
||||||
// RUN: -- -std=c++11
|
// RUN: -- -std=c++11
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -15,14 +15,14 @@ struct Struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void regularImplicitCastIntegerToBoolIsNotIgnored() {
|
void regularImplicitConversionIntegerToBoolIsNotIgnored() {
|
||||||
int integer = 0;
|
int integer = 0;
|
||||||
functionTaking<bool>(integer);
|
functionTaking<bool>(integer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool [readability-implicit-bool-cast]
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool [readability-implicit-bool-conversion]
|
||||||
// CHECK-FIXES: functionTaking<bool>(integer != 0);
|
// CHECK-FIXES: functionTaking<bool>(integer != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastIntegerToBoolInConditionalsIsAllowed() {
|
void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
|
||||||
if (functionReturningInt()) {}
|
if (functionReturningInt()) {}
|
||||||
if (!functionReturningInt()) {}
|
if (!functionReturningInt()) {}
|
||||||
if (functionReturningInt() && functionReturningPointer()) {}
|
if (functionReturningInt() && functionReturningPointer()) {}
|
||||||
|
@ -40,19 +40,19 @@ void implicitCastIntegerToBoolInConditionalsIsAllowed() {
|
||||||
int *p1 = functionReturningPointer() ?: &value3;
|
int *p1 = functionReturningPointer() ?: &value3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void regularImplicitCastPointerToBoolIsNotIgnored() {
|
void regularImplicitConversionPointerToBoolIsNotIgnored() {
|
||||||
int* pointer = nullptr;
|
int* pointer = nullptr;
|
||||||
functionTaking<bool>(pointer);
|
functionTaking<bool>(pointer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
|
// CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
|
||||||
|
|
||||||
int Struct::* memberPointer = &Struct::member;
|
int Struct::* memberPointer = &Struct::member;
|
||||||
functionTaking<bool>(memberPointer);
|
functionTaking<bool>(memberPointer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
|
// CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastPointerToBoolInConditionalsIsAllowed() {
|
void implicitConversionPointerToBoolInConditionalsIsAllowed() {
|
||||||
if (functionReturningPointer()) {}
|
if (functionReturningPointer()) {}
|
||||||
if (not functionReturningPointer()) {}
|
if (not functionReturningPointer()) {}
|
||||||
int value1 = functionReturningPointer() ? 1 : 2;
|
int value1 = functionReturningPointer() ? 1 : 2;
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t -- -- -std=c++98
|
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c++98
|
||||||
|
|
||||||
// We need NULL macro, but some buildbots don't like including <cstddef> header
|
// We need NULL macro, but some buildbots don't like including <cstddef> header
|
||||||
// This is a portable way of getting it to work
|
// This is a portable way of getting it to work
|
||||||
|
@ -15,31 +15,31 @@ struct Struct {
|
||||||
void useOldNullMacroInReplacements() {
|
void useOldNullMacroInReplacements() {
|
||||||
int* pointer = NULL;
|
int* pointer = NULL;
|
||||||
functionTaking<bool>(pointer);
|
functionTaking<bool>(pointer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool [readability-implicit-bool-cast]
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool [readability-implicit-bool-conversion]
|
||||||
// CHECK-FIXES: functionTaking<bool>(pointer != 0);
|
// CHECK-FIXES: functionTaking<bool>(pointer != 0);
|
||||||
|
|
||||||
int Struct::* memberPointer = NULL;
|
int Struct::* memberPointer = NULL;
|
||||||
functionTaking<bool>(!memberPointer);
|
functionTaking<bool>(!memberPointer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast 'int Struct::*' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'int Struct::*' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
|
// CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixFalseLiteralConvertingToNullPointer() {
|
void fixFalseLiteralConvertingToNullPointer() {
|
||||||
functionTaking<int*>(false);
|
functionTaking<int*>(false);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int *'
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int *'
|
||||||
// CHECK-FIXES: functionTaking<int*>(0);
|
// CHECK-FIXES: functionTaking<int*>(0);
|
||||||
|
|
||||||
int* pointer = NULL;
|
int* pointer = NULL;
|
||||||
if (pointer == false) {}
|
if (pointer == false) {}
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit cast bool -> 'int *'
|
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit conversion bool -> 'int *'
|
||||||
// CHECK-FIXES: if (pointer == 0) {}
|
// CHECK-FIXES: if (pointer == 0) {}
|
||||||
|
|
||||||
functionTaking<int Struct::*>(false);
|
functionTaking<int Struct::*>(false);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'int Struct::*'
|
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'int Struct::*'
|
||||||
// CHECK-FIXES: functionTaking<int Struct::*>(0);
|
// CHECK-FIXES: functionTaking<int Struct::*>(0);
|
||||||
|
|
||||||
int Struct::* memberPointer = NULL;
|
int Struct::* memberPointer = NULL;
|
||||||
if (memberPointer != false) {}
|
if (memberPointer != false) {}
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int Struct::*'
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int Struct::*'
|
||||||
// CHECK-FIXES: if (memberPointer != 0) {}
|
// CHECK-FIXES: if (memberPointer != 0) {}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t
|
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
|
||||||
|
|
||||||
// We need NULL macro, but some buildbots don't like including <cstddef> header
|
// We need NULL macro, but some buildbots don't like including <cstddef> header
|
||||||
// This is a portable way of getting it to work
|
// This is a portable way of getting it to work
|
||||||
|
@ -13,42 +13,42 @@ struct Struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////// Implicit cast from bool.
|
////////// Implicit conversion from bool.
|
||||||
|
|
||||||
void implicitCastFromBoolSimpleCases() {
|
void implicitConversionFromBoolSimpleCases() {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
|
|
||||||
functionTaking<bool>(boolean);
|
functionTaking<bool>(boolean);
|
||||||
|
|
||||||
functionTaking<int>(boolean);
|
functionTaking<int>(boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int' [readability-implicit-bool-cast]
|
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
|
||||||
// CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
|
// CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
|
||||||
|
|
||||||
functionTaking<unsigned long>(boolean);
|
functionTaking<unsigned long>(boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
|
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
|
||||||
// CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
|
// CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
|
||||||
|
|
||||||
functionTaking<char>(boolean);
|
functionTaking<char>(boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'char'
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'char'
|
||||||
// CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
|
// CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
|
||||||
|
|
||||||
functionTaking<float>(boolean);
|
functionTaking<float>(boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
|
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
|
||||||
// CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
|
// CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
|
||||||
|
|
||||||
functionTaking<double>(boolean);
|
functionTaking<double>(boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
|
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
|
||||||
// CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
|
// CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
float implicitCastFromBoolInReturnValue() {
|
float implicitConversionFromBoolInReturnValue() {
|
||||||
bool boolean = false;
|
bool boolean = false;
|
||||||
return boolean;
|
return boolean;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast bool -> 'float'
|
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion bool -> 'float'
|
||||||
// CHECK-FIXES: return static_cast<float>(boolean);
|
// CHECK-FIXES: return static_cast<float>(boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
boolean = b1 ^ b2;
|
boolean = b1 ^ b2;
|
||||||
boolean = b1 && b2;
|
boolean = b1 && b2;
|
||||||
|
@ -58,71 +58,71 @@ void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
||||||
boolean = b2 != false;
|
boolean = b2 != false;
|
||||||
|
|
||||||
int integer = boolean - 3;
|
int integer = boolean - 3;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
|
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
|
||||||
// CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
|
// CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
|
||||||
|
|
||||||
float floating = boolean / 0.3f;
|
float floating = boolean / 0.3f;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
|
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
|
||||||
// CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
|
// CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
|
||||||
|
|
||||||
char character = boolean;
|
char character = boolean;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'char'
|
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'char'
|
||||||
// CHECK-FIXES: char character = static_cast<char>(boolean);
|
// CHECK-FIXES: char character = static_cast<char>(boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastFromBoollInComplexBoolExpressions() {
|
void implicitConversionFromBoollInComplexBoolExpressions() {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
bool anotherBoolean = false;
|
bool anotherBoolean = false;
|
||||||
|
|
||||||
int integer = boolean && anotherBoolean;
|
int integer = boolean && anotherBoolean;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
|
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
|
||||||
// CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
|
// CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
|
||||||
|
|
||||||
unsigned long unsignedLong = (! boolean) + 4ul;
|
unsigned long unsignedLong = (! boolean) + 4ul;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast bool -> 'unsigned long'
|
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion bool -> 'unsigned long'
|
||||||
// CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
|
// CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
|
||||||
|
|
||||||
float floating = (boolean || anotherBoolean) * 0.3f;
|
float floating = (boolean || anotherBoolean) * 0.3f;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
|
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
|
||||||
// CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
|
// CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
|
||||||
|
|
||||||
double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
|
double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit cast bool -> 'double'
|
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion bool -> 'double'
|
||||||
// CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
|
// CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastFromBoolLiterals() {
|
void implicitConversionFromBoolLiterals() {
|
||||||
functionTaking<int>(true);
|
functionTaking<int>(true);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int'
|
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int'
|
||||||
// CHECK-FIXES: functionTaking<int>(1);
|
// CHECK-FIXES: functionTaking<int>(1);
|
||||||
|
|
||||||
functionTaking<unsigned long>(false);
|
functionTaking<unsigned long>(false);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
|
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
|
||||||
// CHECK-FIXES: functionTaking<unsigned long>(0u);
|
// CHECK-FIXES: functionTaking<unsigned long>(0u);
|
||||||
|
|
||||||
functionTaking<signed char>(true);
|
functionTaking<signed char>(true);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit cast bool -> 'signed char'
|
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion bool -> 'signed char'
|
||||||
// CHECK-FIXES: functionTaking<signed char>(1);
|
// CHECK-FIXES: functionTaking<signed char>(1);
|
||||||
|
|
||||||
functionTaking<float>(false);
|
functionTaking<float>(false);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
|
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
|
||||||
// CHECK-FIXES: functionTaking<float>(0.0f);
|
// CHECK-FIXES: functionTaking<float>(0.0f);
|
||||||
|
|
||||||
functionTaking<double>(true);
|
functionTaking<double>(true);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
|
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
|
||||||
// CHECK-FIXES: functionTaking<double>(1.0);
|
// CHECK-FIXES: functionTaking<double>(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastFromBoolInComparisons() {
|
void implicitConversionFromBoolInComparisons() {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
int integer = 0;
|
int integer = 0;
|
||||||
|
|
||||||
functionTaking<bool>(boolean == integer);
|
functionTaking<bool>(boolean == integer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int'
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int'
|
||||||
// CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
|
// CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
|
||||||
|
|
||||||
functionTaking<bool>(integer != boolean);
|
functionTaking<bool>(integer != boolean);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit cast bool -> 'int'
|
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit conversion bool -> 'int'
|
||||||
// CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
|
// CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ void ignoreExplicitCastsFromBool() {
|
||||||
char character = static_cast<char>(boolean);
|
char character = static_cast<char>(boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignoreImplicitCastFromBoolInMacroExpansions() {
|
void ignoreImplicitConversionFromBoolInMacroExpansions() {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
|
|
||||||
#define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
|
#define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
|
||||||
|
@ -152,7 +152,7 @@ void ignoreImplicitCastFromBoolInMacroExpansions() {
|
||||||
int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
|
int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ignoreImplicitCastFromBoolInTemplateInstantiations {
|
namespace ignoreImplicitConversionFromBoolInTemplateInstantiations {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void templateFunction() {
|
void templateFunction() {
|
||||||
|
@ -164,204 +164,204 @@ void useOfTemplateFunction() {
|
||||||
templateFunction<int>();
|
templateFunction<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ignoreImplicitCastFromBoolInTemplateInstantiations
|
} // namespace ignoreImplicitConversionFromBoolInTemplateInstantiations
|
||||||
|
|
||||||
////////// Implicit cast to bool.
|
////////// Implicit conversions to bool.
|
||||||
|
|
||||||
void implicitCastToBoolSimpleCases() {
|
void implicitConversionToBoolSimpleCases() {
|
||||||
int integer = 10;
|
int integer = 10;
|
||||||
functionTaking<bool>(integer);
|
functionTaking<bool>(integer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(integer != 0);
|
// CHECK-FIXES: functionTaking<bool>(integer != 0);
|
||||||
|
|
||||||
unsigned long unsignedLong = 10;
|
unsigned long unsignedLong = 10;
|
||||||
functionTaking<bool>(unsignedLong);
|
functionTaking<bool>(unsignedLong);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
|
// CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
|
||||||
|
|
||||||
float floating = 0.0f;
|
float floating = 0.0f;
|
||||||
functionTaking<bool>(floating);
|
functionTaking<bool>(floating);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
|
// CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
|
||||||
|
|
||||||
double doubleFloating = 1.0f;
|
double doubleFloating = 1.0f;
|
||||||
functionTaking<bool>(doubleFloating);
|
functionTaking<bool>(doubleFloating);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
|
// CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
|
||||||
|
|
||||||
signed char character = 'a';
|
signed char character = 'a';
|
||||||
functionTaking<bool>(character);
|
functionTaking<bool>(character);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'signed char' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'signed char' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(character != 0);
|
// CHECK-FIXES: functionTaking<bool>(character != 0);
|
||||||
|
|
||||||
int* pointer = nullptr;
|
int* pointer = nullptr;
|
||||||
functionTaking<bool>(pointer);
|
functionTaking<bool>(pointer);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
|
// CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
|
||||||
|
|
||||||
auto pointerToMember = &Struct::member;
|
auto pointerToMember = &Struct::member;
|
||||||
functionTaking<bool>(pointerToMember);
|
functionTaking<bool>(pointerToMember);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
|
// CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolInSingleExpressions() {
|
void implicitConversionToBoolInSingleExpressions() {
|
||||||
int integer = 10;
|
int integer = 10;
|
||||||
bool boolComingFromInt = integer;
|
bool boolComingFromInt = integer;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromInt = integer != 0;
|
// CHECK-FIXES: bool boolComingFromInt = integer != 0;
|
||||||
|
|
||||||
float floating = 10.0f;
|
float floating = 10.0f;
|
||||||
bool boolComingFromFloat = floating;
|
bool boolComingFromFloat = floating;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
|
// CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
|
||||||
|
|
||||||
signed char character = 'a';
|
signed char character = 'a';
|
||||||
bool boolComingFromChar = character;
|
bool boolComingFromChar = character;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit cast 'signed char' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit conversion 'signed char' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromChar = character != 0;
|
// CHECK-FIXES: bool boolComingFromChar = character != 0;
|
||||||
|
|
||||||
int* pointer = nullptr;
|
int* pointer = nullptr;
|
||||||
bool boolComingFromPointer = pointer;
|
bool boolComingFromPointer = pointer;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int *' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
|
// CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolInComplexExpressions() {
|
void implicitConversionToBoolInComplexExpressions() {
|
||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
|
|
||||||
int integer = 10;
|
int integer = 10;
|
||||||
int anotherInteger = 20;
|
int anotherInteger = 20;
|
||||||
bool boolComingFromInteger = integer + anotherInteger;
|
bool boolComingFromInteger = integer + anotherInteger;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
|
// CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
|
||||||
|
|
||||||
float floating = 0.2f;
|
float floating = 0.2f;
|
||||||
bool boolComingFromFloating = floating - 0.3f || boolean;
|
bool boolComingFromFloating = floating - 0.3f || boolean;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
|
// CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
|
||||||
|
|
||||||
double doubleFloating = 0.3;
|
double doubleFloating = 0.3;
|
||||||
bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
|
bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'double' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'double' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
|
// CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastInNegationExpressions() {
|
void implicitConversionInNegationExpressions() {
|
||||||
int integer = 10;
|
int integer = 10;
|
||||||
bool boolComingFromNegatedInt = !integer;
|
bool boolComingFromNegatedInt = !integer;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
|
// CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
|
||||||
|
|
||||||
float floating = 10.0f;
|
float floating = 10.0f;
|
||||||
bool boolComingFromNegatedFloat = ! floating;
|
bool boolComingFromNegatedFloat = ! floating;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
|
// CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
|
||||||
|
|
||||||
signed char character = 'a';
|
signed char character = 'a';
|
||||||
bool boolComingFromNegatedChar = (! character);
|
bool boolComingFromNegatedChar = (! character);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'signed char' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'signed char' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
|
// CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
|
||||||
|
|
||||||
int* pointer = nullptr;
|
int* pointer = nullptr;
|
||||||
bool boolComingFromNegatedPointer = not pointer;
|
bool boolComingFromNegatedPointer = not pointer;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit cast 'int *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit conversion 'int *' -> bool
|
||||||
// CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
|
// CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolInControlStatements() {
|
void implicitConversionToBoolInControlStatements() {
|
||||||
int integer = 10;
|
int integer = 10;
|
||||||
if (integer) {}
|
if (integer) {}
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: if (integer != 0) {}
|
// CHECK-FIXES: if (integer != 0) {}
|
||||||
|
|
||||||
long int longInteger = 0.2f;
|
long int longInteger = 0.2f;
|
||||||
for (;longInteger;) {}
|
for (;longInteger;) {}
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit cast 'long' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion 'long' -> bool
|
||||||
// CHECK-FIXES: for (;longInteger != 0;) {}
|
// CHECK-FIXES: for (;longInteger != 0;) {}
|
||||||
|
|
||||||
float floating = 0.3f;
|
float floating = 0.3f;
|
||||||
while (floating) {}
|
while (floating) {}
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: while (floating != 0.0f) {}
|
// CHECK-FIXES: while (floating != 0.0f) {}
|
||||||
|
|
||||||
double doubleFloating = 0.4;
|
double doubleFloating = 0.4;
|
||||||
do {} while (doubleFloating);
|
do {} while (doubleFloating);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit cast 'double' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit conversion 'double' -> bool
|
||||||
// CHECK-FIXES: do {} while (doubleFloating != 0.0);
|
// CHECK-FIXES: do {} while (doubleFloating != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool implicitCastToBoolInReturnValue() {
|
bool implicitConversionToBoolInReturnValue() {
|
||||||
float floating = 1.0f;
|
float floating = 1.0f;
|
||||||
return floating;
|
return floating;
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: return floating != 0.0f;
|
// CHECK-FIXES: return floating != 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolFromLiterals() {
|
void implicitConversionToBoolFromLiterals() {
|
||||||
functionTaking<bool>(0);
|
functionTaking<bool>(0);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(false);
|
// CHECK-FIXES: functionTaking<bool>(false);
|
||||||
|
|
||||||
functionTaking<bool>(1);
|
functionTaking<bool>(1);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
functionTaking<bool>(2ul);
|
functionTaking<bool>(2ul);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
|
|
||||||
functionTaking<bool>(0.0f);
|
functionTaking<bool>(0.0f);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(false);
|
// CHECK-FIXES: functionTaking<bool>(false);
|
||||||
|
|
||||||
functionTaking<bool>(1.0f);
|
functionTaking<bool>(1.0f);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
functionTaking<bool>(2.0);
|
functionTaking<bool>(2.0);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
|
|
||||||
functionTaking<bool>('\0');
|
functionTaking<bool>('\0');
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(false);
|
// CHECK-FIXES: functionTaking<bool>(false);
|
||||||
|
|
||||||
functionTaking<bool>('a');
|
functionTaking<bool>('a');
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
|
|
||||||
functionTaking<bool>("");
|
functionTaking<bool>("");
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
functionTaking<bool>("abc");
|
functionTaking<bool>("abc");
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(true);
|
// CHECK-FIXES: functionTaking<bool>(true);
|
||||||
|
|
||||||
functionTaking<bool>(NULL);
|
functionTaking<bool>(NULL);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'long' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'long' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(false);
|
// CHECK-FIXES: functionTaking<bool>(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolFromUnaryMinusAndZeroLiterals() {
|
void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
|
||||||
functionTaking<bool>(-0);
|
functionTaking<bool>(-0);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>((-0) != 0);
|
// CHECK-FIXES: functionTaking<bool>((-0) != 0);
|
||||||
|
|
||||||
functionTaking<bool>(-0.0f);
|
functionTaking<bool>(-0.0f);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
|
// CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
|
||||||
|
|
||||||
functionTaking<bool>(-0.0);
|
functionTaking<bool>(-0.0);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
|
// CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void implicitCastToBoolInWithOverloadedOperators() {
|
void implicitConversionToBoolInWithOverloadedOperators() {
|
||||||
struct UserStruct {
|
struct UserStruct {
|
||||||
int operator()(int x) { return x; }
|
int operator()(int x) { return x; }
|
||||||
int operator+(int y) { return y; }
|
int operator+(int y) { return y; }
|
||||||
|
@ -370,18 +370,18 @@ void implicitCastToBoolInWithOverloadedOperators() {
|
||||||
UserStruct s;
|
UserStruct s;
|
||||||
|
|
||||||
functionTaking<bool>(s(0));
|
functionTaking<bool>(s(0));
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>(s(0) != 0);
|
// CHECK-FIXES: functionTaking<bool>(s(0) != 0);
|
||||||
|
|
||||||
functionTaking<bool>(s + 2);
|
functionTaking<bool>(s + 2);
|
||||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
|
||||||
// CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
|
// CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int functionReturningInt();
|
int functionReturningInt();
|
||||||
int* functionReturningPointer();
|
int* functionReturningPointer();
|
||||||
|
|
||||||
void ignoreImplicitCastToBoolWhenDeclaringVariableInControlStatements() {
|
void ignoreImplicitConversionToBoolWhenDeclaringVariableInControlStatements() {
|
||||||
if (int integer = functionReturningInt()) {}
|
if (int integer = functionReturningInt()) {}
|
||||||
|
|
||||||
while (int* pointer = functionReturningPointer()) {}
|
while (int* pointer = functionReturningPointer()) {}
|
||||||
|
@ -401,7 +401,7 @@ void ignoreExplicitCastsToBool() {
|
||||||
bool booleanComingFromPointer = static_cast<bool>(pointer);
|
bool booleanComingFromPointer = static_cast<bool>(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignoreImplicitCastToBoolInMacroExpansions() {
|
void ignoreImplicitConversionToBoolInMacroExpansions() {
|
||||||
int integer = 3;
|
int integer = 3;
|
||||||
|
|
||||||
#define CAST_TO_BOOL_IN_MACRO_BODY integer && false
|
#define CAST_TO_BOOL_IN_MACRO_BODY integer && false
|
||||||
|
@ -411,7 +411,7 @@ void ignoreImplicitCastToBoolInMacroExpansions() {
|
||||||
bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
|
bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ignoreImplicitCastToBoolInTemplateInstantiations {
|
namespace ignoreImplicitConversionToBoolInTemplateInstantiations {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void templateFunction() {
|
void templateFunction() {
|
||||||
|
@ -423,7 +423,7 @@ void useOfTemplateFunction() {
|
||||||
templateFunction<int>();
|
templateFunction<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ignoreImplicitCastToBoolInTemplateInstantiations
|
} // namespace ignoreImplicitConversionToBoolInTemplateInstantiations
|
||||||
|
|
||||||
namespace ignoreUserDefinedConversionOperator {
|
namespace ignoreUserDefinedConversionOperator {
|
||||||
|
|
Loading…
Reference in New Issue