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
|
||||
FasterStringFindCheck.cpp
|
||||
ForRangeCopyCheck.cpp
|
||||
ImplicitCastInLoopCheck.cpp
|
||||
ImplicitConversionInLoopCheck.cpp
|
||||
InefficientStringConcatenationCheck.cpp
|
||||
InefficientVectorOperationCheck.cpp
|
||||
PerformanceTidyModule.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===--- ImplicitCastInLoopCheck.cpp - clang-tidy--------------------------===//
|
||||
//===--- ImplicitConversionInLoopCheck.cpp - clang-tidy--------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -7,7 +7,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ImplicitCastInLoopCheck.h"
|
||||
#include "ImplicitConversionInLoopCheck.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
@ -21,30 +21,30 @@ namespace clang {
|
|||
namespace tidy {
|
||||
namespace performance {
|
||||
|
||||
namespace {
|
||||
// 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
|
||||
// get to ImplicitCastExpr inside each other, with the outer one a NoOp. In this
|
||||
// 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)) {
|
||||
return (ICE->getCastKind() != CK_NoOp) ||
|
||||
IsNonTrivialImplicitCast(ICE->getSubExpr());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void ImplicitCastInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
||||
void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
||||
// We look for const ref loop variables that (optionally inside an
|
||||
// ExprWithCleanup) materialize a temporary, and contain a implicit cast. The
|
||||
// check on the implicit cast is done in check() because we can't access
|
||||
// implicit cast subnode via matchers: has() skips casts and materialize!
|
||||
// We also bind on the call to operator* to get the proper 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
|
||||
// it should not get caught by the cxxOperatorCallExpr() matcher.
|
||||
// ExprWithCleanup) materialize a temporary, and contain a implicit
|
||||
// conversion. The check on the implicit conversion is done in check() because
|
||||
// we can't access implicit conversion subnode via matchers: has() skips casts
|
||||
// and materialize! We also bind on the call to operator* to get the proper
|
||||
// type in the diagnostic message.
|
||||
//
|
||||
// Note that when the implicit conversion is done through a user defined
|
||||
// conversion operator, the node is a CXXMemberCallExpr, not a
|
||||
// CXXOperatorCallExpr, so it should not get caught by the
|
||||
// cxxOperatorCallExpr() matcher.
|
||||
Finder->addMatcher(
|
||||
cxxForRangeStmt(hasLoopVariable(
|
||||
varDecl(hasType(qualType(references(qualType(isConstQualified())))),
|
||||
|
@ -55,7 +55,8 @@ void ImplicitCastInLoopCheck::registerMatchers(MatchFinder *Finder) {
|
|||
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 *Init = Result.Nodes.getNodeAs<Expr>("init");
|
||||
const auto *OperatorCall =
|
||||
|
@ -76,7 +77,7 @@ void ImplicitCastInLoopCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
ReportAndFix(Result.Context, VD, OperatorCall);
|
||||
}
|
||||
|
||||
void ImplicitCastInLoopCheck::ReportAndFix(
|
||||
void ImplicitConversionInLoopCheck::ReportAndFix(
|
||||
const ASTContext *Context, const VarDecl *VD,
|
||||
const CXXOperatorCallExpr *OperatorCall) {
|
||||
// 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);
|
||||
const char Message[] =
|
||||
"the type of the loop variable %0 is different from the one returned "
|
||||
"by the iterator and generates an implicit cast; you can either "
|
||||
"change the type to the correct one (%1 but 'const auto&' is always a "
|
||||
"by the iterator and generates an implicit conversion; you can either "
|
||||
"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 "
|
||||
"creating a new value";
|
||||
diag(VD->getLocStart(), Message) << VD << ConstRefType;
|
|
@ -1,4 +1,4 @@
|
|||
//===--- ImplicitCastInLoopCheck.h - clang-tidy------------------*- C++ -*-===//
|
||||
//===--- ImplicitConversionInLoopCheck.h - clang-tidy------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -7,8 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
|
||||
#define 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_CONVERSION_IN_LOOP_CHECK_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
|
||||
// the underlying type is the one returned by the iterator (i.e. that there
|
||||
// isn't any implicit conversion).
|
||||
class ImplicitCastInLoopCheck : public ClangTidyCheck {
|
||||
class ImplicitConversionInLoopCheck : public ClangTidyCheck {
|
||||
public:
|
||||
ImplicitCastInLoopCheck(StringRef Name, ClangTidyContext *Context)
|
||||
ImplicitConversionInLoopCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
|
@ -35,4 +35,4 @@ private:
|
|||
} // namespace tidy
|
||||
} // 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 "FasterStringFindCheck.h"
|
||||
#include "ForRangeCopyCheck.h"
|
||||
#include "ImplicitCastInLoopCheck.h"
|
||||
#include "ImplicitConversionInLoopCheck.h"
|
||||
#include "InefficientStringConcatenationCheck.h"
|
||||
#include "InefficientVectorOperationCheck.h"
|
||||
#include "TypePromotionInMathFnCheck.h"
|
||||
|
@ -30,8 +30,8 @@ public:
|
|||
"performance-faster-string-find");
|
||||
CheckFactories.registerCheck<ForRangeCopyCheck>(
|
||||
"performance-for-range-copy");
|
||||
CheckFactories.registerCheck<ImplicitCastInLoopCheck>(
|
||||
"performance-implicit-cast-in-loop");
|
||||
CheckFactories.registerCheck<ImplicitConversionInLoopCheck>(
|
||||
"performance-implicit-conversion-in-loop");
|
||||
CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
|
||||
"performance-inefficient-string-concatenation");
|
||||
CheckFactories.registerCheck<InefficientVectorOperationCheck>(
|
||||
|
|
|
@ -9,7 +9,7 @@ add_clang_library(clangTidyReadabilityModule
|
|||
ElseAfterReturnCheck.cpp
|
||||
FunctionSizeCheck.cpp
|
||||
IdentifierNamingCheck.cpp
|
||||
ImplicitBoolCastCheck.cpp
|
||||
ImplicitBoolConversionCheck.cpp
|
||||
InconsistentDeclarationParameterNameCheck.cpp
|
||||
MisleadingIndentationCheck.cpp
|
||||
MisplacedArrayIndexCheck.cpp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===--- ImplicitBoolCastCheck.cpp - clang-tidy----------------------------===//
|
||||
//===--- ImplicitBoolConversionCheck.cpp - clang-tidy----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -7,7 +7,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ImplicitBoolCastCheck.h"
|
||||
#include "ImplicitBoolConversionCheck.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
|
@ -218,7 +218,7 @@ StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
|
|||
return BoolLiteral->getValue() ? "1" : "0";
|
||||
}
|
||||
|
||||
bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
|
||||
bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
|
||||
ASTContext &Context) {
|
||||
std::queue<const Stmt *> Q;
|
||||
Q.push(Cast);
|
||||
|
@ -245,22 +245,19 @@ bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
ImplicitBoolCastCheck::ImplicitBoolCastCheck(StringRef Name,
|
||||
ClangTidyContext *Context)
|
||||
ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
|
||||
StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context),
|
||||
AllowConditionalIntegerCasts(
|
||||
Options.get("AllowConditionalIntegerCasts", false)),
|
||||
AllowConditionalPointerCasts(
|
||||
Options.get("AllowConditionalPointerCasts", false)) {}
|
||||
AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
|
||||
AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
|
||||
|
||||
void ImplicitBoolCastCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||
Options.store(Opts, "AllowConditionalIntegerCasts",
|
||||
AllowConditionalIntegerCasts);
|
||||
Options.store(Opts, "AllowConditionalPointerCasts",
|
||||
AllowConditionalPointerCasts);
|
||||
void ImplicitBoolConversionCheck::storeOptions(
|
||||
ClangTidyOptions::OptionMap &Opts) {
|
||||
Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
|
||||
Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
|
||||
}
|
||||
|
||||
void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
|
||||
void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
|
||||
// This check doesn't make much sense if we run it on language without
|
||||
// built-in bool support.
|
||||
if (!getLangOpts().Bool) {
|
||||
|
@ -326,7 +323,8 @@ void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
|
|||
this);
|
||||
}
|
||||
|
||||
void ImplicitBoolCastCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
void ImplicitBoolConversionCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
if (const auto *CastToBool =
|
||||
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
|
||||
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,
|
||||
const Stmt *Parent,
|
||||
ASTContext &Context) {
|
||||
if (AllowConditionalPointerCasts &&
|
||||
void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
||||
const Stmt *Parent,
|
||||
ASTContext &Context) {
|
||||
if (AllowPointerConditions &&
|
||||
(Cast->getCastKind() == CK_PointerToBoolean ||
|
||||
Cast->getCastKind() == CK_MemberPointerToBoolean) &&
|
||||
isAllowedConditionalCast(Cast, Context)) {
|
||||
isCastAllowedInCondition(Cast, Context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllowConditionalIntegerCasts &&
|
||||
Cast->getCastKind() == CK_IntegralToBoolean &&
|
||||
isAllowedConditionalCast(Cast, Context)) {
|
||||
if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
|
||||
isCastAllowedInCondition(Cast, Context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto Diag = diag(Cast->getLocStart(), "implicit cast %0 -> bool")
|
||||
auto Diag = diag(Cast->getLocStart(), "implicit conversion %0 -> bool")
|
||||
<< Cast->getSubExpr()->getType();
|
||||
|
||||
StringRef EquivalentLiteral =
|
||||
|
@ -369,12 +366,13 @@ void ImplicitBoolCastCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
|||
}
|
||||
}
|
||||
|
||||
void ImplicitBoolCastCheck::handleCastFromBool(
|
||||
void ImplicitBoolConversionCheck::handleCastFromBool(
|
||||
const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
|
||||
ASTContext &Context) {
|
||||
QualType DestType =
|
||||
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 =
|
||||
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
|
|
@ -1,4 +1,4 @@
|
|||
//===--- ImplicitBoolCastCheck.h - clang-tidy--------------------*- C++ -*-===//
|
||||
//===--- ImplicitBoolConversionCheck.h - clang-tidy--------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -7,8 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
|
||||
#define 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_CONVERSION_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
|
||||
|
@ -16,13 +16,13 @@ namespace clang {
|
|||
namespace tidy {
|
||||
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:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-cast.html
|
||||
class ImplicitBoolCastCheck : public ClangTidyCheck {
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-conversion.html
|
||||
class ImplicitBoolConversionCheck : public ClangTidyCheck {
|
||||
public:
|
||||
ImplicitBoolCastCheck(StringRef Name, ClangTidyContext *Context);
|
||||
ImplicitBoolConversionCheck(StringRef Name, ClangTidyContext *Context);
|
||||
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
||||
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
|
@ -35,12 +35,12 @@ private:
|
|||
const ImplicitCastExpr *FurtherImplicitCastExpression,
|
||||
ASTContext &Context);
|
||||
|
||||
bool AllowConditionalIntegerCasts;
|
||||
bool AllowConditionalPointerCasts;
|
||||
const bool AllowIntegerConditions;
|
||||
const bool AllowPointerConditions;
|
||||
};
|
||||
|
||||
} // namespace readability
|
||||
} // namespace tidy
|
||||
} // 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 "FunctionSizeCheck.h"
|
||||
#include "IdentifierNamingCheck.h"
|
||||
#include "ImplicitBoolCastCheck.h"
|
||||
#include "ImplicitBoolConversionCheck.h"
|
||||
#include "InconsistentDeclarationParameterNameCheck.h"
|
||||
#include "MisleadingIndentationCheck.h"
|
||||
#include "MisplacedArrayIndexCheck.h"
|
||||
|
@ -58,8 +58,8 @@ public:
|
|||
"readability-function-size");
|
||||
CheckFactories.registerCheck<IdentifierNamingCheck>(
|
||||
"readability-identifier-naming");
|
||||
CheckFactories.registerCheck<ImplicitBoolCastCheck>(
|
||||
"readability-implicit-bool-cast");
|
||||
CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
|
||||
"readability-implicit-bool-conversion");
|
||||
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
|
||||
"readability-inconsistent-declaration-parameter-name");
|
||||
CheckFactories.registerCheck<MisleadingIndentationCheck>(
|
||||
|
|
|
@ -57,7 +57,19 @@ The improvements are...
|
|||
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
|
||||
-----------------------------
|
||||
|
|
|
@ -150,7 +150,7 @@ Clang-Tidy Checks
|
|||
mpi-type-mismatch
|
||||
performance-faster-string-find
|
||||
performance-for-range-copy
|
||||
performance-implicit-cast-in-loop
|
||||
performance-implicit-conversion-in-loop
|
||||
performance-inefficient-string-concatenation
|
||||
performance-inefficient-vector-operation
|
||||
performance-type-promotion-in-math-fn
|
||||
|
@ -164,7 +164,7 @@ Clang-Tidy Checks
|
|||
readability-else-after-return
|
||||
readability-function-size
|
||||
readability-identifier-naming
|
||||
readability-implicit-bool-cast
|
||||
readability-implicit-bool-conversion
|
||||
readability-inconsistent-declaration-parameter-name
|
||||
readability-misleading-indentation
|
||||
readability-misplaced-array-index
|
||||
|
|
|
@ -1,21 +1,12 @@
|
|||
:orphan:
|
||||
|
||||
.. 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
|
||||
=================================
|
||||
|
||||
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 cast has been added, which can for example
|
||||
result in expensive deep copies.
|
||||
This check has been renamed to `performance-implicit-conversion-in-loop
|
||||
<performance-implicit-conversion-in-loop.html>`_.
|
||||
|
||||
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
|
||||
.. meta::
|
||||
:http-equiv=refresh: 5;URL=readability-implicit-bool-conversion.html
|
||||
|
||||
readability-implicit-bool-cast
|
||||
==============================
|
||||
|
||||
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`` 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`.
|
||||
This check has been renamed to `readability-implicit-bool-conversion
|
||||
<readability-implicit-bool-conversion.html>`_.
|
||||
|
|
|
@ -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 ----------
|
||||
|
||||
|
@ -26,8 +26,8 @@ struct View {
|
|||
T end();
|
||||
};
|
||||
|
||||
// With this class, the implicit cast is a call to the (implicit) constructor of
|
||||
// the class.
|
||||
// With this class, the implicit conversion is a call to the (implicit)
|
||||
// constructor of the class.
|
||||
template <typename T>
|
||||
class ImplicitWrapper {
|
||||
public:
|
||||
|
@ -35,8 +35,8 @@ class ImplicitWrapper {
|
|||
ImplicitWrapper(const T& t);
|
||||
};
|
||||
|
||||
// With this class, the implicit cast is a call to the conversion operators of
|
||||
// SimpleClass and ComplexClass.
|
||||
// With this class, the implicit conversion is a call to the conversion
|
||||
// operators of SimpleClass and ComplexClass.
|
||||
template <typename T>
|
||||
class OperatorWrapper {
|
||||
public:
|
||||
|
@ -98,7 +98,7 @@ void ComplexClassRefIterator() {
|
|||
|
||||
void ImplicitSimpleClassIterator() {
|
||||
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 (const 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: [{key: readability-implicit-bool-cast.AllowConditionalIntegerCasts, value: 1}, \
|
||||
// RUN: {key: readability-implicit-bool-cast.AllowConditionalPointerCasts, value: 1}]}' \
|
||||
// RUN: [{key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1}, \
|
||||
// RUN: {key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1}]}' \
|
||||
// RUN: -- -std=c++11
|
||||
|
||||
template<typename T>
|
||||
|
@ -15,14 +15,14 @@ struct Struct {
|
|||
};
|
||||
|
||||
|
||||
void regularImplicitCastIntegerToBoolIsNotIgnored() {
|
||||
void regularImplicitConversionIntegerToBoolIsNotIgnored() {
|
||||
int integer = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastIntegerToBoolInConditionalsIsAllowed() {
|
||||
void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
|
||||
if (functionReturningInt()) {}
|
||||
if (!functionReturningInt()) {}
|
||||
if (functionReturningInt() && functionReturningPointer()) {}
|
||||
|
@ -40,19 +40,19 @@ void implicitCastIntegerToBoolInConditionalsIsAllowed() {
|
|||
int *p1 = functionReturningPointer() ?: &value3;
|
||||
}
|
||||
|
||||
void regularImplicitCastPointerToBoolIsNotIgnored() {
|
||||
void regularImplicitConversionPointerToBoolIsNotIgnored() {
|
||||
int* pointer = nullptr;
|
||||
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);
|
||||
|
||||
int Struct::* memberPointer = &Struct::member;
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastPointerToBoolInConditionalsIsAllowed() {
|
||||
void implicitConversionPointerToBoolInConditionalsIsAllowed() {
|
||||
if (functionReturningPointer()) {}
|
||||
if (not functionReturningPointer()) {}
|
||||
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
|
||||
// This is a portable way of getting it to work
|
||||
|
@ -15,31 +15,31 @@ struct Struct {
|
|||
void useOldNullMacroInReplacements() {
|
||||
int* pointer = NULL;
|
||||
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);
|
||||
|
||||
int Struct::* memberPointer = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
void fixFalseLiteralConvertingToNullPointer() {
|
||||
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);
|
||||
|
||||
int* pointer = NULL;
|
||||
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) {}
|
||||
|
||||
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);
|
||||
|
||||
int Struct::* memberPointer = NULL;
|
||||
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) {}
|
||||
}
|
|
@ -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
|
||||
// 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;
|
||||
|
||||
functionTaking<bool>(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));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
float implicitCastFromBoolInReturnValue() {
|
||||
float implicitConversionFromBoolInReturnValue() {
|
||||
bool boolean = false;
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
||||
void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
||||
bool boolean = true;
|
||||
boolean = b1 ^ b2;
|
||||
boolean = b1 && b2;
|
||||
|
@ -58,71 +58,71 @@ void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
|
|||
boolean = b2 != false;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastFromBoollInComplexBoolExpressions() {
|
||||
void implicitConversionFromBoollInComplexBoolExpressions() {
|
||||
bool boolean = true;
|
||||
bool anotherBoolean = false;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void implicitCastFromBoolLiterals() {
|
||||
void implicitConversionFromBoolLiterals() {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastFromBoolInComparisons() {
|
||||
void implicitConversionFromBoolInComparisons() {
|
||||
bool boolean = true;
|
||||
int integer = 0;
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ void ignoreExplicitCastsFromBool() {
|
|||
char character = static_cast<char>(boolean);
|
||||
}
|
||||
|
||||
void ignoreImplicitCastFromBoolInMacroExpansions() {
|
||||
void ignoreImplicitConversionFromBoolInMacroExpansions() {
|
||||
bool boolean = true;
|
||||
|
||||
#define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
|
||||
|
@ -152,7 +152,7 @@ void ignoreImplicitCastFromBoolInMacroExpansions() {
|
|||
int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
|
||||
}
|
||||
|
||||
namespace ignoreImplicitCastFromBoolInTemplateInstantiations {
|
||||
namespace ignoreImplicitConversionFromBoolInTemplateInstantiations {
|
||||
|
||||
template<typename T>
|
||||
void templateFunction() {
|
||||
|
@ -164,204 +164,204 @@ void useOfTemplateFunction() {
|
|||
templateFunction<int>();
|
||||
}
|
||||
|
||||
} // namespace ignoreImplicitCastFromBoolInTemplateInstantiations
|
||||
} // namespace ignoreImplicitConversionFromBoolInTemplateInstantiations
|
||||
|
||||
////////// Implicit cast to bool.
|
||||
////////// Implicit conversions to bool.
|
||||
|
||||
void implicitCastToBoolSimpleCases() {
|
||||
void implicitConversionToBoolSimpleCases() {
|
||||
int integer = 10;
|
||||
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);
|
||||
|
||||
unsigned long unsignedLong = 10;
|
||||
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);
|
||||
|
||||
float floating = 0.0f;
|
||||
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);
|
||||
|
||||
double doubleFloating = 1.0f;
|
||||
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);
|
||||
|
||||
signed char character = 'a';
|
||||
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);
|
||||
|
||||
int* pointer = nullptr;
|
||||
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);
|
||||
|
||||
auto pointerToMember = &Struct::member;
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastToBoolInSingleExpressions() {
|
||||
void implicitConversionToBoolInSingleExpressions() {
|
||||
int integer = 10;
|
||||
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;
|
||||
|
||||
float floating = 10.0f;
|
||||
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;
|
||||
|
||||
signed char character = 'a';
|
||||
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;
|
||||
|
||||
int* pointer = nullptr;
|
||||
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;
|
||||
}
|
||||
|
||||
void implicitCastToBoolInComplexExpressions() {
|
||||
void implicitConversionToBoolInComplexExpressions() {
|
||||
bool boolean = true;
|
||||
|
||||
int integer = 10;
|
||||
int anotherInteger = 20;
|
||||
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;
|
||||
|
||||
float floating = 0.2f;
|
||||
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;
|
||||
|
||||
double doubleFloating = 0.3;
|
||||
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;
|
||||
}
|
||||
|
||||
void implicitCastInNegationExpressions() {
|
||||
void implicitConversionInNegationExpressions() {
|
||||
int integer = 10;
|
||||
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;
|
||||
|
||||
float floating = 10.0f;
|
||||
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;
|
||||
|
||||
signed char character = 'a';
|
||||
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);
|
||||
|
||||
int* pointer = nullptr;
|
||||
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;
|
||||
}
|
||||
|
||||
void implicitCastToBoolInControlStatements() {
|
||||
void implicitConversionToBoolInControlStatements() {
|
||||
int integer = 10;
|
||||
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) {}
|
||||
|
||||
long int longInteger = 0.2f;
|
||||
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;) {}
|
||||
|
||||
float floating = 0.3f;
|
||||
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) {}
|
||||
|
||||
double doubleFloating = 0.4;
|
||||
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);
|
||||
}
|
||||
|
||||
bool implicitCastToBoolInReturnValue() {
|
||||
bool implicitConversionToBoolInReturnValue() {
|
||||
float floating = 1.0f;
|
||||
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;
|
||||
}
|
||||
|
||||
void implicitCastToBoolFromLiterals() {
|
||||
void implicitConversionToBoolFromLiterals() {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastToBoolFromUnaryMinusAndZeroLiterals() {
|
||||
void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void implicitCastToBoolInWithOverloadedOperators() {
|
||||
void implicitConversionToBoolInWithOverloadedOperators() {
|
||||
struct UserStruct {
|
||||
int operator()(int x) { return x; }
|
||||
int operator+(int y) { return y; }
|
||||
|
@ -370,18 +370,18 @@ void implicitCastToBoolInWithOverloadedOperators() {
|
|||
UserStruct s;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int functionReturningInt();
|
||||
int* functionReturningPointer();
|
||||
|
||||
void ignoreImplicitCastToBoolWhenDeclaringVariableInControlStatements() {
|
||||
void ignoreImplicitConversionToBoolWhenDeclaringVariableInControlStatements() {
|
||||
if (int integer = functionReturningInt()) {}
|
||||
|
||||
while (int* pointer = functionReturningPointer()) {}
|
||||
|
@ -401,7 +401,7 @@ void ignoreExplicitCastsToBool() {
|
|||
bool booleanComingFromPointer = static_cast<bool>(pointer);
|
||||
}
|
||||
|
||||
void ignoreImplicitCastToBoolInMacroExpansions() {
|
||||
void ignoreImplicitConversionToBoolInMacroExpansions() {
|
||||
int integer = 3;
|
||||
|
||||
#define CAST_TO_BOOL_IN_MACRO_BODY integer && false
|
||||
|
@ -411,7 +411,7 @@ void ignoreImplicitCastToBoolInMacroExpansions() {
|
|||
bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
|
||||
}
|
||||
|
||||
namespace ignoreImplicitCastToBoolInTemplateInstantiations {
|
||||
namespace ignoreImplicitConversionToBoolInTemplateInstantiations {
|
||||
|
||||
template<typename T>
|
||||
void templateFunction() {
|
||||
|
@ -423,7 +423,7 @@ void useOfTemplateFunction() {
|
|||
templateFunction<int>();
|
||||
}
|
||||
|
||||
} // namespace ignoreImplicitCastToBoolInTemplateInstantiations
|
||||
} // namespace ignoreImplicitConversionToBoolInTemplateInstantiations
|
||||
|
||||
namespace ignoreUserDefinedConversionOperator {
|
||||
|
Loading…
Reference in New Issue