blob: d091237d12e760cd930e71605514a9d54e8afc99 [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"
17
Hans Wennborgf3749f42012-08-07 08:11:26 +000018using clang::analyze_format_string::ArgType;
Ted Kremenekd9c904d2010-07-16 02:11:31 +000019using clang::analyze_format_string::FormatStringHandler;
20using clang::analyze_format_string::LengthModifier;
21using clang::analyze_format_string::OptionalAmount;
Ted Kremenek1e51c202010-07-20 20:04:47 +000022using clang::analyze_format_string::ConversionSpecifier;
Hans Wennborgf3749f42012-08-07 08:11:26 +000023using clang::analyze_scanf::ScanfArgType;
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,
71 const LangOptions &LO) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +000072
73 using namespace clang::analyze_scanf;
74 const char *I = Beg;
75 const char *Start = 0;
76 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
77
78 // Look for a '%' character that indicates the start of a format specifier.
79 for ( ; I != E ; ++I) {
80 char c = *I;
81 if (c == '\0') {
82 // Detect spurious null characters, which are likely errors.
83 H.HandleNullChar(I);
84 return true;
85 }
86 if (c == '%') {
87 Start = I++; // Record the start of the format specifier.
88 break;
89 }
90 }
91
92 // No format specifier found?
93 if (!Start)
94 return false;
95
96 if (I == E) {
97 // No more characters left?
98 H.HandleIncompleteSpecifier(Start, E - Start);
99 return true;
100 }
101
102 ScanfSpecifier FS;
103 if (ParseArgPosition(H, FS, Start, I, E))
104 return true;
105
106 if (I == E) {
107 // No more characters left?
108 H.HandleIncompleteSpecifier(Start, E - Start);
109 return true;
110 }
111
112 // Look for '*' flag if it is present.
113 if (*I == '*') {
114 FS.setSuppressAssignment(I);
115 if (++I == E) {
116 H.HandleIncompleteSpecifier(Start, E - Start);
117 return true;
118 }
119 }
120
121 // Look for the field width (if any). Unlike printf, this is either
122 // a fixed integer or isn't present.
123 const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
124 if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
125 assert(Amt.getHowSpecified() == OptionalAmount::Constant);
126 FS.setFieldWidth(Amt);
127
128 if (I == E) {
129 // No more characters left?
130 H.HandleIncompleteSpecifier(Start, E - Start);
131 return true;
132 }
133 }
134
135 // Look for the length modifier.
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000136 if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000137 // No more characters left?
138 H.HandleIncompleteSpecifier(Start, E - Start);
139 return true;
140 }
141
142 // Detect spurious null characters, which are likely errors.
143 if (*I == '\0') {
144 H.HandleNullChar(I);
145 return true;
146 }
147
148 // Finally, look for the conversion specifier.
149 const char *conversionPosition = I++;
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000150 ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000151 switch (*conversionPosition) {
152 default:
153 break;
Ted Kremenek1e51c202010-07-20 20:04:47 +0000154 case '%': k = ConversionSpecifier::PercentArg; break;
155 case 'A': k = ConversionSpecifier::AArg; break;
156 case 'E': k = ConversionSpecifier::EArg; break;
157 case 'F': k = ConversionSpecifier::FArg; break;
158 case 'G': k = ConversionSpecifier::GArg; break;
159 case 'X': k = ConversionSpecifier::XArg; break;
160 case 'a': k = ConversionSpecifier::aArg; break;
161 case 'd': k = ConversionSpecifier::dArg; break;
162 case 'e': k = ConversionSpecifier::eArg; break;
163 case 'f': k = ConversionSpecifier::fArg; break;
164 case 'g': k = ConversionSpecifier::gArg; break;
165 case 'i': k = ConversionSpecifier::iArg; break;
166 case 'n': k = ConversionSpecifier::nArg; break;
167 case 'c': k = ConversionSpecifier::cArg; break;
168 case 'C': k = ConversionSpecifier::CArg; break;
169 case 'S': k = ConversionSpecifier::SArg; break;
170 case '[': k = ConversionSpecifier::ScanListArg; break;
171 case 'u': k = ConversionSpecifier::uArg; break;
172 case 'x': k = ConversionSpecifier::xArg; break;
173 case 'o': k = ConversionSpecifier::oArg; break;
174 case 's': k = ConversionSpecifier::sArg; break;
175 case 'p': k = ConversionSpecifier::pArg; break;
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000176 }
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000177 ScanfConversionSpecifier CS(conversionPosition, k);
178 if (k == ScanfConversionSpecifier::ScanListArg) {
Hans Wennborg6de0b482012-01-12 14:44:54 +0000179 if (ParseScanList(H, CS, I, E))
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000180 return true;
181 }
182 FS.setConversionSpecifier(CS);
183 if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
184 && !FS.usesPositionalArg())
185 FS.setArgIndex(argIndex++);
186
187 // FIXME: '%' and '*' doesn't make sense. Issue a warning.
188 // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
189
Ted Kremenek6ecb9502010-07-20 20:04:27 +0000190 if (k == ScanfConversionSpecifier::InvalidSpecifier) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000191 // Assume the conversion takes one argument.
192 return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg);
193 }
194 return ScanfSpecifierResult(Start, FS);
195}
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000196
Hans Wennborgf3749f42012-08-07 08:11:26 +0000197ScanfArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000198 const ScanfConversionSpecifier &CS = getConversionSpecifier();
199
200 if (!CS.consumesDataArgument())
Hans Wennborgf3749f42012-08-07 08:11:26 +0000201 return ScanfArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000202
203 switch(CS.getKind()) {
204 // Signed int.
205 case ConversionSpecifier::dArg:
206 case ConversionSpecifier::iArg:
207 switch (LM.getKind()) {
Hans Wennborgf3749f42012-08-07 08:11:26 +0000208 case LengthModifier::None: return ArgType(Ctx.IntTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000209 case LengthModifier::AsChar:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000210 return ArgType(ArgType::AnyCharTy);
211 case LengthModifier::AsShort: return ArgType(Ctx.ShortTy);
212 case LengthModifier::AsLong: return ArgType(Ctx.LongTy);
Hans Wennborg32addd52012-02-16 16:34:54 +0000213 case LengthModifier::AsLongLong:
214 case LengthModifier::AsQuad:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000215 return ArgType(Ctx.LongLongTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000216 case LengthModifier::AsIntMax:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000217 return ScanfArgType(Ctx.getIntMaxType(), "intmax_t *");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000218 case LengthModifier::AsSizeT:
219 // FIXME: ssize_t.
Hans Wennborgf3749f42012-08-07 08:11:26 +0000220 return ScanfArgType();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000221 case LengthModifier::AsPtrDiff:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000222 return ScanfArgType(Ctx.getPointerDiffType(), "ptrdiff_t *");
Ted Kremenek9d24c2c2012-01-24 21:29:54 +0000223 case LengthModifier::AsLongDouble:
224 // GNU extension.
Hans Wennborgf3749f42012-08-07 08:11:26 +0000225 return ArgType(Ctx.LongLongTy);
226 case LengthModifier::AsAllocate: return ScanfArgType::Invalid();
227 case LengthModifier::AsMAllocate: return ScanfArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000228 }
229
230 // Unsigned int.
231 case ConversionSpecifier::oArg:
232 case ConversionSpecifier::uArg:
233 case ConversionSpecifier::xArg:
234 case ConversionSpecifier::XArg:
235 switch (LM.getKind()) {
Hans Wennborgf3749f42012-08-07 08:11:26 +0000236 case LengthModifier::None: return ArgType(Ctx.UnsignedIntTy);
237 case LengthModifier::AsChar: return ArgType(Ctx.UnsignedCharTy);
238 case LengthModifier::AsShort: return ArgType(Ctx.UnsignedShortTy);
239 case LengthModifier::AsLong: return ArgType(Ctx.UnsignedLongTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000240 case LengthModifier::AsLongLong:
Hans Wennborg32addd52012-02-16 16:34:54 +0000241 case LengthModifier::AsQuad:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000242 return ArgType(Ctx.UnsignedLongLongTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000243 case LengthModifier::AsIntMax:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000244 return ScanfArgType(Ctx.getUIntMaxType(), "uintmax_t *");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000245 case LengthModifier::AsSizeT:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000246 return ScanfArgType(Ctx.getSizeType(), "size_t *");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000247 case LengthModifier::AsPtrDiff:
248 // FIXME: Unsigned version of ptrdiff_t?
Hans Wennborgf3749f42012-08-07 08:11:26 +0000249 return ScanfArgType();
Ted Kremenek9d24c2c2012-01-24 21:29:54 +0000250 case LengthModifier::AsLongDouble:
251 // GNU extension.
Hans Wennborgf3749f42012-08-07 08:11:26 +0000252 return ArgType(Ctx.UnsignedLongLongTy);
253 case LengthModifier::AsAllocate: return ScanfArgType::Invalid();
254 case LengthModifier::AsMAllocate: return ScanfArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000255 }
256
257 // Float.
258 case ConversionSpecifier::aArg:
259 case ConversionSpecifier::AArg:
260 case ConversionSpecifier::eArg:
261 case ConversionSpecifier::EArg:
262 case ConversionSpecifier::fArg:
263 case ConversionSpecifier::FArg:
264 case ConversionSpecifier::gArg:
265 case ConversionSpecifier::GArg:
266 switch (LM.getKind()) {
Hans Wennborgf3749f42012-08-07 08:11:26 +0000267 case LengthModifier::None: return ArgType(Ctx.FloatTy);
268 case LengthModifier::AsLong: return ArgType(Ctx.DoubleTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000269 case LengthModifier::AsLongDouble:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000270 return ArgType(Ctx.LongDoubleTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000271 default:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000272 return ScanfArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000273 }
274
275 // Char, string and scanlist.
276 case ConversionSpecifier::cArg:
277 case ConversionSpecifier::sArg:
278 case ConversionSpecifier::ScanListArg:
279 switch (LM.getKind()) {
Hans Wennborgf3749f42012-08-07 08:11:26 +0000280 case LengthModifier::None: return ScanfArgType::CStrTy;
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000281 case LengthModifier::AsLong:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000282 return ScanfArgType(ScanfArgType::WCStrTy, "wchar_t *");
Hans Wennborg37969b72012-01-12 17:11:12 +0000283 case LengthModifier::AsAllocate:
284 case LengthModifier::AsMAllocate:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000285 return ScanfArgType(ArgType::CStrTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000286 default:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000287 return ScanfArgType::Invalid();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000288 }
289 case ConversionSpecifier::CArg:
290 case ConversionSpecifier::SArg:
291 // FIXME: Mac OS X specific?
Hans Wennborg37969b72012-01-12 17:11:12 +0000292 switch (LM.getKind()) {
293 case LengthModifier::None:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000294 return ScanfArgType(ScanfArgType::WCStrTy, "wchar_t *");
Hans Wennborg37969b72012-01-12 17:11:12 +0000295 case LengthModifier::AsAllocate:
296 case LengthModifier::AsMAllocate:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000297 return ScanfArgType(ArgType::WCStrTy, "wchar_t **");
Hans Wennborg37969b72012-01-12 17:11:12 +0000298 default:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000299 return ScanfArgType::Invalid();
Hans Wennborg37969b72012-01-12 17:11:12 +0000300 }
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000301
302 // Pointer.
303 case ConversionSpecifier::pArg:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000304 return ScanfArgType(ArgType(ArgType::CPointerTy));
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000305
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000306 case ConversionSpecifier::nArg:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000307 return ArgType(Ctx.IntTy);
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000308
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000309 default:
310 break;
311 }
312
Hans Wennborgf3749f42012-08-07 08:11:26 +0000313 return ScanfArgType();
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000314}
315
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000316bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
317 ASTContext &Ctx) {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000318 if (!QT->isPointerType())
319 return false;
320
Hans Wennborgcec9ce42012-07-30 17:11:32 +0000321 // %n is different from other conversion specifiers; don't try to fix it.
322 if (CS.getKind() == ConversionSpecifier::nArg)
323 return false;
324
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000325 QualType PT = QT->getPointeeType();
Jordan Rose033a9c02012-06-04 22:49:02 +0000326
327 // If it's an enum, get its underlying type.
328 if (const EnumType *ETy = QT->getAs<EnumType>())
329 QT = ETy->getDecl()->getIntegerType();
330
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000331 const BuiltinType *BT = PT->getAs<BuiltinType>();
332 if (!BT)
333 return false;
334
335 // Pointer to a character.
336 if (PT->isAnyCharacterType()) {
337 CS.setKind(ConversionSpecifier::sArg);
338 if (PT->isWideCharType())
339 LM.setKind(LengthModifier::AsWideChar);
340 else
341 LM.setKind(LengthModifier::None);
342 return true;
343 }
344
345 // Figure out the length modifier.
346 switch (BT->getKind()) {
347 // no modifier
348 case BuiltinType::UInt:
349 case BuiltinType::Int:
350 case BuiltinType::Float:
351 LM.setKind(LengthModifier::None);
352 break;
353
354 // hh
355 case BuiltinType::Char_U:
356 case BuiltinType::UChar:
357 case BuiltinType::Char_S:
358 case BuiltinType::SChar:
359 LM.setKind(LengthModifier::AsChar);
360 break;
361
362 // h
363 case BuiltinType::Short:
364 case BuiltinType::UShort:
365 LM.setKind(LengthModifier::AsShort);
366 break;
367
368 // l
369 case BuiltinType::Long:
370 case BuiltinType::ULong:
371 case BuiltinType::Double:
372 LM.setKind(LengthModifier::AsLong);
373 break;
374
375 // ll
376 case BuiltinType::LongLong:
377 case BuiltinType::ULongLong:
378 LM.setKind(LengthModifier::AsLongLong);
379 break;
380
381 // L
382 case BuiltinType::LongDouble:
383 LM.setKind(LengthModifier::AsLongDouble);
384 break;
385
386 // Don't know.
387 default:
388 return false;
389 }
390
391 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
Hans Wennborg46847782012-07-27 19:17:46 +0000392 if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
393 namedTypeToLengthModifier(PT, LM);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000394
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000395 // If fixing the length modifier was enough, we are done.
Hans Wennborgf3749f42012-08-07 08:11:26 +0000396 const analyze_scanf::ScanfArgType &ATR = getArgType(Ctx);
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000397 if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT))
398 return true;
399
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000400 // Figure out the conversion specifier.
401 if (PT->isRealFloatingType())
402 CS.setKind(ConversionSpecifier::fArg);
403 else if (PT->isSignedIntegerType())
404 CS.setKind(ConversionSpecifier::dArg);
Hans Wennborgbe6126a2012-02-15 09:59:46 +0000405 else if (PT->isUnsignedIntegerType())
406 CS.setKind(ConversionSpecifier::uArg);
407 else
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000408 llvm_unreachable("Unexpected type");
409
410 return true;
411}
412
413void ScanfSpecifier::toString(raw_ostream &os) const {
414 os << "%";
415
416 if (usesPositionalArg())
417 os << getPositionalArgIndex() << "$";
418 if (SuppressAssignment)
419 os << "*";
420
421 FieldWidth.toString(os);
422 os << LM.toString();
423 os << CS.toString();
424}
425
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000426bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
427 const char *I,
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000428 const char *E,
429 const LangOptions &LO) {
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000430
431 unsigned argIndex = 0;
432
433 // Keep looking for a format specifier until we have exhausted the string.
434 while (I != E) {
Hans Wennborgd02deeb2011-12-15 10:25:47 +0000435 const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
436 LO);
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000437 // Did a fail-stop error of any kind occur when parsing the specifier?
438 // If so, don't do any more processing.
439 if (FSR.shouldStop())
440 return true;;
441 // Did we exhaust the string or encounter an error that
442 // we can recover from?
443 if (!FSR.hasValue())
444 continue;
445 // We have a format specifier. Pass it to the callback.
446 if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
447 I - FSR.getStart())) {
448 return true;
449 }
450 }
451 assert(I == E && "Format string not exhausted");
452 return false;
453}
454
Hans Wennborgf3749f42012-08-07 08:11:26 +0000455bool ScanfArgType::matchesType(ASTContext& C, QualType argTy) const {
Hans Wennborg5deddaf2012-07-31 16:37:47 +0000456 // It has to be a pointer type.
457 const PointerType *PT = argTy->getAs<PointerType>();
458 if (!PT)
459 return false;
460
461 // We cannot write through a const qualified pointer.
462 if (PT->getPointeeType().isConstQualified())
463 return false;
464
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000465 switch (K) {
466 case InvalidTy:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000467 llvm_unreachable("ArgType must be valid");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000468 case UnknownTy:
469 return true;
470 case CStrTy:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000471 return ArgType(ArgType::CStrTy).matchesType(C, argTy);
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000472 case WCStrTy:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000473 return ArgType(ArgType::WCStrTy).matchesType(C, argTy);
474 case PtrToArgTypeTy: {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000475 return A.matchesType(C, PT->getPointeeType());
476 }
477 }
Ted Kremenekd9c904d2010-07-16 02:11:31 +0000478
Hans Wennborgf3749f42012-08-07 08:11:26 +0000479 llvm_unreachable("Invalid ScanfArgType Kind!");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000480}
481
Hans Wennborgf3749f42012-08-07 08:11:26 +0000482QualType ScanfArgType::getRepresentativeType(ASTContext &C) const {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000483 switch (K) {
484 case InvalidTy:
Hans Wennborgf3749f42012-08-07 08:11:26 +0000485 llvm_unreachable("No representative type for Invalid ArgType");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000486 case UnknownTy:
487 return QualType();
488 case CStrTy:
489 return C.getPointerType(C.CharTy);
490 case WCStrTy:
491 return C.getPointerType(C.getWCharType());
Hans Wennborgf3749f42012-08-07 08:11:26 +0000492 case PtrToArgTypeTy:
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000493 return C.getPointerType(A.getRepresentativeType(C));
494 }
495
Hans Wennborgf3749f42012-08-07 08:11:26 +0000496 llvm_unreachable("Invalid ScanfArgType Kind!");
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000497}
498
Hans Wennborgf3749f42012-08-07 08:11:26 +0000499std::string ScanfArgType::getRepresentativeTypeName(ASTContext& C) const {
Hans Wennborg6fcd9322011-12-10 13:20:11 +0000500 std::string S = getRepresentativeType(C).getAsString();
501 if (!Name)
502 return std::string("'") + S + "'";
503 return std::string("'") + Name + "' (aka '" + S + "')";
504}