24 functionDecl(hasName(
"::memset"), parameterCountIs(3),
25 hasParameter(0, hasType(pointerType(pointee(voidType())))),
26 hasParameter(1, hasType(isInteger())),
27 hasParameter(2, hasType(isInteger())));
32 callee(MemsetDecl), argumentCountIs(3),
33 hasArgument(1, characterLiteral(equals(
static_cast<unsigned>(
'0')))
34 .bind(
"char-zero-fill")),
36 0, anyOf(hasType(pointsTo(isAnyCharacter())),
37 hasType(arrayType(hasElementType(isAnyCharacter()))))))),
43 callExpr(callee(MemsetDecl), argumentCountIs(3),
44 hasArgument(1, integerLiteral().bind(
"num-fill"))),
49 callExpr(callee(MemsetDecl), argumentCountIs(3),
50 unless(hasArgument(1, anyOf(characterLiteral(equals(
51 static_cast<unsigned>(
'0'))),
58 if (
const auto *CharZeroFill =
59 Result.Nodes.getNodeAs<CharacterLiteral>(
"char-zero-fill")) {
63 const SourceRange CharRange = CharZeroFill->getSourceRange();
65 diag(CharZeroFill->getBeginLoc(),
"memset fill value is char '0', "
66 "potentially mistaken for int 0");
69 if (CharRange.getBegin().isMacroID())
71 Diag << FixItHint::CreateReplacement(
72 CharSourceRange::getTokenRange(CharRange),
"0");
73 }
else if (
const auto *NumFill =
74 Result.Nodes.getNodeAs<IntegerLiteral>(
"num-fill")) {
78 const auto UCharMax = (1 << Result.Context->getCharWidth()) - 1;
79 Expr::EvalResult EVResult;
80 if (!NumFill->EvaluateAsInt(EVResult, *Result.Context))
83 const llvm::APSInt NumValue = EVResult.Val.getInt();
84 if (NumValue >= 0 && NumValue <= UCharMax)
87 diag(NumFill->getBeginLoc(),
"memset fill value is out of unsigned "
88 "character range, gets truncated");
89 }
else if (
const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call")) {
93 const Expr *FillChar = Call->getArg(1);
94 const Expr *ByteCount = Call->getArg(2);
97 Expr::EvalResult Value2;
98 if (ByteCount->isValueDependent() ||
99 !ByteCount->EvaluateAsInt(Value2, *Result.Context) ||
100 Value2.Val.getInt() != 0)
106 Expr::EvalResult EVResult;
107 if (!FillChar->isValueDependent() &&
108 FillChar->EvaluateAsInt(EVResult, *Result.Context)) {
109 const llvm::APSInt Value1 = EVResult.Val.getInt();
110 if (Value1 == 0 || Value1.isNegative())
117 auto D = diag(Call->getBeginLoc(),
118 "memset of size zero, potentially swapped arguments");
119 const StringRef RHSString =
120 tooling::fixit::getText(*ByteCount, *Result.Context);
121 const StringRef LHSString =
122 tooling::fixit::getText(*FillChar, *Result.Context);
123 if (LHSString.empty() || RHSString.empty())
126 D << tooling::fixit::createReplacement(*FillChar, RHSString)
127 << tooling::fixit::createReplacement(*ByteCount, LHSString);