blob: 9c0f8139640cad4360da9d8b6096237e66cb8128 [file] [log] [blame]
Ted Kremeneka2e77b42010-01-27 23:43:25 +00001//= PrintfFormatStrings.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 printf and friends. The structure of format
11// strings for fprintf() are described in C99 7.19.6.1.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/Analyses/PrintfFormatString.h"
Ted Kremenek79db7b72010-01-29 22:59:32 +000016#include "clang/AST/ASTContext.h"
Ted Kremeneka2e77b42010-01-27 23:43:25 +000017
Ted Kremenek176f7d62010-01-29 02:13:53 +000018using clang::analyze_printf::FormatSpecifier;
19using clang::analyze_printf::OptionalAmount;
Ted Kremenek79db7b72010-01-29 22:59:32 +000020using clang::analyze_printf::ArgTypeResult;
Ted Kremenek1de17072010-02-04 20:46:58 +000021using clang::analyze_printf::FormatStringHandler;
Ted Kremenekc22f78d2010-01-29 03:16:21 +000022using namespace clang;
Ted Kremeneka2e77b42010-01-27 23:43:25 +000023
24namespace {
25class FormatSpecifierResult {
26 FormatSpecifier FS;
27 const char *Start;
Ted Kremenek94af5752010-01-29 02:40:24 +000028 bool Stop;
Ted Kremeneka2e77b42010-01-27 23:43:25 +000029public:
Ted Kremenek94af5752010-01-29 02:40:24 +000030 FormatSpecifierResult(bool stop = false)
31 : Start(0), Stop(stop) {}
Ted Kremeneka2e77b42010-01-27 23:43:25 +000032 FormatSpecifierResult(const char *start,
Ted Kremenek08ad1cc2010-01-28 02:02:59 +000033 const FormatSpecifier &fs)
Ted Kremenek94af5752010-01-29 02:40:24 +000034 : FS(fs), Start(start), Stop(false) {}
Ted Kremeneka2e77b42010-01-27 23:43:25 +000035
Ted Kremenekc8b188d2010-02-16 01:46:59 +000036
Ted Kremeneka2e77b42010-01-27 23:43:25 +000037 const char *getStart() const { return Start; }
Ted Kremenek94af5752010-01-29 02:40:24 +000038 bool shouldStop() const { return Stop; }
Ted Kremeneka2e77b42010-01-27 23:43:25 +000039 bool hasValue() const { return Start != 0; }
40 const FormatSpecifier &getValue() const {
41 assert(hasValue());
42 return FS;
43 }
Ted Kremenek08ad1cc2010-01-28 02:02:59 +000044 const FormatSpecifier &getValue() { return FS; }
Ted Kremeneka2e77b42010-01-27 23:43:25 +000045};
46} // end anonymous namespace
47
48template <typename T>
49class UpdateOnReturn {
50 T &ValueToUpdate;
51 const T &ValueToCopy;
52public:
53 UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
54 : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
Ted Kremenekc8b188d2010-02-16 01:46:59 +000055
Ted Kremeneka2e77b42010-01-27 23:43:25 +000056 ~UpdateOnReturn() {
57 ValueToUpdate = ValueToCopy;
58 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +000059};
60
61//===----------------------------------------------------------------------===//
62// Methods for parsing format strings.
63//===----------------------------------------------------------------------===//
Ted Kremeneka2e77b42010-01-27 23:43:25 +000064
Ted Kremenek4a49d982010-02-26 19:18:41 +000065static OptionalAmount ParseAmount(const char *&Beg, const char *E,
66 unsigned &argIndex) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +000067 const char *I = Beg;
68 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
Ted Kremenekc8b188d2010-02-16 01:46:59 +000069
Ted Kremeneka2e77b42010-01-27 23:43:25 +000070 bool foundDigits = false;
71 unsigned accumulator = 0;
72
73 for ( ; I != E; ++I) {
74 char c = *I;
75 if (c >= '0' && c <= '9') {
76 foundDigits = true;
77 accumulator += (accumulator * 10) + (c - '0');
78 continue;
79 }
80
81 if (foundDigits)
Ted Kremenek4a49d982010-02-26 19:18:41 +000082 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg);
Ted Kremenekc8b188d2010-02-16 01:46:59 +000083
Ted Kremenek5739de72010-01-29 01:06:55 +000084 if (c == '*') {
85 ++I;
Ted Kremenek4a49d982010-02-26 19:18:41 +000086 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg);
Ted Kremenek5739de72010-01-29 01:06:55 +000087 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +000088
Ted Kremeneka2e77b42010-01-27 23:43:25 +000089 break;
90 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +000091
92 return OptionalAmount();
Ted Kremeneka2e77b42010-01-27 23:43:25 +000093}
94
Ted Kremenekc22f78d2010-01-29 03:16:21 +000095static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
Ted Kremenek1de17072010-02-04 20:46:58 +000096 const char *&Beg,
Ted Kremenek4a49d982010-02-26 19:18:41 +000097 const char *E,
98 unsigned &argIndex) {
Ted Kremenekc8b188d2010-02-16 01:46:59 +000099
Ted Kremenek176f7d62010-01-29 02:13:53 +0000100 using namespace clang::analyze_printf;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000101
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000102 const char *I = Beg;
Ted Kremenekc8d9c012010-01-28 00:02:05 +0000103 const char *Start = 0;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000104 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
105
106 // Look for a '%' character that indicates the start of a format specifier.
Ted Kremenekb5c98ef2010-01-28 23:56:52 +0000107 for ( ; I != E ; ++I) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000108 char c = *I;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000109 if (c == '\0') {
110 // Detect spurious null characters, which are likely errors.
111 H.HandleNullChar(I);
112 return true;
113 }
114 if (c == '%') {
Ted Kremenekb5c98ef2010-01-28 23:56:52 +0000115 Start = I++; // Record the start of the format specifier.
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000116 break;
117 }
118 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000119
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000120 // No format specifier found?
121 if (!Start)
122 return false;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000123
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000124 if (I == E) {
125 // No more characters left?
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000126 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000127 return true;
128 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000129
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000130 FormatSpecifier FS;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000131
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000132 // Look for flags (if any).
133 bool hasMore = true;
134 for ( ; I != E; ++I) {
135 switch (*I) {
136 default: hasMore = false; break;
137 case '-': FS.setIsLeftJustified(); break;
138 case '+': FS.setHasPlusPrefix(); break;
139 case ' ': FS.setHasSpacePrefix(); break;
140 case '#': FS.setHasAlternativeForm(); break;
141 case '0': FS.setHasLeadingZeros(); break;
142 }
143 if (!hasMore)
144 break;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000145 }
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000146
147 if (I == E) {
148 // No more characters left?
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000149 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000150 return true;
151 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000152
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000153 // Look for the field width (if any).
Ted Kremenek4a49d982010-02-26 19:18:41 +0000154 FS.setFieldWidth(ParseAmount(I, E, argIndex));
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000155
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000156 if (I == E) {
157 // No more characters left?
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000158 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000159 return true;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000160 }
161
162 // Look for the precision (if any).
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000163 if (*I == '.') {
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000164 ++I;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000165 if (I == E) {
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000166 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000167 return true;
168 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000169
Ted Kremenek4a49d982010-02-26 19:18:41 +0000170 FS.setPrecision(ParseAmount(I, E, argIndex));
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000171
172 if (I == E) {
173 // No more characters left?
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000174 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000175 return true;
176 }
177 }
178
179 // Look for the length modifier.
180 LengthModifier lm = None;
181 switch (*I) {
182 default:
183 break;
184 case 'h':
185 ++I;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000186 lm = (I != E && *I == 'h') ? ++I, AsChar : AsShort;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000187 break;
188 case 'l':
189 ++I;
190 lm = (I != E && *I == 'l') ? ++I, AsLongLong : AsLong;
191 break;
192 case 'j': lm = AsIntMax; ++I; break;
193 case 'z': lm = AsSizeT; ++I; break;
194 case 't': lm = AsPtrDiff; ++I; break;
195 case 'L': lm = AsLongDouble; ++I; break;
Daniel Dunbar19b70bd2010-01-30 15:49:20 +0000196 case 'q': lm = AsLongLong; ++I; break;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000197 }
198 FS.setLengthModifier(lm);
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000199
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000200 if (I == E) {
201 // No more characters left?
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000202 H.HandleIncompleteFormatSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000203 return true;
204 }
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000205
Ted Kremenek23a71a12010-01-29 20:29:53 +0000206 if (*I == '\0') {
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000207 // Detect spurious null characters, which are likely errors.
208 H.HandleNullChar(I);
209 return true;
Ted Kremenek23a71a12010-01-29 20:29:53 +0000210 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000211
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000212 // Finally, look for the conversion specifier.
Ted Kremenekfee0e962010-01-28 02:46:17 +0000213 const char *conversionPosition = I++;
Ted Kremenek94af5752010-01-29 02:40:24 +0000214 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000215 switch (*conversionPosition) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000216 default:
Ted Kremenek94af5752010-01-29 02:40:24 +0000217 break;
Ted Kremenekc06ead62010-01-28 00:55:28 +0000218 // C99: 7.19.6.1 (section 8).
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000219 case '%': k = ConversionSpecifier::PercentArg; break;
220 case 'A': k = ConversionSpecifier::AArg; break;
221 case 'E': k = ConversionSpecifier::EArg; break;
222 case 'F': k = ConversionSpecifier::FArg; break;
223 case 'G': k = ConversionSpecifier::GArg; break;
224 case 'X': k = ConversionSpecifier::XArg; break;
225 case 'a': k = ConversionSpecifier::aArg; break;
226 case 'c': k = ConversionSpecifier::IntAsCharArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000227 case 'd': k = ConversionSpecifier::dArg; break;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000228 case 'e': k = ConversionSpecifier::eArg; break;
229 case 'f': k = ConversionSpecifier::fArg; break;
230 case 'g': k = ConversionSpecifier::gArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000231 case 'i': k = ConversionSpecifier::iArg; break;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000232 case 'n': k = ConversionSpecifier::OutIntPtrArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000233 case 'o': k = ConversionSpecifier::oArg; break;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000234 case 'p': k = ConversionSpecifier::VoidPtrArg; break;
235 case 's': k = ConversionSpecifier::CStrArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000236 case 'u': k = ConversionSpecifier::uArg; break;
237 case 'x': k = ConversionSpecifier::xArg; break;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000238 // Mac OS X (unicode) specific
239 case 'C': k = ConversionSpecifier::CArg; break;
240 case 'S': k = ConversionSpecifier::UnicodeStrArg; break;
Ted Kremenekc06ead62010-01-28 00:55:28 +0000241 // Objective-C.
Ted Kremenek23a71a12010-01-29 20:29:53 +0000242 case '@': k = ConversionSpecifier::ObjCObjArg; break;
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000243 // Glibc specific.
Ted Kremenek23a71a12010-01-29 20:29:53 +0000244 case 'm': k = ConversionSpecifier::PrintErrno; break;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000245 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000246 ConversionSpecifier CS(conversionPosition, k);
247 FS.setConversionSpecifier(CS);
248 if (CS.consumesDataArgument())
249 FS.setArgIndex(argIndex++);
Ted Kremenek94af5752010-01-29 02:40:24 +0000250
251 if (k == ConversionSpecifier::InvalidSpecifier) {
Ted Kremenek4a49d982010-02-26 19:18:41 +0000252 // Assume the conversion takes one argument.
253 return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
Ted Kremenek94af5752010-01-29 02:40:24 +0000254 }
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000255 return FormatSpecifierResult(Start, FS);
256}
257
Ted Kremenek1de17072010-02-04 20:46:58 +0000258bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
Ted Kremenekfee0e962010-01-28 02:46:17 +0000259 const char *I, const char *E) {
Ted Kremenek4a49d982010-02-26 19:18:41 +0000260
261 unsigned argIndex = 0;
262
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000263 // Keep looking for a format specifier until we have exhausted the string.
264 while (I != E) {
Ted Kremenek4a49d982010-02-26 19:18:41 +0000265 const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex);
Ted Kremenek94af5752010-01-29 02:40:24 +0000266 // Did a fail-stop error of any kind occur when parsing the specifier?
267 // If so, don't do any more processing.
268 if (FSR.shouldStop())
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000269 return true;;
Ted Kremenek94af5752010-01-29 02:40:24 +0000270 // Did we exhaust the string or encounter an error that
271 // we can recover from?
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000272 if (!FSR.hasValue())
Ted Kremenek94af5752010-01-29 02:40:24 +0000273 continue;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000274 // We have a format specifier. Pass it to the callback.
Ted Kremenekfee0e962010-01-28 02:46:17 +0000275 if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
276 I - FSR.getStart()))
Ted Kremenek23a71a12010-01-29 20:29:53 +0000277 return true;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000278 }
279 assert(I == E && "Format string not exhausted");
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000280 return false;
281}
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000282
283FormatStringHandler::~FormatStringHandler() {}
Ted Kremenek79db7b72010-01-29 22:59:32 +0000284
285//===----------------------------------------------------------------------===//
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000286// Methods on ArgTypeResult.
287//===----------------------------------------------------------------------===//
288
289bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
290 assert(isValid());
291
292 if (K == UnknownTy)
293 return true;
294
295 if (K == SpecificTy) {
296 argTy = C.getCanonicalType(argTy).getUnqualifiedType();
297
298 if (T == argTy)
299 return true;
300
301 if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
302 switch (BT->getKind()) {
303 default:
304 break;
305 case BuiltinType::Char_S:
306 case BuiltinType::SChar:
307 return T == C.UnsignedCharTy;
308 case BuiltinType::Char_U:
309 case BuiltinType::UChar:
310 return T == C.SignedCharTy;
311 case BuiltinType::Short:
312 return T == C.UnsignedShortTy;
313 case BuiltinType::UShort:
314 return T == C.ShortTy;
315 case BuiltinType::Int:
316 return T == C.UnsignedIntTy;
317 case BuiltinType::UInt:
318 return T == C.IntTy;
319 case BuiltinType::Long:
320 return T == C.UnsignedLongTy;
321 case BuiltinType::ULong:
322 return T == C.LongTy;
323 case BuiltinType::LongLong:
324 return T == C.UnsignedLongLongTy;
325 case BuiltinType::ULongLong:
326 return T == C.LongLongTy;
327 }
328
329 return false;
330 }
331
332 if (K == CStrTy) {
333 const PointerType *PT = argTy->getAs<PointerType>();
334 if (!PT)
335 return false;
336
337 QualType pointeeTy = PT->getPointeeType();
338
339 if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
340 switch (BT->getKind()) {
341 case BuiltinType::Void:
342 case BuiltinType::Char_U:
343 case BuiltinType::UChar:
344 case BuiltinType::Char_S:
345 case BuiltinType::SChar:
346 return true;
347 default:
348 break;
349 }
350
351 return false;
352 }
353
354 if (K == WCStrTy) {
355 const PointerType *PT = argTy->getAs<PointerType>();
356 if (!PT)
357 return false;
358
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000359 QualType pointeeTy =
360 C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
361
362 return pointeeTy == C.getWCharType();
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000363 }
364
365 return false;
366}
367
368QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
369 assert(isValid());
370 if (K == SpecificTy)
371 return T;
372 if (K == CStrTy)
373 return C.getPointerType(C.CharTy);
374 if (K == WCStrTy)
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000375 return C.getPointerType(C.getWCharType());
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000376 if (K == ObjCPointerTy)
377 return C.ObjCBuiltinIdTy;
378
379 return QualType();
380}
381
382//===----------------------------------------------------------------------===//
383// Methods on OptionalAmount.
384//===----------------------------------------------------------------------===//
385
386ArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const {
387 return Ctx.IntTy;
388}
389
390//===----------------------------------------------------------------------===//
Ted Kremenek79db7b72010-01-29 22:59:32 +0000391// Methods on FormatSpecifier.
392//===----------------------------------------------------------------------===//
393
394ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
395 if (!CS.consumesDataArgument())
396 return ArgTypeResult::Invalid();
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000397
Ted Kremenek79db7b72010-01-29 22:59:32 +0000398 if (CS.isIntArg())
399 switch (LM) {
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000400 case AsLongDouble:
Ted Kremenek79db7b72010-01-29 22:59:32 +0000401 return ArgTypeResult::Invalid();
402 case None: return Ctx.IntTy;
403 case AsChar: return Ctx.SignedCharTy;
404 case AsShort: return Ctx.ShortTy;
405 case AsLong: return Ctx.LongTy;
406 case AsLongLong: return Ctx.LongLongTy;
407 case AsIntMax:
408 // FIXME: Return unknown for now.
409 return ArgTypeResult();
410 case AsSizeT: return Ctx.getSizeType();
411 case AsPtrDiff: return Ctx.getPointerDiffType();
412 }
413
414 if (CS.isUIntArg())
415 switch (LM) {
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000416 case AsLongDouble:
Ted Kremenek79db7b72010-01-29 22:59:32 +0000417 return ArgTypeResult::Invalid();
418 case None: return Ctx.UnsignedIntTy;
419 case AsChar: return Ctx.UnsignedCharTy;
420 case AsShort: return Ctx.UnsignedShortTy;
421 case AsLong: return Ctx.UnsignedLongTy;
422 case AsLongLong: return Ctx.UnsignedLongLongTy;
423 case AsIntMax:
424 // FIXME: Return unknown for now.
425 return ArgTypeResult();
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000426 case AsSizeT:
Ted Kremenek79db7b72010-01-29 22:59:32 +0000427 // FIXME: How to get the corresponding unsigned
428 // version of size_t?
429 return ArgTypeResult();
430 case AsPtrDiff:
431 // FIXME: How to get the corresponding unsigned
432 // version of ptrdiff_t?
433 return ArgTypeResult();
434 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000435
Ted Kremenek016b6052010-02-01 23:23:50 +0000436 if (CS.isDoubleArg()) {
437 if (LM == AsLongDouble)
438 return Ctx.LongDoubleTy;
Ted Kremenek9ff02052010-01-30 01:02:18 +0000439 return Ctx.DoubleTy;
Ted Kremenek016b6052010-02-01 23:23:50 +0000440 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000441
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000442 switch (CS.getKind()) {
443 case ConversionSpecifier::CStrArg:
444 return ArgTypeResult(LM == AsWideChar ? ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
445 case ConversionSpecifier::UnicodeStrArg:
446 // FIXME: This appears to be Mac OS X specific.
447 return ArgTypeResult::WCStrTy;
448 case ConversionSpecifier::CArg:
Ted Kremenek4a49d982010-02-26 19:18:41 +0000449 return Ctx.WCharTy;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000450 default:
451 break;
452 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000453
Ted Kremenek79db7b72010-01-29 22:59:32 +0000454 // FIXME: Handle other cases.
Ted Kremenekba775fe2010-01-29 23:00:35 +0000455 return ArgTypeResult();
Ted Kremenek79db7b72010-01-29 22:59:32 +0000456}
457