forked from OSchip/llvm-project
[clang-tidy] Code cleanup, (almost) NFC (*).
(*) Printed types of member pointers don't use elaborated type specifiers (`int struct S::*` -> `int S::*`). llvm-svn: 302160
This commit is contained in:
parent
bde6fa9ca7
commit
cbe8d16da4
|
@ -11,6 +11,7 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Tooling/FixIt.h"
|
||||
#include <queue>
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
@ -32,7 +33,7 @@ bool isNULLMacroExpansion(const Stmt *Statement, ASTContext &Context) {
|
|||
const LangOptions &LO = Context.getLangOpts();
|
||||
SourceLocation Loc = Statement->getLocStart();
|
||||
return SM.isMacroBodyExpansion(Loc) &&
|
||||
clang::Lexer::getImmediateMacroName(Loc, SM, LO) == "NULL";
|
||||
Lexer::getImmediateMacroName(Loc, SM, LO) == "NULL";
|
||||
}
|
||||
|
||||
AST_MATCHER(Stmt, isNULLMacroExpansion) {
|
||||
|
@ -57,17 +58,15 @@ StatementMatcher createImplicitCastFromBoolMatcher() {
|
|||
hasSourceExpression(expr(hasType(qualType(booleanType())))));
|
||||
}
|
||||
|
||||
StringRef
|
||||
getZeroLiteralToCompareWithForGivenType(CastKind CastExpressionKind,
|
||||
QualType CastSubExpressionType,
|
||||
StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
|
||||
QualType Type,
|
||||
ASTContext &Context) {
|
||||
switch (CastExpressionKind) {
|
||||
switch (CastExprKind) {
|
||||
case CK_IntegralToBoolean:
|
||||
return CastSubExpressionType->isUnsignedIntegerType() ? "0u" : "0";
|
||||
return Type->isUnsignedIntegerType() ? "0u" : "0";
|
||||
|
||||
case CK_FloatingToBoolean:
|
||||
return Context.hasSameType(CastSubExpressionType, Context.FloatTy) ? "0.0f"
|
||||
: "0.0";
|
||||
return Context.hasSameType(Type, Context.FloatTy) ? "0.0f" : "0.0";
|
||||
|
||||
case CK_PointerToBoolean:
|
||||
case CK_MemberPointerToBoolean: // Fall-through on purpose.
|
||||
|
@ -79,10 +78,8 @@ getZeroLiteralToCompareWithForGivenType(CastKind CastExpressionKind,
|
|||
}
|
||||
|
||||
bool isUnaryLogicalNotOperator(const Stmt *Statement) {
|
||||
const auto *UnaryOperatorExpression =
|
||||
llvm::dyn_cast<UnaryOperator>(Statement);
|
||||
return UnaryOperatorExpression != nullptr &&
|
||||
UnaryOperatorExpression->getOpcode() == UO_LNot;
|
||||
const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
|
||||
return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
|
||||
}
|
||||
|
||||
bool areParensNeededForOverloadedOperator(OverloadedOperatorKind OperatorKind) {
|
||||
|
@ -103,39 +100,35 @@ bool areParensNeededForOverloadedOperator(OverloadedOperatorKind OperatorKind) {
|
|||
}
|
||||
|
||||
bool areParensNeededForStatement(const Stmt *Statement) {
|
||||
if (const auto *OverloadedOperatorCall =
|
||||
llvm::dyn_cast<CXXOperatorCallExpr>(Statement)) {
|
||||
return areParensNeededForOverloadedOperator(
|
||||
OverloadedOperatorCall->getOperator());
|
||||
if (const auto *OperatorCall = dyn_cast<CXXOperatorCallExpr>(Statement)) {
|
||||
return areParensNeededForOverloadedOperator(OperatorCall->getOperator());
|
||||
}
|
||||
|
||||
return llvm::isa<BinaryOperator>(Statement) ||
|
||||
llvm::isa<UnaryOperator>(Statement);
|
||||
return isa<BinaryOperator>(Statement) || isa<UnaryOperator>(Statement);
|
||||
}
|
||||
|
||||
void addFixItHintsForGenericExpressionCastToBool(
|
||||
DiagnosticBuilder &Diagnostic, const ImplicitCastExpr *CastExpression,
|
||||
const Stmt *ParentStatement, ASTContext &Context) {
|
||||
void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
|
||||
const ImplicitCastExpr *Cast, const Stmt *Parent,
|
||||
ASTContext &Context) {
|
||||
// In case of expressions like (! integer), we should remove the redundant not
|
||||
// operator and use inverted comparison (integer == 0).
|
||||
bool InvertComparison =
|
||||
ParentStatement != nullptr && isUnaryLogicalNotOperator(ParentStatement);
|
||||
Parent != nullptr && isUnaryLogicalNotOperator(Parent);
|
||||
if (InvertComparison) {
|
||||
SourceLocation ParentStartLoc = ParentStatement->getLocStart();
|
||||
SourceLocation ParentStartLoc = Parent->getLocStart();
|
||||
SourceLocation ParentEndLoc =
|
||||
llvm::cast<UnaryOperator>(ParentStatement)->getSubExpr()->getLocStart();
|
||||
Diagnostic.AddFixItHint(FixItHint::CreateRemoval(
|
||||
CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc)));
|
||||
cast<UnaryOperator>(Parent)->getSubExpr()->getLocStart();
|
||||
Diag << FixItHint::CreateRemoval(
|
||||
CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc));
|
||||
|
||||
auto FurtherParents = Context.getParents(*ParentStatement);
|
||||
ParentStatement = FurtherParents[0].get<Stmt>();
|
||||
Parent = Context.getParents(*Parent)[0].get<Stmt>();
|
||||
}
|
||||
|
||||
const Expr *SubExpression = CastExpression->getSubExpr();
|
||||
const Expr *SubExpr = Cast->getSubExpr();
|
||||
|
||||
bool NeedInnerParens = areParensNeededForStatement(SubExpression);
|
||||
bool NeedOuterParens = ParentStatement != nullptr &&
|
||||
areParensNeededForStatement(ParentStatement);
|
||||
bool NeedInnerParens = areParensNeededForStatement(SubExpr);
|
||||
bool NeedOuterParens =
|
||||
Parent != nullptr && areParensNeededForStatement(Parent);
|
||||
|
||||
std::string StartLocInsertion;
|
||||
|
||||
|
@ -147,9 +140,7 @@ void addFixItHintsForGenericExpressionCastToBool(
|
|||
}
|
||||
|
||||
if (!StartLocInsertion.empty()) {
|
||||
SourceLocation StartLoc = CastExpression->getLocStart();
|
||||
Diagnostic.AddFixItHint(
|
||||
FixItHint::CreateInsertion(StartLoc, StartLocInsertion));
|
||||
Diag << FixItHint::CreateInsertion(Cast->getLocStart(), StartLocInsertion);
|
||||
}
|
||||
|
||||
std::string EndLocInsertion;
|
||||
|
@ -164,128 +155,91 @@ void addFixItHintsForGenericExpressionCastToBool(
|
|||
EndLocInsertion += " != ";
|
||||
}
|
||||
|
||||
EndLocInsertion += getZeroLiteralToCompareWithForGivenType(
|
||||
CastExpression->getCastKind(), SubExpression->getType(), Context);
|
||||
EndLocInsertion += getZeroLiteralToCompareWithForType(
|
||||
Cast->getCastKind(), SubExpr->getType(), Context);
|
||||
|
||||
if (NeedOuterParens) {
|
||||
EndLocInsertion += ")";
|
||||
}
|
||||
|
||||
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
|
||||
CastExpression->getLocEnd(), 0, Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
Diagnostic.AddFixItHint(FixItHint::CreateInsertion(EndLoc, EndLocInsertion));
|
||||
Cast->getLocEnd(), 0, Context.getSourceManager(), Context.getLangOpts());
|
||||
Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
|
||||
}
|
||||
|
||||
StringRef getEquivalentBoolLiteralForExpression(const Expr *Expression,
|
||||
StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
|
||||
ASTContext &Context) {
|
||||
if (isNULLMacroExpansion(Expression, Context)) {
|
||||
return "false";
|
||||
}
|
||||
|
||||
if (const auto *IntLit = llvm::dyn_cast<IntegerLiteral>(Expression)) {
|
||||
if (const auto *IntLit = dyn_cast<IntegerLiteral>(Expression)) {
|
||||
return (IntLit->getValue() == 0) ? "false" : "true";
|
||||
}
|
||||
|
||||
if (const auto *FloatLit = llvm::dyn_cast<FloatingLiteral>(Expression)) {
|
||||
if (const auto *FloatLit = dyn_cast<FloatingLiteral>(Expression)) {
|
||||
llvm::APFloat FloatLitAbsValue = FloatLit->getValue();
|
||||
FloatLitAbsValue.clearSign();
|
||||
return (FloatLitAbsValue.bitcastToAPInt() == 0) ? "false" : "true";
|
||||
}
|
||||
|
||||
if (const auto *CharLit = llvm::dyn_cast<CharacterLiteral>(Expression)) {
|
||||
if (const auto *CharLit = dyn_cast<CharacterLiteral>(Expression)) {
|
||||
return (CharLit->getValue() == 0) ? "false" : "true";
|
||||
}
|
||||
|
||||
if (llvm::isa<StringLiteral>(Expression->IgnoreCasts())) {
|
||||
if (isa<StringLiteral>(Expression->IgnoreCasts())) {
|
||||
return "true";
|
||||
}
|
||||
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
void addFixItHintsForLiteralCastToBool(DiagnosticBuilder &Diagnostic,
|
||||
const ImplicitCastExpr *CastExpression,
|
||||
StringRef EquivalentLiteralExpression) {
|
||||
SourceLocation StartLoc = CastExpression->getLocStart();
|
||||
SourceLocation EndLoc = CastExpression->getLocEnd();
|
||||
|
||||
Diagnostic.AddFixItHint(FixItHint::CreateReplacement(
|
||||
CharSourceRange::getTokenRange(StartLoc, EndLoc),
|
||||
EquivalentLiteralExpression));
|
||||
}
|
||||
|
||||
void addFixItHintsForGenericExpressionCastFromBool(
|
||||
DiagnosticBuilder &Diagnostic, const ImplicitCastExpr *CastExpression,
|
||||
void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
|
||||
const ImplicitCastExpr *Cast,
|
||||
ASTContext &Context, StringRef OtherType) {
|
||||
const Expr *SubExpression = CastExpression->getSubExpr();
|
||||
bool NeedParens = !llvm::isa<ParenExpr>(SubExpression);
|
||||
const Expr *SubExpr = Cast->getSubExpr();
|
||||
bool NeedParens = !isa<ParenExpr>(SubExpr);
|
||||
|
||||
std::string StartLocInsertion = "static_cast<";
|
||||
StartLocInsertion += OtherType.str();
|
||||
StartLocInsertion += ">";
|
||||
if (NeedParens) {
|
||||
StartLocInsertion += "(";
|
||||
}
|
||||
|
||||
SourceLocation StartLoc = CastExpression->getLocStart();
|
||||
Diagnostic.AddFixItHint(
|
||||
FixItHint::CreateInsertion(StartLoc, StartLocInsertion));
|
||||
Diag << FixItHint::CreateInsertion(
|
||||
Cast->getLocStart(),
|
||||
(Twine("static_cast<") + OtherType + ">" + (NeedParens ? "(" : ""))
|
||||
.str());
|
||||
|
||||
if (NeedParens) {
|
||||
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
|
||||
CastExpression->getLocEnd(), 0, Context.getSourceManager(),
|
||||
Cast->getLocEnd(), 0, Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
|
||||
Diagnostic.AddFixItHint(FixItHint::CreateInsertion(EndLoc, ")"));
|
||||
Diag << FixItHint::CreateInsertion(EndLoc, ")");
|
||||
}
|
||||
}
|
||||
|
||||
StringRef getEquivalentLiteralForBoolLiteral(
|
||||
const CXXBoolLiteralExpr *BoolLiteralExpression, QualType DestinationType,
|
||||
ASTContext &Context) {
|
||||
StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
|
||||
QualType DestType, ASTContext &Context) {
|
||||
// Prior to C++11, false literal could be implicitly converted to pointer.
|
||||
if (!Context.getLangOpts().CPlusPlus11 &&
|
||||
(DestinationType->isPointerType() ||
|
||||
DestinationType->isMemberPointerType()) &&
|
||||
BoolLiteralExpression->getValue() == false) {
|
||||
(DestType->isPointerType() || DestType->isMemberPointerType()) &&
|
||||
BoolLiteral->getValue() == false) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
if (DestinationType->isFloatingType()) {
|
||||
if (BoolLiteralExpression->getValue() == true) {
|
||||
return Context.hasSameType(DestinationType, Context.FloatTy) ? "1.0f"
|
||||
: "1.0";
|
||||
if (DestType->isFloatingType()) {
|
||||
if (Context.hasSameType(DestType, Context.FloatTy)) {
|
||||
return BoolLiteral->getValue() ? "1.0f" : "0.0f";
|
||||
}
|
||||
return Context.hasSameType(DestinationType, Context.FloatTy) ? "0.0f"
|
||||
: "0.0";
|
||||
return BoolLiteral->getValue() ? "1.0" : "0.0";
|
||||
}
|
||||
|
||||
if (BoolLiteralExpression->getValue() == true) {
|
||||
return DestinationType->isUnsignedIntegerType() ? "1u" : "1";
|
||||
if (DestType->isUnsignedIntegerType()) {
|
||||
return BoolLiteral->getValue() ? "1u" : "0u";
|
||||
}
|
||||
return DestinationType->isUnsignedIntegerType() ? "0u" : "0";
|
||||
return BoolLiteral->getValue() ? "1" : "0";
|
||||
}
|
||||
|
||||
void addFixItHintsForLiteralCastFromBool(DiagnosticBuilder &Diagnostic,
|
||||
const ImplicitCastExpr *CastExpression,
|
||||
ASTContext &Context,
|
||||
QualType DestinationType) {
|
||||
SourceLocation StartLoc = CastExpression->getLocStart();
|
||||
SourceLocation EndLoc = CastExpression->getLocEnd();
|
||||
const auto *BoolLiteralExpression =
|
||||
llvm::dyn_cast<CXXBoolLiteralExpr>(CastExpression->getSubExpr());
|
||||
|
||||
Diagnostic.AddFixItHint(FixItHint::CreateReplacement(
|
||||
CharSourceRange::getTokenRange(StartLoc, EndLoc),
|
||||
getEquivalentLiteralForBoolLiteral(BoolLiteralExpression, DestinationType,
|
||||
Context)));
|
||||
}
|
||||
|
||||
bool isAllowedConditionalCast(const ImplicitCastExpr *CastExpression,
|
||||
bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
|
||||
ASTContext &Context) {
|
||||
std::queue<const Stmt *> Q;
|
||||
Q.push(CastExpression);
|
||||
Q.push(Cast);
|
||||
while (!Q.empty()) {
|
||||
for (const auto &N : Context.getParents(*Q.front())) {
|
||||
const Stmt *S = N.get<Stmt>();
|
||||
|
@ -294,8 +248,7 @@ bool isAllowedConditionalCast(const ImplicitCastExpr *CastExpression,
|
|||
if (isa<IfStmt>(S) || isa<ConditionalOperator>(S))
|
||||
return true;
|
||||
if (isa<ParenExpr>(S) || isa<ImplicitCastExpr>(S) ||
|
||||
(isa<UnaryOperator>(S) &&
|
||||
cast<UnaryOperator>(S)->getOpcode() == UO_LNot) ||
|
||||
isUnaryLogicalNotOperator(S) ||
|
||||
(isa<BinaryOperator>(S) && cast<BinaryOperator>(S)->isLogicalOp())) {
|
||||
Q.push(S);
|
||||
} else {
|
||||
|
@ -371,69 +324,59 @@ void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
|
|||
void ImplicitBoolCastCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
if (const auto *CastToBool =
|
||||
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
|
||||
const auto *ParentStatement = Result.Nodes.getNodeAs<Stmt>("parentStmt");
|
||||
return handleCastToBool(CastToBool, ParentStatement, *Result.Context);
|
||||
const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
|
||||
return handleCastToBool(CastToBool, Parent, *Result.Context);
|
||||
}
|
||||
|
||||
if (const auto *CastFromBool =
|
||||
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastFromBool")) {
|
||||
const auto *FurtherImplicitCastExpression =
|
||||
const auto *NextImplicitCast =
|
||||
Result.Nodes.getNodeAs<ImplicitCastExpr>("furtherImplicitCast");
|
||||
return handleCastFromBool(CastFromBool, FurtherImplicitCastExpression,
|
||||
*Result.Context);
|
||||
return handleCastFromBool(CastFromBool, NextImplicitCast, *Result.Context);
|
||||
}
|
||||
}
|
||||
|
||||
void ImplicitBoolCastCheck::handleCastToBool(
|
||||
const ImplicitCastExpr *CastExpression, const Stmt *ParentStatement,
|
||||
void ImplicitBoolCastCheck::handleCastToBool(const ImplicitCastExpr *Cast,
|
||||
const Stmt *Parent,
|
||||
ASTContext &Context) {
|
||||
if (AllowConditionalPointerCasts &&
|
||||
(CastExpression->getCastKind() == CK_PointerToBoolean ||
|
||||
CastExpression->getCastKind() == CK_MemberPointerToBoolean) &&
|
||||
isAllowedConditionalCast(CastExpression, Context)) {
|
||||
(Cast->getCastKind() == CK_PointerToBoolean ||
|
||||
Cast->getCastKind() == CK_MemberPointerToBoolean) &&
|
||||
isAllowedConditionalCast(Cast, Context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllowConditionalIntegerCasts &&
|
||||
CastExpression->getCastKind() == CK_IntegralToBoolean &&
|
||||
isAllowedConditionalCast(CastExpression, Context)) {
|
||||
Cast->getCastKind() == CK_IntegralToBoolean &&
|
||||
isAllowedConditionalCast(Cast, Context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string OtherType = CastExpression->getSubExpr()->getType().getAsString();
|
||||
DiagnosticBuilder Diagnostic =
|
||||
diag(CastExpression->getLocStart(), "implicit cast '%0' -> bool")
|
||||
<< OtherType;
|
||||
auto Diag = diag(Cast->getLocStart(), "implicit cast %0 -> bool")
|
||||
<< Cast->getSubExpr()->getType();
|
||||
|
||||
StringRef EquivalentLiteralExpression = getEquivalentBoolLiteralForExpression(
|
||||
CastExpression->getSubExpr(), Context);
|
||||
if (!EquivalentLiteralExpression.empty()) {
|
||||
addFixItHintsForLiteralCastToBool(Diagnostic, CastExpression,
|
||||
EquivalentLiteralExpression);
|
||||
StringRef EquivalentLiteral =
|
||||
getEquivalentBoolLiteralForExpr(Cast->getSubExpr(), Context);
|
||||
if (!EquivalentLiteral.empty()) {
|
||||
Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
|
||||
} else {
|
||||
addFixItHintsForGenericExpressionCastToBool(Diagnostic, CastExpression,
|
||||
ParentStatement, Context);
|
||||
fixGenericExprCastToBool(Diag, Cast, Parent, Context);
|
||||
}
|
||||
}
|
||||
|
||||
void ImplicitBoolCastCheck::handleCastFromBool(
|
||||
const ImplicitCastExpr *CastExpression,
|
||||
const ImplicitCastExpr *FurtherImplicitCastExpression,
|
||||
const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
|
||||
ASTContext &Context) {
|
||||
QualType DestinationType = (FurtherImplicitCastExpression != nullptr)
|
||||
? FurtherImplicitCastExpression->getType()
|
||||
: CastExpression->getType();
|
||||
std::string DestinationTypeString = DestinationType.getAsString();
|
||||
DiagnosticBuilder Diagnostic =
|
||||
diag(CastExpression->getLocStart(), "implicit cast bool -> '%0'")
|
||||
<< DestinationTypeString;
|
||||
QualType DestType =
|
||||
NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
|
||||
auto Diag = diag(Cast->getLocStart(), "implicit cast bool -> %0") << DestType;
|
||||
|
||||
if (llvm::isa<CXXBoolLiteralExpr>(CastExpression->getSubExpr())) {
|
||||
addFixItHintsForLiteralCastFromBool(Diagnostic, CastExpression, Context,
|
||||
DestinationType);
|
||||
if (const auto *BoolLiteral =
|
||||
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
|
||||
Diag << tooling::fixit::createReplacement(
|
||||
*Cast, getEquivalentForBoolLiteral(BoolLiteral, DestType, Context));
|
||||
} else {
|
||||
addFixItHintsForGenericExpressionCastFromBool(
|
||||
Diagnostic, CastExpression, Context, DestinationTypeString);
|
||||
fixGenericExprCastFromBool(Diag, Cast, Context, DestType.getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void regularImplicitCastPointerToBoolIsNotIgnored() {
|
|||
|
||||
int Struct::* memberPointer = &Struct::member;
|
||||
functionTaking<bool>(memberPointer);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int struct Struct::*' -> bool
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
|
||||
// CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ void useOldNullMacroInReplacements() {
|
|||
|
||||
int Struct::* memberPointer = NULL;
|
||||
functionTaking<bool>(!memberPointer);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast 'int struct Struct::*' -> bool
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast 'int Struct::*' -> bool
|
||||
// CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,11 @@ void fixFalseLiteralConvertingToNullPointer() {
|
|||
// CHECK-FIXES: if (pointer == 0) {}
|
||||
|
||||
functionTaking<int Struct::*>(false);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'int struct Struct::*'
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast 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 Struct::*'
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int Struct::*'
|
||||
// CHECK-FIXES: if (memberPointer != 0) {}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ void implicitCastToBoolSimpleCases() {
|
|||
|
||||
auto pointerToMember = &Struct::member;
|
||||
functionTaking<bool>(pointerToMember);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int struct Struct::*' -> bool
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
|
||||
// CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue