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 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");
75 else if (
const auto *NumFill =
76 Result.Nodes.getNodeAs<IntegerLiteral>(
"num-fill")) {
80 const auto UCharMax = (1 << Result.Context->getCharWidth()) - 1;
81 Expr::EvalResult EVResult;
82 if (!NumFill->EvaluateAsInt(EVResult, *Result.Context))
85 llvm::APSInt NumValue = EVResult.Val.getInt();
86 if (NumValue >= 0 && NumValue <= UCharMax)
89 diag(NumFill->getBeginLoc(),
"memset fill value is out of unsigned "
90 "character range, gets truncated");
93 else if (
const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"call")) {
97 const Expr *FillChar = Call->getArg(1);
98 const Expr *ByteCount = Call->getArg(2);
101 Expr::EvalResult Value2;
102 if (ByteCount->isValueDependent() ||
103 !ByteCount->EvaluateAsInt(Value2, *Result.Context) ||
104 Value2.Val.getInt() != 0)
110 Expr::EvalResult EVResult;
111 if (!FillChar->isValueDependent() &&
112 FillChar->EvaluateAsInt(EVResult, *Result.Context)) {
113 llvm::APSInt Value1 = EVResult.Val.getInt();
114 if (Value1 == 0 || Value1.isNegative())
121 auto D = diag(Call->getBeginLoc(),
122 "memset of size zero, potentially swapped arguments");
123 StringRef RHSString = tooling::fixit::getText(*ByteCount, *Result.Context);
124 StringRef LHSString = tooling::fixit::getText(*FillChar, *Result.Context);
125 if (LHSString.empty() || RHSString.empty())
128 D << tooling::fixit::createReplacement(*FillChar, RHSString)
129 << tooling::fixit::createReplacement(*ByteCount, LHSString);