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 analyze_scanf::ScanfConversionSpecifier SCS = FS.getConversionSpecifier();
81 switch (FS.getLengthModifier().getKind()) {
82 case analyze_scanf::LengthModifier::AsLongLong:
83 CK = ConversionKind::ToLongInt;
85 case analyze_scanf::LengthModifier::AsIntMax:
86 CK = ConversionKind::ToIntMax;
89 CK = ConversionKind::ToInt;
92 }
else if (SCS.isUIntArg()) {
93 switch (FS.getLengthModifier().getKind()) {
94 case analyze_scanf::LengthModifier::AsLongLong:
95 CK = ConversionKind::ToLongUInt;
97 case analyze_scanf::LengthModifier::AsIntMax:
98 CK = ConversionKind::ToUIntMax;
101 CK = ConversionKind::ToUInt;
104 }
else if (SCS.isDoubleArg()) {
105 switch (FS.getLengthModifier().getKind()) {
106 case analyze_scanf::LengthModifier::AsLongDouble:
107 CK = ConversionKind::ToLongDouble;
109 case analyze_scanf::LengthModifier::AsLong:
110 CK = ConversionKind::ToDouble;
113 CK = ConversionKind::ToFloat;
119 return CK == ConversionKind::None;
125 ConversionKind get()
const {
return CK; }
129 analyze_format_string::ParseScanfString(H, Fmt.begin(), Fmt.end(), LO, TI);
136 case ConversionKind::None:
137 llvm_unreachable(
"Unexpected conversion kind");
138 case ConversionKind::ToInt:
139 case ConversionKind::ToLongInt:
140 case ConversionKind::ToIntMax:
141 return "an integer value";
142 case ConversionKind::ToUInt:
143 case ConversionKind::ToLongUInt:
144 case ConversionKind::ToUIntMax:
145 return "an unsigned integer value";
146 case ConversionKind::ToFloat:
147 case ConversionKind::ToDouble:
148 case ConversionKind::ToLongDouble:
149 return "a floating-point value";
151 llvm_unreachable(
"Unknown conversion kind");
156 case ConversionKind::None:
157 llvm_unreachable(
"Unexpected conversion kind");
158 case ConversionKind::ToInt:
160 case ConversionKind::ToUInt:
162 case ConversionKind::ToIntMax:
164 case ConversionKind::ToLongInt:
166 case ConversionKind::ToLongUInt:
168 case ConversionKind::ToUIntMax:
170 case ConversionKind::ToFloat:
172 case ConversionKind::ToDouble:
174 case ConversionKind::ToLongDouble:
177 llvm_unreachable(
"Unknown conversion kind");
181 const MatchFinder::MatchResult &Result) {
182 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"expr");
183 const FunctionDecl *
FuncDecl =
nullptr;
184 ConversionKind Conversion = ConversionKind::None;
186 if (
const auto *ConverterFunc =
187 Result.Nodes.getNodeAs<FunctionDecl>(
"converter")) {
191 }
else if (
const auto *FFD =
192 Result.Nodes.getNodeAs<FunctionDecl>(
"formatted")) {
198 (FFD->getName() ==
"scanf" || FFD->getName() ==
"vscanf") ? 0 : 1;
202 if (Call->getNumArgs() < Idx)
205 if (
const Expr *Arg = Call->getArg(Idx)->IgnoreParenImpCasts()) {
206 if (
const auto *SL = dyn_cast<StringLiteral>(Arg)) {
207 FmtStr = SL->getString();
218 Result.Context->getTargetInfo());
219 if (Conversion != ConversionKind::None)
226 diag(Call->getExprLoc(),
227 "%0 used to convert a string to %1, but function will not report "
228 "conversion errors; consider using '%2' instead")