53 return llvm::StringSwitch<ConversionKind>(FD->getName())
54 .Cases({
"atoi",
"atol"}, ConversionKind::ToInt)
55 .Case(
"atoll", ConversionKind::ToLongInt)
56 .Case(
"atof", ConversionKind::ToDouble)
57 .Default(ConversionKind::None);
61 const TargetInfo &TI) {
67 ConversionKind CK = ConversionKind::None;
69 bool HandleScanfSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
70 const char *StartSpecifier,
71 unsigned SpecifierLen)
override {
74 if (!FS.consumesDataArgument())
79 const analyze_scanf::ScanfConversionSpecifier SCS =
80 FS.getConversionSpecifier();
82 switch (FS.getLengthModifier().getKind()) {
83 case analyze_scanf::LengthModifier::AsLongLong:
84 CK = ConversionKind::ToLongInt;
86 case analyze_scanf::LengthModifier::AsIntMax:
87 CK = ConversionKind::ToIntMax;
90 CK = ConversionKind::ToInt;
93 }
else if (SCS.isUIntArg()) {
94 switch (FS.getLengthModifier().getKind()) {
95 case analyze_scanf::LengthModifier::AsLongLong:
96 CK = ConversionKind::ToLongUInt;
98 case analyze_scanf::LengthModifier::AsIntMax:
99 CK = ConversionKind::ToUIntMax;
102 CK = ConversionKind::ToUInt;
105 }
else if (SCS.isDoubleArg()) {
106 switch (FS.getLengthModifier().getKind()) {
107 case analyze_scanf::LengthModifier::AsLongDouble:
108 CK = ConversionKind::ToLongDouble;
110 case analyze_scanf::LengthModifier::AsLong:
111 CK = ConversionKind::ToDouble;
114 CK = ConversionKind::ToFloat;
120 return CK == ConversionKind::None;
126 ConversionKind get()
const {
return CK; }
130 analyze_format_string::ParseScanfString(H, Fmt.begin(), Fmt.end(), LO, TI);
137 case ConversionKind::None:
138 llvm_unreachable(
"Unexpected conversion kind");
139 case ConversionKind::ToInt:
140 case ConversionKind::ToLongInt:
141 case ConversionKind::ToIntMax:
142 return "an integer value";
143 case ConversionKind::ToUInt:
144 case ConversionKind::ToLongUInt:
145 case ConversionKind::ToUIntMax:
146 return "an unsigned integer value";
147 case ConversionKind::ToFloat:
148 case ConversionKind::ToDouble:
149 case ConversionKind::ToLongDouble:
150 return "a floating-point value";
152 llvm_unreachable(
"Unknown conversion kind");
157 case ConversionKind::None:
158 llvm_unreachable(
"Unexpected conversion kind");
159 case ConversionKind::ToInt:
161 case ConversionKind::ToUInt:
163 case ConversionKind::ToIntMax:
165 case ConversionKind::ToLongInt:
167 case ConversionKind::ToLongUInt:
169 case ConversionKind::ToUIntMax:
171 case ConversionKind::ToFloat:
173 case ConversionKind::ToDouble:
175 case ConversionKind::ToLongDouble:
178 llvm_unreachable(
"Unknown conversion kind");
182 const MatchFinder::MatchResult &Result) {
183 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"expr");
184 const FunctionDecl *
FuncDecl =
nullptr;
185 ConversionKind Conversion = ConversionKind::None;
187 if (
const auto *ConverterFunc =
188 Result.Nodes.getNodeAs<FunctionDecl>(
"converter")) {
192 }
else if (
const auto *FFD =
193 Result.Nodes.getNodeAs<FunctionDecl>(
"formatted")) {
199 (FFD->getName() ==
"scanf" || FFD->getName() ==
"vscanf") ? 0 : 1;
203 if (Call->getNumArgs() < Idx)
206 if (
const Expr *Arg = Call->getArg(Idx)->IgnoreParenImpCasts()) {
207 if (
const auto *SL = dyn_cast<StringLiteral>(Arg)) {
208 FmtStr = SL->getString();
219 Result.Context->getTargetInfo());
220 if (Conversion != ConversionKind::None)
227 diag(Call->getExprLoc(),
228 "%0 used to convert a string to %1, but function will not report "
229 "conversion errors; consider using '%2' instead")