75 const ImplicitCastExpr *Cast,
76 const Stmt *Parent, ASTContext &Context,
77 bool UseUpperCaseLiteralSuffix) {
80 const bool InvertComparison =
82 if (InvertComparison) {
83 const SourceLocation ParentStartLoc = Parent->getBeginLoc();
84 const SourceLocation ParentEndLoc =
85 cast<UnaryOperator>(Parent)->getSubExpr()->getBeginLoc();
86 Diag << FixItHint::CreateRemoval(
87 CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc));
89 Parent = Context.getParents(*Parent)[0].get<Stmt>();
92 const Expr *SubExpr = Cast->getSubExpr();
94 const bool NeedInnerParens =
96 const bool NeedOuterParens =
99 std::string StartLocInsertion;
102 StartLocInsertion +=
"(";
104 StartLocInsertion +=
"(";
106 if (!StartLocInsertion.empty())
107 Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(), StartLocInsertion);
109 std::string EndLocInsertion;
112 EndLocInsertion +=
")";
114 if (InvertComparison)
115 EndLocInsertion +=
" == ";
117 EndLocInsertion +=
" != ";
120 Cast->getCastKind(), SubExpr->getType(), Context);
122 if (UseUpperCaseLiteralSuffix)
123 EndLocInsertion += ZeroLiteral.upper();
125 EndLocInsertion += ZeroLiteral;
128 EndLocInsertion +=
")";
130 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
131 Cast->getEndLoc(), 0, Context.getSourceManager(), Context.getLangOpts());
132 Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
136 ASTContext &Context) {
137 if (isNULLMacroExpansion(Expression, Context))
140 if (
const auto *IntLit = dyn_cast<IntegerLiteral>(Expression->IgnoreParens()))
141 return (IntLit->getValue() == 0) ?
"false" :
"true";
143 if (
const auto *FloatLit = dyn_cast<FloatingLiteral>(Expression)) {
144 llvm::APFloat FloatLitAbsValue = FloatLit->getValue();
145 FloatLitAbsValue.clearSign();
146 return (FloatLitAbsValue.bitcastToAPInt() == 0) ?
"false" :
"true";
149 if (
const auto *CharLit = dyn_cast<CharacterLiteral>(Expression))
150 return (CharLit->getValue() == 0) ?
"false" :
"true";
152 if (isa<StringLiteral>(Expression->IgnoreCasts()))
171 const ImplicitCastExpr *Cast,
173 StringRef OtherType) {
174 if (!Context.getLangOpts().CPlusPlus) {
175 Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(),
176 (Twine(
"(") + OtherType +
")").str());
180 const Expr *SubExpr = Cast->getSubExpr();
181 const bool NeedParens = !isa<ParenExpr>(SubExpr->IgnoreImplicit());
184 Diag << FixItHint::CreateInsertion(
185 Cast->getBeginLoc(), (Twine() + (NeedSpace ?
" " :
"") +
"static_cast<" +
186 OtherType +
">" + (NeedParens ?
"(" :
""))
190 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
191 Cast->getEndLoc(), 0, Context.getSourceManager(),
192 Context.getLangOpts());
194 Diag << FixItHint::CreateInsertion(EndLoc,
")");
200 QualType DestType, ASTContext &Context) {
202 if (!Context.getLangOpts().CPlusPlus11 &&
203 (DestType->isPointerType() || DestType->isMemberPointerType()) &&
204 BoolLiteral->getValue() ==
false) {
208 if (DestType->isFloatingType()) {
209 if (ASTContext::hasSameType(DestType, Context.FloatTy))
210 return BoolLiteral->getValue() ?
"1.0f" :
"0.0f";
211 return BoolLiteral->getValue() ?
"1.0" :
"0.0";
214 if (DestType->isUnsignedIntegerType())
215 return BoolLiteral->getValue() ?
"1u" :
"0u";
216 return BoolLiteral->getValue() ?
"1" :
"0";
264 auto ExceptionCases =
265 expr(anyOf(allOf(isMacroExpansion(), unless(isNULLMacroExpansion())),
266 has(ignoringImplicit(
267 memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))),
268 hasParent(explicitCastExpr()),
269 expr(hasType(qualType().bind(
"type")),
270 hasParent(initListExpr(hasParent(explicitCastExpr(
271 hasType(qualType(equalsBoundNode(
"type"))))))))));
272 auto ImplicitCastFromBool = implicitCastExpr(
273 anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating),
275 allOf(anyOf(hasCastKind(CK_NullToPointer),
276 hasCastKind(CK_NullToMemberPointer)),
277 hasSourceExpression(cxxBoolLiteral()))),
278 hasSourceExpression(expr(hasType(booleanType()))));
280 binaryOperator(hasOperatorName(
"^"), hasLHS(ImplicitCastFromBool),
281 hasRHS(ImplicitCastFromBool));
282 auto ComparisonInCall = allOf(
283 hasParent(callExpr()),
284 hasSourceExpression(binaryOperator(hasAnyOperatorName(
"==",
"!="))));
286 auto IsInCompilerGeneratedFunction = hasAncestor(namedDecl(anyOf(
287 isImplicit(), functionDecl(isDefaulted()), functionTemplateDecl())));
292 anyOf(hasCastKind(CK_IntegralToBoolean),
293 hasCastKind(CK_FloatingToBoolean),
294 hasCastKind(CK_PointerToBoolean),
295 hasCastKind(CK_MemberPointerToBoolean)),
298 hasSourceExpression(ignoringParens(
299 binaryOperator(hasAnyOperatorName(
300 ">",
">=",
"==",
"!=",
"<",
"<=")))))),
305 stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))),
307 unless(ExceptionCases), unless(has(BoolXor)),
309 unless(ComparisonInCall),
312 optionally(hasParent(stmt().bind(
"parentStmt"))),
313 unless(isInTemplateInstantiation()),
314 unless(IsInCompilerGeneratedFunction))
315 .bind(
"implicitCastToBool")),
318 auto BoolComparison = binaryOperator(hasAnyOperatorName(
"==",
"!="),
319 hasLHS(ImplicitCastFromBool),
320 hasRHS(ImplicitCastFromBool));
321 auto BoolOpAssignment = binaryOperator(hasAnyOperatorName(
"|=",
"&="),
322 hasLHS(expr(hasType(booleanType()))));
323 auto BitfieldAssignment = binaryOperator(
324 hasLHS(memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1))))));
325 auto BitfieldConstruct = cxxConstructorDecl(hasDescendant(cxxCtorInitializer(
326 withInitializer(equalsBoundNode(
"implicitCastFromBool")),
327 forField(hasBitWidth(1)))));
332 ImplicitCastFromBool, unless(ExceptionCases),
338 binaryOperator(anyOf(BoolComparison, BoolXor,
339 BoolOpAssignment, BitfieldAssignment)))),
341 unless(allOf(isC(), hasParent(binaryOperator(
342 hasAnyOperatorName(
"&&",
"||"))))),
343 implicitCastExpr().bind(
"implicitCastFromBool"),
344 unless(hasParent(BitfieldConstruct)),
347 hasParent(implicitCastExpr().bind(
"furtherImplicitCast"))),
348 unless(isInTemplateInstantiation()),
349 unless(IsInCompilerGeneratedFunction))),
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.