blob: 3ff7f0ad2e56a259cf67ba4c533f08f851f14a07 [file] [log] [blame]
Ted Kremenekd9c904d2010-07-16 02:11:31 +00001//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Handling of format string in scanf and friends. The structure of format
11// strings for fscanf() are described in C99 7.19.6.2.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/Analyses/FormatString.h"
16#include "FormatStringParsing.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000017#include "clang/Basic/TargetInfo.h"
Ted Kremenekd9c904d2010-07-16 02:11:31 +000018
Hans Wennborgf3749f42012-08-07 08:11:26 +000019using clang::analyze_format_string::ArgType;
Ted Kremenekd9c904d2010-07-16 02:11:31 +000020using clang::analyze_format_string::FormatStringHandler;
21using clang::analyze_format_string::LengthModifier;
22using clang::analyze_format_string::OptionalAmount;
Ted Kremenek1e51c202010-07-20 20:04:47 +000023using clang::analyze_format_string::ConversionSpecifier;
Ted Kremenek6ecb9502010-07-20 20:04:27 +000024using clang::analyze_scanf::ScanfConversionSpecifier;
Ted Kremenekd9c904d2010-07-16 02:11:31 +000025using clang::analyze_scanf::ScanfSpecifier;
Dan Gohman3c46e8d2010-07-26 21:25:24 +000026using clang::UpdateOnReturn;
Hans Wennborg6fcd9322011-12-10 13:20:11 +000027using namespace clang;
Ted Kremenekd9c904d2010-07-16 02:11:31 +000028
29typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
30 ScanfSpecifierResult;
31
32static bool ParseScanList(FormatStringHandler &H,
Ted Kremenek6ecb9502010-07-20 20:04:27 +000033 ScanfConversionSpecifier &CS,
Ted Kremenekd9c904d2010-07-16 02:11:31 +000034 const char *&Beg, const char *E) {
35 const char *I = Beg;
36 const char *start = I - 1;
37 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
38
39 // No more characters?
40 if (I == E) {
41 H.HandleIncompleteScanList(start, I);
42 return true;
43 }
44
45 // Special case: ']' is the first character.
46 if (*I == ']') {
47 if (++I == E) {
Ted Kremenekb7c21012010-07-16 18:28:03 +000048 H.HandleIncompleteScanList(start, I - 1);
Ted Kremenekd9c904d2010-07-16 02:11:31 +000049 return true;
50 }
51 }
52
53 // Look for a ']' character which denotes the end of the scan list.
54 while (*I != ']') {
55 if (++I == E) {
Ted Kremenekb7c21012010-07-16 18:28:03 +000056 H.HandleIncompleteScanList(start, I - 1);
Ted Kremenekd9c904d2010-07-16 02:11:31 +000057 return true;
58 }
59 }
60
61 CS.setEndScanList(I);
62 return false;
63}
64
65// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
66// We can possibly refactor.
67static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
68 const char *&Beg,
69 const char *E,
Hans Wennborgd02deeb2011-12-15 10:25:47 +000070 unsigned &argIndex,
Jordan Rose275b6f52012-09-13 02:11:03 +000071 const LangOptions &LO,
72 const TargetInfo &Target) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +000073
74 using namespace clang::analyze_scanf;
75 const char *I = Beg;
76 const char *Start = 0;
77 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
78
79 // Look for a '%' character that indicates the start of a format specifier.
80 for ( ; I != E ; ++I) {
81 char c = *I;
82 if (c == '\0') {
83 // Detect spurious null characters, which are likely errors.
84 H.HandleNullChar(I);
85 return true;
86 }
87 if (c == '%') {
88 Start = I++; // Record the start of the format specifier.
89 break;
90 }
91 }
92
93 // No format specifier found?
94 if (!Start)
95 return false;
96
97 if (I == E) {
98 // No more characters left?
99 H.HandleIncompleteSpecifier(Start, E - Start);
100 return true;
101 }
102
103 ScanfSpecifier FS;
104 if (ParseArgPosition(H, FS, Start, I, E))
105 return true;
106
107 if (I == E) {
108 // No more characters left?
109 H.HandleIncompleteSpecifier(Start, E - Start);
110 return true;
111 }
112
113 // Look for '*' flag if it is present.
114 if (*I == '*') {
115 FS.setSuppressAssignment(I);
116 if (++I == E) {
117 H.HandleIncompleteSpecifier(Start, E - Start);
118 return true;
119 }
120 }
121
122 // Look for the field width (if any). Unlike printf, this is either
123 // a fixed integer or isn't present.
124 const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
125 if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
126 assert(Amt.getHowSpecified() == OptionalAmount::Constant);
127 FS.setFieldWidth(Amt);
128
129 if (I == E) {
130 // No more characters left?
131 H.HandleIncompleteSpecifier(Start, E - Start);
132 return true;
133 }
134 }
135
136 // Look for the length modifier.
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000137 if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000138 // No more characters left?
139 H.HandleIncompleteSpecifier(Start, E - Start);
140 return true;
141 }
142
143 // Detect spurious null characters, which are likely errors.
144 if (*I == '\0') {
145 H.HandleNullChar(I);
146 return true;
147 }
148
149 // Finally, look for the conversion specifier.
150 const char *conversionPosition = I++;
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000151 ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000152 switch (*conversionPosition) {
153 default:
154 break;
Ted Kremenek1e51c202010-07-20 20:04:47 +0000155 case '%': k = ConversionSpecifier::PercentArg; break;
156 case 'A': k = ConversionSpecifier::AArg; break;
157 case 'E': k = ConversionSpecifier::EArg; break;
158 case 'F': k = ConversionSpecifier::FArg; break;
159 case 'G': k = ConversionSpecifier::GArg; break;
160 case 'X': k = ConversionSpecifier::XArg; break;
161 case 'a': k = ConversionSpecifier::aArg; break;
162 case 'd': k = ConversionSpecifier::dArg; break;
163 case 'e': k = ConversionSpecifier::eArg; break;
164 case 'f': k = ConversionSpecifier::fArg; break;
165 case 'g': k = ConversionSpecifier::gArg; break;
166 case 'i': k = ConversionSpecifier::iArg; break;
167 case 'n': k = ConversionSpecifier::nArg; break;
168 case 'c': k = ConversionSpecifier::cArg; break;
169 case 'C': k = ConversionSpecifier::CArg; break;
170 case 'S': k = ConversionSpecifier::SArg; break;
171 case '[': k = ConversionSpecifier::ScanListArg; break;
172 case 'u': k = ConversionSpecifier::uArg; break;
173 case 'x': k = ConversionSpecifier::xArg; break;
174 case 'o': k = ConversionSpecifier::oArg; break;
175 case 's': k = ConversionSpecifier::sArg; break;
176 case 'p': k = ConversionSpecifier::pArg; break;
Jordan Rose275b6f52012-09-13 02:11:03 +0000177 // Apple extensions
178 // Apple-specific
179 case 'D':
180 if (Target.getTriple().isOSDarwin())
181 k = ConversionSpecifier::DArg;
182 break;
183 case 'O':
184 if (Target.getTriple().isOSDarwin())
185 k = ConversionSpecifier::OArg;
186 break;
187 case 'U':
188 if (Target.getTriple().isOSDarwin())
189 k = ConversionSpecifier::UArg;
190 break;
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000191 }
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000192 ScanfConversionSpecifier CS(conversionPosition, k);
193 if (k == ScanfConversionSpecifier::ScanListArg) {
Hans Wennborg6de0b482012-01-12 14:44:54 +0000194 if (ParseScanList(H, CS, I, E))
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000195 return true;
196 }
197 FS.setConversionSpecifier(CS);
198 if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
199 && !FS.usesPositionalArg())
200 FS.setArgIndex(argIndex++);
201
202 // FIXME: '%' and '*' doesn't make sense. Issue a warning.
203 // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
204
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000205 if (k == ScanfConversionSpecifier::InvalidSpecifier) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000206 // Assume the conversion takes one argument.
207 return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg);
208 }
209 return ScanfSpecifierResult(Start, FS);
210}
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000211
Hans Wennborg58e1e542012-08-07 08:59:46 +0000212ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000213 const ScanfConversionSpecifier &CS = getConversionSpecifier();
214
215 if (!CS.consumesDataArgument())
Hans Wennborg58e1e542012-08-07 08:59:46 +0000216 return ArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000217
218 switch(CS.getKind()) {
219 // Signed int.
220 case ConversionSpecifier::dArg:
Jordan Rose275b6f52012-09-13 02:11:03 +0000221 case ConversionSpecifier::DArg:
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000222 case ConversionSpecifier::iArg:
223 switch (LM.getKind()) {
Hans Wennborg58e1e542012-08-07 08:59:46 +0000224 case LengthModifier::None:
225 return ArgType::PtrTo(Ctx.IntTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000226 case LengthModifier::AsChar:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000227 return ArgType::PtrTo(ArgType::AnyCharTy);
228 case LengthModifier::AsShort:
229 return ArgType::PtrTo(Ctx.ShortTy);
230 case LengthModifier::AsLong:
231 return ArgType::PtrTo(Ctx.LongTy);
Hans Wennborg32addd52012-02-16 16:34:54 +0000232 case LengthModifier::AsLongLong:
233 case LengthModifier::AsQuad:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000234 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer47ad6ce2013-08-21 21:54:46 +0000235 case LengthModifier::AsInt64:
236 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000237 case LengthModifier::AsIntMax:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000238 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000239 case LengthModifier::AsSizeT:
240 // FIXME: ssize_t.
Hans Wennborg58e1e542012-08-07 08:59:46 +0000241 return ArgType();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000242 case LengthModifier::AsPtrDiff:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000243 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
Ted Kremenek9d24c2c2012-01-24 21:29:54 +0000244 case LengthModifier::AsLongDouble:
245 // GNU extension.
Hans Wennborg58e1e542012-08-07 08:59:46 +0000246 return ArgType::PtrTo(Ctx.LongLongTy);
247 case LengthModifier::AsAllocate:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000248 case LengthModifier::AsMAllocate:
David Majnemer47ad6ce2013-08-21 21:54:46 +0000249 case LengthModifier::AsInt32:
250 case LengthModifier::AsInt3264:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000251 return ArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000252 }
253
254 // Unsigned int.
255 case ConversionSpecifier::oArg:
Jordan Rose275b6f52012-09-13 02:11:03 +0000256 case ConversionSpecifier::OArg:
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000257 case ConversionSpecifier::uArg:
Jordan Rose275b6f52012-09-13 02:11:03 +0000258 case ConversionSpecifier::UArg:
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000259 case ConversionSpecifier::xArg:
260 case ConversionSpecifier::XArg:
261 switch (LM.getKind()) {
Hans Wennborg58e1e542012-08-07 08:59:46 +0000262 case LengthModifier::None:
263 return ArgType::PtrTo(Ctx.UnsignedIntTy);
264 case LengthModifier::AsChar:
265 return ArgType::PtrTo(Ctx.UnsignedCharTy);
266 case LengthModifier::AsShort:
267 return ArgType::PtrTo(Ctx.UnsignedShortTy);
268 case LengthModifier::AsLong:
269 return ArgType::PtrTo(Ctx.UnsignedLongTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000270 case LengthModifier::AsLongLong:
Hans Wennborg32addd52012-02-16 16:34:54 +0000271 case LengthModifier::AsQuad:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000272 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
David Majnemer47ad6ce2013-08-21 21:54:46 +0000273 case LengthModifier::AsInt64:
274 return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000275 case LengthModifier::AsIntMax:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000276 return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000277 case LengthModifier::AsSizeT:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000278 return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000279 case LengthModifier::AsPtrDiff:
280 // FIXME: Unsigned version of ptrdiff_t?
Hans Wennborg58e1e542012-08-07 08:59:46 +0000281 return ArgType();
Ted Kremenek9d24c2c2012-01-24 21:29:54 +0000282 case LengthModifier::AsLongDouble:
283 // GNU extension.
Hans Wennborg58e1e542012-08-07 08:59:46 +0000284 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
285 case LengthModifier::AsAllocate:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000286 case LengthModifier::AsMAllocate:
David Majnemer47ad6ce2013-08-21 21:54:46 +0000287 case LengthModifier::AsInt32:
288 case LengthModifier::AsInt3264:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000289 return ArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000290 }
291
292 // Float.
293 case ConversionSpecifier::aArg:
294 case ConversionSpecifier::AArg:
295 case ConversionSpecifier::eArg:
296 case ConversionSpecifier::EArg:
297 case ConversionSpecifier::fArg:
298 case ConversionSpecifier::FArg:
299 case ConversionSpecifier::gArg:
300 case ConversionSpecifier::GArg:
301 switch (LM.getKind()) {
Hans Wennborg58e1e542012-08-07 08:59:46 +0000302 case LengthModifier::None:
303 return ArgType::PtrTo(Ctx.FloatTy);
304 case LengthModifier::AsLong:
305 return ArgType::PtrTo(Ctx.DoubleTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000306 case LengthModifier::AsLongDouble:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000307 return ArgType::PtrTo(Ctx.LongDoubleTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000308 default:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000309 return ArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000310 }
311
312 // Char, string and scanlist.
313 case ConversionSpecifier::cArg:
314 case ConversionSpecifier::sArg:
315 case ConversionSpecifier::ScanListArg:
316 switch (LM.getKind()) {
Hans Wennborg58e1e542012-08-07 08:59:46 +0000317 case LengthModifier::None:
318 return ArgType::PtrTo(ArgType::AnyCharTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000319 case LengthModifier::AsLong:
Hans Wennborg15f92ba2013-05-10 10:08:40 +0000320 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg37969b72012-01-12 17:11:12 +0000321 case LengthModifier::AsAllocate:
322 case LengthModifier::AsMAllocate:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000323 return ArgType::PtrTo(ArgType::CStrTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000324 default:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000325 return ArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000326 }
327 case ConversionSpecifier::CArg:
328 case ConversionSpecifier::SArg:
329 // FIXME: Mac OS X specific?
Hans Wennborg37969b72012-01-12 17:11:12 +0000330 switch (LM.getKind()) {
331 case LengthModifier::None:
Hans Wennborg15f92ba2013-05-10 10:08:40 +0000332 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg37969b72012-01-12 17:11:12 +0000333 case LengthModifier::AsAllocate:
334 case LengthModifier::AsMAllocate:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000335 return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
Hans Wennborg37969b72012-01-12 17:11:12 +0000336 default:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000337 return ArgType::Invalid();
Hans Wennborg37969b72012-01-12 17:11:12 +0000338 }
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000339
340 // Pointer.
341 case ConversionSpecifier::pArg:
Hans Wennborg58e1e542012-08-07 08:59:46 +0000342 return ArgType::PtrTo(ArgType::CPointerTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000343
Hans Wennborg58e1e542012-08-07 08:59:46 +0000344 // Write-back.
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000345 case ConversionSpecifier::nArg:
Hans Wennborgf7158fa2012-08-07 09:13:19 +0000346 switch (LM.getKind()) {
347 case LengthModifier::None:
348 return ArgType::PtrTo(Ctx.IntTy);
349 case LengthModifier::AsChar:
350 return ArgType::PtrTo(Ctx.SignedCharTy);
351 case LengthModifier::AsShort:
352 return ArgType::PtrTo(Ctx.ShortTy);
353 case LengthModifier::AsLong:
354 return ArgType::PtrTo(Ctx.LongTy);
355 case LengthModifier::AsLongLong:
356 case LengthModifier::AsQuad:
357 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer47ad6ce2013-08-21 21:54:46 +0000358 case LengthModifier::AsInt64:
359 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborgf7158fa2012-08-07 09:13:19 +0000360 case LengthModifier::AsIntMax:
361 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
362 case LengthModifier::AsSizeT:
363 return ArgType(); // FIXME: ssize_t
364 case LengthModifier::AsPtrDiff:
365 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
366 case LengthModifier::AsLongDouble:
367 return ArgType(); // FIXME: Is this a known extension?
368 case LengthModifier::AsAllocate:
369 case LengthModifier::AsMAllocate:
David Majnemer47ad6ce2013-08-21 21:54:46 +0000370 case LengthModifier::AsInt32:
371 case LengthModifier::AsInt3264:
Hans Wennborgf7158fa2012-08-07 09:13:19 +0000372 return ArgType::Invalid();
373 }
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000374
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000375 default:
376 break;
377 }
378
Hans Wennborg58e1e542012-08-07 08:59:46 +0000379 return ArgType();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000380}
381
Stephen Hines651f13c2014-04-23 16:59:28 -0700382bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
383 const LangOptions &LangOpt,
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000384 ASTContext &Ctx) {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000385
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000386 // %n is different from other conversion specifiers; don't try to fix it.
387 if (CS.getKind() == ConversionSpecifier::nArg)
388 return false;
389
Stephen Hines651f13c2014-04-23 16:59:28 -0700390 if (!QT->isPointerType())
391 return false;
392
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000393 QualType PT = QT->getPointeeType();
Jordan Rose033a9c02012-06-04 22:49:02 +0000394
395 // If it's an enum, get its underlying type.
Stephen Hines651f13c2014-04-23 16:59:28 -0700396 if (const EnumType *ETy = PT->getAs<EnumType>())
397 PT = ETy->getDecl()->getIntegerType();
398
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000399 const BuiltinType *BT = PT->getAs<BuiltinType>();
400 if (!BT)
401 return false;
402
403 // Pointer to a character.
404 if (PT->isAnyCharacterType()) {
405 CS.setKind(ConversionSpecifier::sArg);
406 if (PT->isWideCharType())
407 LM.setKind(LengthModifier::AsWideChar);
408 else
409 LM.setKind(LengthModifier::None);
Stephen Hines651f13c2014-04-23 16:59:28 -0700410
411 // If we know the target array length, we can use it as a field width.
412 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
413 if (CAT->getSizeModifier() == ArrayType::Normal)
414 FieldWidth = OptionalAmount(OptionalAmount::Constant,
415 CAT->getSize().getZExtValue() - 1,
416 "", 0, false);
417
418 }
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000419 return true;
420 }
421
422 // Figure out the length modifier.
423 switch (BT->getKind()) {
424 // no modifier
425 case BuiltinType::UInt:
426 case BuiltinType::Int:
427 case BuiltinType::Float:
428 LM.setKind(LengthModifier::None);
429 break;
430
431 // hh
432 case BuiltinType::Char_U:
433 case BuiltinType::UChar:
434 case BuiltinType::Char_S:
435 case BuiltinType::SChar:
436 LM.setKind(LengthModifier::AsChar);
437 break;
438
439 // h
440 case BuiltinType::Short:
441 case BuiltinType::UShort:
442 LM.setKind(LengthModifier::AsShort);
443 break;
444
445 // l
446 case BuiltinType::Long:
447 case BuiltinType::ULong:
448 case BuiltinType::Double:
449 LM.setKind(LengthModifier::AsLong);
450 break;
451
452 // ll
453 case BuiltinType::LongLong:
454 case BuiltinType::ULongLong:
455 LM.setKind(LengthModifier::AsLongLong);
456 break;
457
458 // L
459 case BuiltinType::LongDouble:
460 LM.setKind(LengthModifier::AsLongDouble);
461 break;
462
463 // Don't know.
464 default:
465 return false;
466 }
467
468 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
Richard Smith80ad52f2013-01-02 11:42:31 +0000469 if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
Hans Wennborg46847782012-07-27 19:17:46 +0000470 namedTypeToLengthModifier(PT, LM);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000471
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000472 // If fixing the length modifier was enough, we are done.
Jordan Rosebbb6bb42012-09-08 04:00:03 +0000473 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
474 const analyze_scanf::ArgType &AT = getArgType(Ctx);
475 if (AT.isValid() && AT.matchesType(Ctx, QT))
476 return true;
477 }
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000478
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000479 // Figure out the conversion specifier.
480 if (PT->isRealFloatingType())
481 CS.setKind(ConversionSpecifier::fArg);
482 else if (PT->isSignedIntegerType())
483 CS.setKind(ConversionSpecifier::dArg);
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000484 else if (PT->isUnsignedIntegerType())
485 CS.setKind(ConversionSpecifier::uArg);
486 else
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000487 llvm_unreachable("Unexpected type");
488
489 return true;
490}
491
492void ScanfSpecifier::toString(raw_ostream &os) const {
493 os << "%";
494
495 if (usesPositionalArg())
496 os << getPositionalArgIndex() << "$";
497 if (SuppressAssignment)
498 os << "*";
499
500 FieldWidth.toString(os);
501 os << LM.toString();
502 os << CS.toString();
503}
504
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000505bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
506 const char *I,
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000507 const char *E,
Jordan Rose275b6f52012-09-13 02:11:03 +0000508 const LangOptions &LO,
509 const TargetInfo &Target) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000510
511 unsigned argIndex = 0;
512
513 // Keep looking for a format specifier until we have exhausted the string.
514 while (I != E) {
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000515 const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
Jordan Rose275b6f52012-09-13 02:11:03 +0000516 LO, Target);
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000517 // Did a fail-stop error of any kind occur when parsing the specifier?
518 // If so, don't do any more processing.
519 if (FSR.shouldStop())
Dmitri Gribenko1ad23d62012-09-10 21:20:09 +0000520 return true;
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000521 // Did we exhaust the string or encounter an error that
522 // we can recover from?
523 if (!FSR.hasValue())
524 continue;
525 // We have a format specifier. Pass it to the callback.
526 if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
527 I - FSR.getStart())) {
528 return true;
529 }
530 }
531 assert(I == E && "Format string not exhausted");
532 return false;
533}