blob: e743e23078a2641bf978be2f9fd0327accc0787e [file] [log] [blame]
Ted Kremenek02087932010-07-16 02:11:22 +00001// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Ted Kremenek02087932010-07-16 02:11:22 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Shared details for processing format strings of printf and scanf
10// (and friends).
11//
12//===----------------------------------------------------------------------===//
13
14#include "FormatStringParsing.h"
Hans Wennborg23926bd2011-12-15 10:25:47 +000015#include "clang/Basic/LangOptions.h"
Jordan Rose92303592012-09-08 04:00:03 +000016#include "clang/Basic/TargetInfo.h"
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +000017#include "llvm/Support/ConvertUTF.h"
Ted Kremenek02087932010-07-16 02:11:22 +000018
Hans Wennborgc3b3da02012-08-07 08:11:26 +000019using clang::analyze_format_string::ArgType;
Ted Kremenek02087932010-07-16 02:11:22 +000020using clang::analyze_format_string::FormatStringHandler;
21using clang::analyze_format_string::FormatSpecifier;
22using clang::analyze_format_string::LengthModifier;
23using clang::analyze_format_string::OptionalAmount;
24using clang::analyze_format_string::PositionContext;
Ted Kremenekea28f832010-07-20 20:04:42 +000025using clang::analyze_format_string::ConversionSpecifier;
Ted Kremenek02087932010-07-16 02:11:22 +000026using namespace clang;
27
28// Key function to FormatStringHandler.
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000029FormatStringHandler::~FormatStringHandler() {}
Ted Kremenek02087932010-07-16 02:11:22 +000030
31//===----------------------------------------------------------------------===//
32// Functions for parsing format strings components in both printf and
33// scanf format strings.
34//===----------------------------------------------------------------------===//
35
36OptionalAmount
37clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
38 const char *I = Beg;
39 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
40
41 unsigned accumulator = 0;
42 bool hasDigits = false;
43
44 for ( ; I != E; ++I) {
45 char c = *I;
46 if (c >= '0' && c <= '9') {
47 hasDigits = true;
48 accumulator = (accumulator * 10) + (c - '0');
49 continue;
50 }
51
52 if (hasDigits)
53 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
54 false);
55
56 break;
57 }
58
59 return OptionalAmount();
60}
61
62OptionalAmount
63clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
64 const char *E,
65 unsigned &argIndex) {
66 if (*Beg == '*') {
67 ++Beg;
68 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
69 }
70
71 return ParseAmount(Beg, E);
72}
73
74OptionalAmount
75clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
76 const char *Start,
77 const char *&Beg,
78 const char *E,
79 PositionContext p) {
80 if (*Beg == '*') {
81 const char *I = Beg + 1;
82 const OptionalAmount &Amt = ParseAmount(I, E);
83
84 if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
85 H.HandleInvalidPosition(Beg, I - Beg, p);
86 return OptionalAmount(false);
87 }
88
89 if (I == E) {
90 // No more characters left?
91 H.HandleIncompleteSpecifier(Start, E - Start);
92 return OptionalAmount(false);
93 }
94
95 assert(Amt.getHowSpecified() == OptionalAmount::Constant);
96
97 if (*I == '$') {
98 // Handle positional arguments
99
100 // Special case: '*0$', since this is an easy mistake.
101 if (Amt.getConstantAmount() == 0) {
102 H.HandleZeroPosition(Beg, I - Beg + 1);
103 return OptionalAmount(false);
104 }
105
106 const char *Tmp = Beg;
107 Beg = ++I;
108
109 return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
110 Tmp, 0, true);
111 }
112
113 H.HandleInvalidPosition(Beg, I - Beg, p);
114 return OptionalAmount(false);
115 }
116
117 return ParseAmount(Beg, E);
118}
119
120
121bool
122clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
123 FormatSpecifier &CS,
124 const char *Start,
125 const char *&Beg, const char *E,
126 unsigned *argIndex) {
127 // FIXME: Support negative field widths.
128 if (argIndex) {
129 CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
130 }
131 else {
132 const OptionalAmount Amt =
133 ParsePositionAmount(H, Start, Beg, E,
134 analyze_format_string::FieldWidthPos);
135
136 if (Amt.isInvalid())
137 return true;
138 CS.setFieldWidth(Amt);
139 }
140 return false;
141}
142
143bool
144clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
145 FormatSpecifier &FS,
146 const char *Start,
147 const char *&Beg,
148 const char *E) {
149 const char *I = Beg;
150
151 const OptionalAmount &Amt = ParseAmount(I, E);
152
153 if (I == E) {
154 // No more characters left?
155 H.HandleIncompleteSpecifier(Start, E - Start);
156 return true;
157 }
158
159 if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
Hans Wennborgaa8c61c2012-03-09 10:10:54 +0000160 // Warn that positional arguments are non-standard.
161 H.HandlePosition(Start, I - Start);
162
Ted Kremenek02087932010-07-16 02:11:22 +0000163 // Special case: '%0$', since this is an easy mistake.
164 if (Amt.getConstantAmount() == 0) {
165 H.HandleZeroPosition(Start, I - Start);
166 return true;
167 }
168
169 FS.setArgIndex(Amt.getConstantAmount() - 1);
170 FS.setUsesPositionalArg();
171 // Update the caller's pointer if we decided to consume
172 // these characters.
173 Beg = I;
174 return false;
175 }
176
177 return false;
178}
179
180bool
Matt Arsenault0ff50d42018-12-01 22:16:27 +0000181clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
182 FormatSpecifier &FS,
183 const char *&I,
184 const char *E,
185 const LangOptions &LO) {
186 if (!LO.OpenCL)
187 return false;
188
189 const char *Start = I;
190 if (*I == 'v') {
191 ++I;
192
193 if (I == E) {
194 H.HandleIncompleteSpecifier(Start, E - Start);
195 return true;
196 }
197
198 OptionalAmount NumElts = ParseAmount(I, E);
199 if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
200 H.HandleIncompleteSpecifier(Start, E - Start);
201 return true;
202 }
203
204 FS.setVectorNumElts(NumElts);
205 }
206
207 return false;
208}
209
210bool
Ted Kremenek02087932010-07-16 02:11:22 +0000211clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
212 const char *&I,
Hans Wennborg23926bd2011-12-15 10:25:47 +0000213 const char *E,
214 const LangOptions &LO,
215 bool IsScanf) {
Ted Kremenek02087932010-07-16 02:11:22 +0000216 LengthModifier::Kind lmKind = LengthModifier::None;
217 const char *lmPosition = I;
218 switch (*I) {
219 default:
220 return false;
221 case 'h':
222 ++I;
Richard Trieucc3949d2016-02-18 22:34:54 +0000223 if (I != E && *I == 'h') {
224 ++I;
225 lmKind = LengthModifier::AsChar;
226 } else {
227 lmKind = LengthModifier::AsShort;
228 }
Ted Kremenek02087932010-07-16 02:11:22 +0000229 break;
230 case 'l':
231 ++I;
Richard Trieucc3949d2016-02-18 22:34:54 +0000232 if (I != E && *I == 'l') {
233 ++I;
234 lmKind = LengthModifier::AsLongLong;
235 } else {
236 lmKind = LengthModifier::AsLong;
237 }
Ted Kremenek02087932010-07-16 02:11:22 +0000238 break;
239 case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
240 case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
241 case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
242 case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000243 case 'q': lmKind = LengthModifier::AsQuad; ++I; break;
Hans Wennborg23926bd2011-12-15 10:25:47 +0000244 case 'a':
Richard Smith2bf7fdb2013-01-02 11:42:31 +0000245 if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
Hans Wennborg23926bd2011-12-15 10:25:47 +0000246 // For scanf in C90, look at the next character to see if this should
247 // be parsed as the GNU extension 'a' length modifier. If not, this
248 // will be parsed as a conversion specifier.
249 ++I;
250 if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
251 lmKind = LengthModifier::AsAllocate;
252 break;
253 }
254 --I;
255 }
256 return false;
Hans Wennborg6073e312012-01-12 17:11:12 +0000257 case 'm':
258 if (IsScanf) {
259 lmKind = LengthModifier::AsMAllocate;
260 ++I;
261 break;
262 }
263 return false;
David Majnemer3cba4952013-08-21 21:54:46 +0000264 // printf: AsInt64, AsInt32, AsInt3264
265 // scanf: AsInt64
266 case 'I':
267 if (I + 1 != E && I + 2 != E) {
268 if (I[1] == '6' && I[2] == '4') {
269 I += 3;
270 lmKind = LengthModifier::AsInt64;
271 break;
272 }
273 if (IsScanf)
274 return false;
275
276 if (I[1] == '3' && I[2] == '2') {
277 I += 3;
278 lmKind = LengthModifier::AsInt32;
279 break;
280 }
281 }
282 ++I;
283 lmKind = LengthModifier::AsInt3264;
284 break;
Hans Wennborg68f42b92014-09-04 21:39:46 +0000285 case 'w':
286 lmKind = LengthModifier::AsWide; ++I; break;
Ted Kremenek02087932010-07-16 02:11:22 +0000287 }
288 LengthModifier lm(lmPosition, lmKind);
289 FS.setLengthModifier(lm);
290 return true;
291}
292
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000293bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
294 const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
295 if (SpecifierBegin + 1 >= FmtStrEnd)
296 return false;
297
Justin Lebar90910552016-09-30 00:38:45 +0000298 const llvm::UTF8 *SB =
299 reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
300 const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000301 const char FirstByte = *SB;
302
303 // If the invalid specifier is a multibyte UTF-8 string, return the
304 // total length accordingly so that the conversion specifier can be
305 // properly updated to reflect a complete UTF-8 specifier.
Justin Lebar90910552016-09-30 00:38:45 +0000306 unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000307 if (NumBytes == 1)
308 return false;
309 if (SB + NumBytes > SE)
310 return false;
311
312 Len = NumBytes + 1;
313 return true;
314}
315
Ted Kremenek02087932010-07-16 02:11:22 +0000316//===----------------------------------------------------------------------===//
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000317// Methods on ArgType.
Ted Kremenek02087932010-07-16 02:11:22 +0000318//===----------------------------------------------------------------------===//
319
Seth Cantrellb4802962015-03-04 03:12:10 +0000320clang::analyze_format_string::ArgType::MatchKind
321ArgType::matchesType(ASTContext &C, QualType argTy) const {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000322 if (Ptr) {
323 // It has to be a pointer.
324 const PointerType *PT = argTy->getAs<PointerType>();
325 if (!PT)
Seth Cantrellb4802962015-03-04 03:12:10 +0000326 return NoMatch;
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000327
328 // We cannot write through a const qualified pointer.
329 if (PT->getPointeeType().isConstQualified())
Seth Cantrellb4802962015-03-04 03:12:10 +0000330 return NoMatch;
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000331
332 argTy = PT->getPointeeType();
333 }
334
Ted Kremenek02087932010-07-16 02:11:22 +0000335 switch (K) {
336 case InvalidTy:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000337 llvm_unreachable("ArgType must be valid");
Ted Kremenek02087932010-07-16 02:11:22 +0000338
339 case UnknownTy:
Seth Cantrellb4802962015-03-04 03:12:10 +0000340 return Match;
341
Ted Kremenek74e82bd2011-10-25 04:20:41 +0000342 case AnyCharTy: {
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000343 if (const EnumType *ETy = argTy->getAs<EnumType>()) {
344 // If the enum is incomplete we know nothing about the underlying type.
345 // Assume that it's 'int'.
346 if (!ETy->getDecl()->isComplete())
347 return NoMatch;
Jordan Rose98709982012-06-04 22:48:57 +0000348 argTy = ETy->getDecl()->getIntegerType();
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000349 }
Jordan Rose98709982012-06-04 22:48:57 +0000350
Ted Kremenek74e82bd2011-10-25 04:20:41 +0000351 if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
352 switch (BT->getKind()) {
353 default:
354 break;
355 case BuiltinType::Char_S:
356 case BuiltinType::SChar:
357 case BuiltinType::UChar:
358 case BuiltinType::Char_U:
Seth Cantrellb4802962015-03-04 03:12:10 +0000359 return Match;
Ted Kremenek74e82bd2011-10-25 04:20:41 +0000360 }
Seth Cantrellb4802962015-03-04 03:12:10 +0000361 return NoMatch;
Ted Kremenek74e82bd2011-10-25 04:20:41 +0000362 }
Seth Cantrellb4802962015-03-04 03:12:10 +0000363
Ted Kremenek02087932010-07-16 02:11:22 +0000364 case SpecificTy: {
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000365 if (const EnumType *ETy = argTy->getAs<EnumType>()) {
366 // If the enum is incomplete we know nothing about the underlying type.
367 // Assume that it's 'int'.
368 if (!ETy->getDecl()->isComplete())
369 argTy = C.IntTy;
370 else
371 argTy = ETy->getDecl()->getIntegerType();
372 }
Ted Kremenek02087932010-07-16 02:11:22 +0000373 argTy = C.getCanonicalType(argTy).getUnqualifiedType();
Jordan Rose98709982012-06-04 22:48:57 +0000374
Nick Lewycky45ccba62011-12-02 23:21:43 +0000375 if (T == argTy)
Seth Cantrellb4802962015-03-04 03:12:10 +0000376 return Match;
Ted Kremenekcc47e0f2011-07-13 17:35:14 +0000377 // Check for "compatible types".
Ted Kremenekd0c2afd2011-07-14 17:05:32 +0000378 if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
Ted Kremenek02087932010-07-16 02:11:22 +0000379 switch (BT->getKind()) {
380 default:
381 break;
382 case BuiltinType::Char_S:
383 case BuiltinType::SChar:
Ted Kremenekcc47e0f2011-07-13 17:35:14 +0000384 case BuiltinType::Char_U:
Seth Cantrellb4802962015-03-04 03:12:10 +0000385 case BuiltinType::UChar:
386 return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
387 : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000388 case BuiltinType::Short:
Seth Cantrellb4802962015-03-04 03:12:10 +0000389 return T == C.UnsignedShortTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000390 case BuiltinType::UShort:
Seth Cantrellb4802962015-03-04 03:12:10 +0000391 return T == C.ShortTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000392 case BuiltinType::Int:
Seth Cantrellb4802962015-03-04 03:12:10 +0000393 return T == C.UnsignedIntTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000394 case BuiltinType::UInt:
Seth Cantrellb4802962015-03-04 03:12:10 +0000395 return T == C.IntTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000396 case BuiltinType::Long:
Seth Cantrellb4802962015-03-04 03:12:10 +0000397 return T == C.UnsignedLongTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000398 case BuiltinType::ULong:
Seth Cantrellb4802962015-03-04 03:12:10 +0000399 return T == C.LongTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000400 case BuiltinType::LongLong:
Seth Cantrellb4802962015-03-04 03:12:10 +0000401 return T == C.UnsignedLongLongTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000402 case BuiltinType::ULongLong:
Seth Cantrellb4802962015-03-04 03:12:10 +0000403 return T == C.LongLongTy ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000404 }
Seth Cantrellb4802962015-03-04 03:12:10 +0000405 return NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000406 }
407
408 case CStrTy: {
409 const PointerType *PT = argTy->getAs<PointerType>();
410 if (!PT)
Seth Cantrellb4802962015-03-04 03:12:10 +0000411 return NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000412 QualType pointeeTy = PT->getPointeeType();
413 if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
414 switch (BT->getKind()) {
415 case BuiltinType::Void:
416 case BuiltinType::Char_U:
417 case BuiltinType::UChar:
418 case BuiltinType::Char_S:
419 case BuiltinType::SChar:
Seth Cantrellb4802962015-03-04 03:12:10 +0000420 return Match;
Ted Kremenek02087932010-07-16 02:11:22 +0000421 default:
422 break;
423 }
424
Seth Cantrellb4802962015-03-04 03:12:10 +0000425 return NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000426 }
427
428 case WCStrTy: {
429 const PointerType *PT = argTy->getAs<PointerType>();
430 if (!PT)
Seth Cantrellb4802962015-03-04 03:12:10 +0000431 return NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000432 QualType pointeeTy =
433 C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
Seth Cantrellb4802962015-03-04 03:12:10 +0000434 return pointeeTy == C.getWideCharType() ? Match : NoMatch;
Ted Kremenek02087932010-07-16 02:11:22 +0000435 }
Seth Cantrellb4802962015-03-04 03:12:10 +0000436
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000437 case WIntTy: {
James Molloy36365542012-05-04 10:55:22 +0000438 QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
Saleem Abdulrasool29bf94d2018-09-19 18:13:34 +0000439
440 if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
441 return Match;
442
443 QualType PromoArg = argTy->isPromotableIntegerType()
444 ? C.getPromotedIntegerType(argTy)
445 : argTy;
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000446 PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
Seth Cantrellb4802962015-03-04 03:12:10 +0000447
James Molloy36365542012-05-04 10:55:22 +0000448 // If the promoted argument is the corresponding signed type of the
449 // wint_t type, then it should match.
450 if (PromoArg->hasSignedIntegerRepresentation() &&
451 C.getCorrespondingUnsignedType(PromoArg) == WInt)
Seth Cantrellb4802962015-03-04 03:12:10 +0000452 return Match;
James Molloy36365542012-05-04 10:55:22 +0000453
Seth Cantrellb4802962015-03-04 03:12:10 +0000454 return WInt == PromoArg ? Match : NoMatch;
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000455 }
Ted Kremenek02087932010-07-16 02:11:22 +0000456
457 case CPointerTy:
Seth Cantrellb4802962015-03-04 03:12:10 +0000458 if (argTy->isVoidPointerType()) {
459 return Match;
460 } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
461 argTy->isBlockPointerType() || argTy->isNullPtrType()) {
462 return NoMatchPedantic;
463 } else {
464 return NoMatch;
465 }
Ted Kremenek02087932010-07-16 02:11:22 +0000466
Ted Kremenekd22b98a2012-02-06 21:45:29 +0000467 case ObjCPointerTy: {
468 if (argTy->getAs<ObjCObjectPointerType>() ||
469 argTy->getAs<BlockPointerType>())
Seth Cantrellb4802962015-03-04 03:12:10 +0000470 return Match;
471
Ted Kremenekd22b98a2012-02-06 21:45:29 +0000472 // Handle implicit toll-free bridging.
473 if (const PointerType *PT = argTy->getAs<PointerType>()) {
474 // Things such as CFTypeRef are really just opaque pointers
475 // to C structs representing CF types that can often be bridged
476 // to Objective-C objects. Since the compiler doesn't know which
477 // structs can be toll-free bridged, we just accept them all.
478 QualType pointee = PT->getPointeeType();
479 if (pointee->getAsStructureType() || pointee->isVoidType())
Seth Cantrellb4802962015-03-04 03:12:10 +0000480 return Match;
Ted Kremenekd22b98a2012-02-06 21:45:29 +0000481 }
Seth Cantrellb4802962015-03-04 03:12:10 +0000482 return NoMatch;
Ted Kremenekd22b98a2012-02-06 21:45:29 +0000483 }
Ted Kremenek02087932010-07-16 02:11:22 +0000484 }
485
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000486 llvm_unreachable("Invalid ArgType Kind!");
Ted Kremenek02087932010-07-16 02:11:22 +0000487}
488
Matt Arsenault0ff50d42018-12-01 22:16:27 +0000489ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
490 if (K != SpecificTy) // Won't be a valid vector element type.
491 return ArgType::Invalid();
492
493 QualType Vec = C.getExtVectorType(T, NumElts);
494 return ArgType(Vec, Name);
495}
496
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000497QualType ArgType::getRepresentativeType(ASTContext &C) const {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000498 QualType Res;
Ted Kremenek02087932010-07-16 02:11:22 +0000499 switch (K) {
500 case InvalidTy:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000501 llvm_unreachable("No representative type for Invalid ArgType");
Ted Kremenek02087932010-07-16 02:11:22 +0000502 case UnknownTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000503 llvm_unreachable("No representative type for Unknown ArgType");
Ted Kremenek74e82bd2011-10-25 04:20:41 +0000504 case AnyCharTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000505 Res = C.CharTy;
506 break;
Ted Kremenek02087932010-07-16 02:11:22 +0000507 case SpecificTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000508 Res = T;
509 break;
Ted Kremenek02087932010-07-16 02:11:22 +0000510 case CStrTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000511 Res = C.getPointerType(C.CharTy);
512 break;
Ted Kremenek02087932010-07-16 02:11:22 +0000513 case WCStrTy:
Hans Wennborg0d81e012013-05-10 10:08:40 +0000514 Res = C.getPointerType(C.getWideCharType());
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000515 break;
Ted Kremenek02087932010-07-16 02:11:22 +0000516 case ObjCPointerTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000517 Res = C.ObjCBuiltinIdTy;
518 break;
Ted Kremenek02087932010-07-16 02:11:22 +0000519 case CPointerTy:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000520 Res = C.VoidPtrTy;
521 break;
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000522 case WIntTy: {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000523 Res = C.getWIntType();
524 break;
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000525 }
Ted Kremenek02087932010-07-16 02:11:22 +0000526 }
527
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000528 if (Ptr)
529 Res = C.getPointerType(Res);
530 return Res;
Ted Kremenek02087932010-07-16 02:11:22 +0000531}
532
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000533std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
Hans Wennborga5b1aa92011-12-09 12:22:12 +0000534 std::string S = getRepresentativeType(C).getAsString();
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000535
536 std::string Alias;
537 if (Name) {
538 // Use a specific name for this type, e.g. "size_t".
539 Alias = Name;
540 if (Ptr) {
541 // If ArgType is actually a pointer to T, append an asterisk.
542 Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
543 }
544 // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
545 if (S == Alias)
546 Alias.clear();
547 }
548
549 if (!Alias.empty())
550 return std::string("'") + Alias + "' (aka '" + S + "')";
Hans Wennborga5b1aa92011-12-09 12:22:12 +0000551 return std::string("'") + S + "'";
Hans Wennborg772e9272011-12-07 10:33:11 +0000552}
553
554
Ted Kremenek02087932010-07-16 02:11:22 +0000555//===----------------------------------------------------------------------===//
556// Methods on OptionalAmount.
557//===----------------------------------------------------------------------===//
558
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000559ArgType
Ted Kremenek02087932010-07-16 02:11:22 +0000560analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
561 return Ctx.IntTy;
562}
563
564//===----------------------------------------------------------------------===//
565// Methods on LengthModifier.
566//===----------------------------------------------------------------------===//
567
568const char *
569analyze_format_string::LengthModifier::toString() const {
570 switch (kind) {
571 case AsChar:
572 return "hh";
573 case AsShort:
574 return "h";
575 case AsLong: // or AsWideChar
576 return "l";
577 case AsLongLong:
578 return "ll";
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000579 case AsQuad:
580 return "q";
Ted Kremenek02087932010-07-16 02:11:22 +0000581 case AsIntMax:
582 return "j";
583 case AsSizeT:
584 return "z";
585 case AsPtrDiff:
586 return "t";
David Majnemer3cba4952013-08-21 21:54:46 +0000587 case AsInt32:
588 return "I32";
589 case AsInt3264:
590 return "I";
591 case AsInt64:
592 return "I64";
Ted Kremenek02087932010-07-16 02:11:22 +0000593 case AsLongDouble:
594 return "L";
Hans Wennborg23926bd2011-12-15 10:25:47 +0000595 case AsAllocate:
596 return "a";
Hans Wennborg6073e312012-01-12 17:11:12 +0000597 case AsMAllocate:
598 return "m";
Hans Wennborg68f42b92014-09-04 21:39:46 +0000599 case AsWide:
600 return "w";
Ted Kremenek02087932010-07-16 02:11:22 +0000601 case None:
602 return "";
603 }
Craig Topper25542942014-05-20 04:30:07 +0000604 return nullptr;
Ted Kremenek02087932010-07-16 02:11:22 +0000605}
606
607//===----------------------------------------------------------------------===//
Hans Wennborga8b042d2011-12-09 11:11:07 +0000608// Methods on ConversionSpecifier.
609//===----------------------------------------------------------------------===//
610
611const char *ConversionSpecifier::toString() const {
612 switch (kind) {
613 case dArg: return "d";
Jordan Rose510260c2012-09-13 02:11:03 +0000614 case DArg: return "D";
Hans Wennborga8b042d2011-12-09 11:11:07 +0000615 case iArg: return "i";
616 case oArg: return "o";
Jordan Rose510260c2012-09-13 02:11:03 +0000617 case OArg: return "O";
Hans Wennborga8b042d2011-12-09 11:11:07 +0000618 case uArg: return "u";
Jordan Rose510260c2012-09-13 02:11:03 +0000619 case UArg: return "U";
Hans Wennborga8b042d2011-12-09 11:11:07 +0000620 case xArg: return "x";
621 case XArg: return "X";
622 case fArg: return "f";
623 case FArg: return "F";
624 case eArg: return "e";
625 case EArg: return "E";
626 case gArg: return "g";
627 case GArg: return "G";
628 case aArg: return "a";
629 case AArg: return "A";
630 case cArg: return "c";
631 case sArg: return "s";
632 case pArg: return "p";
Mehdi Amini06d367c2016-10-24 20:39:34 +0000633 case PArg:
634 return "P";
Hans Wennborga8b042d2011-12-09 11:11:07 +0000635 case nArg: return "n";
636 case PercentArg: return "%";
637 case ScanListArg: return "[";
Craig Topper25542942014-05-20 04:30:07 +0000638 case InvalidSpecifier: return nullptr;
Hans Wennborga8b042d2011-12-09 11:11:07 +0000639
David Majnemer3cba4952013-08-21 21:54:46 +0000640 // POSIX unicode extensions.
Hans Wennborga8b042d2011-12-09 11:11:07 +0000641 case CArg: return "C";
642 case SArg: return "S";
643
644 // Objective-C specific specifiers.
645 case ObjCObjArg: return "@";
646
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000647 // FreeBSD kernel specific specifiers.
648 case FreeBSDbArg: return "b";
649 case FreeBSDDArg: return "D";
650 case FreeBSDrArg: return "r";
651 case FreeBSDyArg: return "y";
652
Hans Wennborga8b042d2011-12-09 11:11:07 +0000653 // GlibC specific specifiers.
654 case PrintErrno: return "m";
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000655
656 // MS specific specifiers.
657 case ZArg: return "Z";
Hans Wennborga8b042d2011-12-09 11:11:07 +0000658 }
Craig Topper25542942014-05-20 04:30:07 +0000659 return nullptr;
Hans Wennborga8b042d2011-12-09 11:11:07 +0000660}
661
David Blaikie05785d12013-02-20 22:23:23 +0000662Optional<ConversionSpecifier>
Jordan Rose4c266aa2012-09-13 02:11:15 +0000663ConversionSpecifier::getStandardSpecifier() const {
664 ConversionSpecifier::Kind NewKind;
Fangrui Song6907ce22018-07-30 19:24:48 +0000665
Jordan Rose4c266aa2012-09-13 02:11:15 +0000666 switch (getKind()) {
667 default:
David Blaikie7a30dc52013-02-21 01:47:18 +0000668 return None;
Jordan Rose4c266aa2012-09-13 02:11:15 +0000669 case DArg:
670 NewKind = dArg;
671 break;
672 case UArg:
673 NewKind = uArg;
674 break;
675 case OArg:
676 NewKind = oArg;
677 break;
678 }
679
680 ConversionSpecifier FixedCS(*this);
681 FixedCS.setKind(NewKind);
682 return FixedCS;
683}
684
Hans Wennborga8b042d2011-12-09 11:11:07 +0000685//===----------------------------------------------------------------------===//
Ted Kremenek02087932010-07-16 02:11:22 +0000686// Methods on OptionalAmount.
687//===----------------------------------------------------------------------===//
688
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000689void OptionalAmount::toString(raw_ostream &os) const {
Ted Kremenek02087932010-07-16 02:11:22 +0000690 switch (hs) {
691 case Invalid:
692 case NotSpecified:
693 return;
694 case Arg:
695 if (UsesDotPrefix)
696 os << ".";
697 if (usesPositionalArg())
698 os << "*" << getPositionalArgIndex() << "$";
699 else
700 os << "*";
701 break;
702 case Constant:
703 if (UsesDotPrefix)
704 os << ".";
705 os << amt;
706 break;
707 }
708}
709
Jordan Rose92303592012-09-08 04:00:03 +0000710bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
Ted Kremenekea28f832010-07-20 20:04:42 +0000711 switch (LM.getKind()) {
712 case LengthModifier::None:
713 return true;
Fangrui Song6907ce22018-07-30 19:24:48 +0000714
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000715 // Handle most integer flags
Ted Kremenekea28f832010-07-20 20:04:42 +0000716 case LengthModifier::AsShort:
Hans Wennborg1b231582014-09-04 21:39:52 +0000717 if (Target.getTriple().isOSMSVCRT()) {
718 switch (CS.getKind()) {
719 case ConversionSpecifier::cArg:
720 case ConversionSpecifier::CArg:
721 case ConversionSpecifier::sArg:
722 case ConversionSpecifier::SArg:
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000723 case ConversionSpecifier::ZArg:
Hans Wennborg1b231582014-09-04 21:39:52 +0000724 return true;
725 default:
726 break;
727 }
728 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000729 LLVM_FALLTHROUGH;
Hans Wennborg1b231582014-09-04 21:39:52 +0000730 case LengthModifier::AsChar:
Ted Kremenekea28f832010-07-20 20:04:42 +0000731 case LengthModifier::AsLongLong:
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000732 case LengthModifier::AsQuad:
Ted Kremenekea28f832010-07-20 20:04:42 +0000733 case LengthModifier::AsIntMax:
734 case LengthModifier::AsSizeT:
735 case LengthModifier::AsPtrDiff:
736 switch (CS.getKind()) {
737 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000738 case ConversionSpecifier::DArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000739 case ConversionSpecifier::iArg:
740 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000741 case ConversionSpecifier::OArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000742 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000743 case ConversionSpecifier::UArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000744 case ConversionSpecifier::xArg:
745 case ConversionSpecifier::XArg:
746 case ConversionSpecifier::nArg:
747 return true;
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000748 case ConversionSpecifier::FreeBSDrArg:
749 case ConversionSpecifier::FreeBSDyArg:
Sunil Srivastavae9e36312016-04-26 23:19:00 +0000750 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
Ted Kremenekea28f832010-07-20 20:04:42 +0000751 default:
752 return false;
753 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000754
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000755 // Handle 'l' flag
Nico Weberce069f12014-08-29 21:05:44 +0000756 case LengthModifier::AsLong: // or AsWideChar
Ted Kremenekea28f832010-07-20 20:04:42 +0000757 switch (CS.getKind()) {
758 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000759 case ConversionSpecifier::DArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000760 case ConversionSpecifier::iArg:
761 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000762 case ConversionSpecifier::OArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000763 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000764 case ConversionSpecifier::UArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000765 case ConversionSpecifier::xArg:
766 case ConversionSpecifier::XArg:
767 case ConversionSpecifier::aArg:
768 case ConversionSpecifier::AArg:
769 case ConversionSpecifier::fArg:
770 case ConversionSpecifier::FArg:
771 case ConversionSpecifier::eArg:
772 case ConversionSpecifier::EArg:
773 case ConversionSpecifier::gArg:
774 case ConversionSpecifier::GArg:
775 case ConversionSpecifier::nArg:
776 case ConversionSpecifier::cArg:
777 case ConversionSpecifier::sArg:
Ted Kremenek91398922012-01-20 22:11:52 +0000778 case ConversionSpecifier::ScanListArg:
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000779 case ConversionSpecifier::ZArg:
Ted Kremenekea28f832010-07-20 20:04:42 +0000780 return true;
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000781 case ConversionSpecifier::FreeBSDrArg:
782 case ConversionSpecifier::FreeBSDyArg:
Sunil Srivastavae9e36312016-04-26 23:19:00 +0000783 return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
Ted Kremenekea28f832010-07-20 20:04:42 +0000784 default:
785 return false;
786 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000787
Ted Kremenekea28f832010-07-20 20:04:42 +0000788 case LengthModifier::AsLongDouble:
789 switch (CS.getKind()) {
790 case ConversionSpecifier::aArg:
791 case ConversionSpecifier::AArg:
792 case ConversionSpecifier::fArg:
793 case ConversionSpecifier::FArg:
794 case ConversionSpecifier::eArg:
795 case ConversionSpecifier::EArg:
796 case ConversionSpecifier::gArg:
797 case ConversionSpecifier::GArg:
798 return true;
Jordan Rose92303592012-09-08 04:00:03 +0000799 // GNU libc extension.
Ted Kremenek6fa57272012-01-24 21:29:54 +0000800 case ConversionSpecifier::dArg:
801 case ConversionSpecifier::iArg:
802 case ConversionSpecifier::oArg:
803 case ConversionSpecifier::uArg:
804 case ConversionSpecifier::xArg:
805 case ConversionSpecifier::XArg:
Jordan Rose92303592012-09-08 04:00:03 +0000806 return !Target.getTriple().isOSDarwin() &&
807 !Target.getTriple().isOSWindows();
Ted Kremenekea28f832010-07-20 20:04:42 +0000808 default:
809 return false;
810 }
Hans Wennborg23926bd2011-12-15 10:25:47 +0000811
812 case LengthModifier::AsAllocate:
813 switch (CS.getKind()) {
814 case ConversionSpecifier::sArg:
815 case ConversionSpecifier::SArg:
Hans Wennborgfd950872012-01-12 15:07:16 +0000816 case ConversionSpecifier::ScanListArg:
Hans Wennborg23926bd2011-12-15 10:25:47 +0000817 return true;
818 default:
819 return false;
820 }
Hans Wennborg6073e312012-01-12 17:11:12 +0000821
822 case LengthModifier::AsMAllocate:
823 switch (CS.getKind()) {
824 case ConversionSpecifier::cArg:
825 case ConversionSpecifier::CArg:
826 case ConversionSpecifier::sArg:
827 case ConversionSpecifier::SArg:
828 case ConversionSpecifier::ScanListArg:
829 return true;
830 default:
831 return false;
832 }
David Majnemer3cba4952013-08-21 21:54:46 +0000833 case LengthModifier::AsInt32:
834 case LengthModifier::AsInt3264:
835 case LengthModifier::AsInt64:
836 switch (CS.getKind()) {
837 case ConversionSpecifier::dArg:
838 case ConversionSpecifier::iArg:
839 case ConversionSpecifier::oArg:
840 case ConversionSpecifier::uArg:
841 case ConversionSpecifier::xArg:
842 case ConversionSpecifier::XArg:
843 return Target.getTriple().isOSMSVCRT();
844 default:
845 return false;
846 }
Hans Wennborg68f42b92014-09-04 21:39:46 +0000847 case LengthModifier::AsWide:
848 switch (CS.getKind()) {
849 case ConversionSpecifier::cArg:
850 case ConversionSpecifier::CArg:
851 case ConversionSpecifier::sArg:
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000852 case ConversionSpecifier::SArg:
853 case ConversionSpecifier::ZArg:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000854 return Target.getTriple().isOSMSVCRT();
855 default:
856 return false;
857 }
Ted Kremenekea28f832010-07-20 20:04:42 +0000858 }
David Blaikiee4d798f2012-01-20 21:50:17 +0000859 llvm_unreachable("Invalid LengthModifier Kind!");
Ted Kremenekea28f832010-07-20 20:04:42 +0000860}
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000861
862bool FormatSpecifier::hasStandardLengthModifier() const {
863 switch (LM.getKind()) {
864 case LengthModifier::None:
865 case LengthModifier::AsChar:
866 case LengthModifier::AsShort:
867 case LengthModifier::AsLong:
868 case LengthModifier::AsLongLong:
869 case LengthModifier::AsIntMax:
870 case LengthModifier::AsSizeT:
871 case LengthModifier::AsPtrDiff:
872 case LengthModifier::AsLongDouble:
873 return true;
874 case LengthModifier::AsAllocate:
875 case LengthModifier::AsMAllocate:
876 case LengthModifier::AsQuad:
David Majnemer3cba4952013-08-21 21:54:46 +0000877 case LengthModifier::AsInt32:
878 case LengthModifier::AsInt3264:
879 case LengthModifier::AsInt64:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000880 case LengthModifier::AsWide:
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000881 return false;
882 }
883 llvm_unreachable("Invalid LengthModifier Kind!");
884}
885
Nico Webereffdb192015-05-18 02:41:17 +0000886bool FormatSpecifier::hasStandardConversionSpecifier(
887 const LangOptions &LangOpt) const {
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000888 switch (CS.getKind()) {
889 case ConversionSpecifier::cArg:
890 case ConversionSpecifier::dArg:
891 case ConversionSpecifier::iArg:
892 case ConversionSpecifier::oArg:
893 case ConversionSpecifier::uArg:
894 case ConversionSpecifier::xArg:
895 case ConversionSpecifier::XArg:
896 case ConversionSpecifier::fArg:
897 case ConversionSpecifier::FArg:
898 case ConversionSpecifier::eArg:
899 case ConversionSpecifier::EArg:
900 case ConversionSpecifier::gArg:
901 case ConversionSpecifier::GArg:
902 case ConversionSpecifier::aArg:
903 case ConversionSpecifier::AArg:
904 case ConversionSpecifier::sArg:
905 case ConversionSpecifier::pArg:
906 case ConversionSpecifier::nArg:
907 case ConversionSpecifier::ObjCObjArg:
908 case ConversionSpecifier::ScanListArg:
909 case ConversionSpecifier::PercentArg:
Mehdi Amini06d367c2016-10-24 20:39:34 +0000910 case ConversionSpecifier::PArg:
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000911 return true;
912 case ConversionSpecifier::CArg:
913 case ConversionSpecifier::SArg:
Erik Pilkingtonfa983902018-10-30 20:31:30 +0000914 return LangOpt.ObjC;
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000915 case ConversionSpecifier::InvalidSpecifier:
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000916 case ConversionSpecifier::FreeBSDbArg:
917 case ConversionSpecifier::FreeBSDDArg:
918 case ConversionSpecifier::FreeBSDrArg:
919 case ConversionSpecifier::FreeBSDyArg:
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000920 case ConversionSpecifier::PrintErrno:
Jordan Rose510260c2012-09-13 02:11:03 +0000921 case ConversionSpecifier::DArg:
922 case ConversionSpecifier::OArg:
923 case ConversionSpecifier::UArg:
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000924 case ConversionSpecifier::ZArg:
Hans Wennborgc9dd9462012-02-22 10:17:01 +0000925 return false;
926 }
927 llvm_unreachable("Invalid ConversionSpecifier Kind!");
928}
929
930bool FormatSpecifier::hasStandardLengthConversionCombination() const {
931 if (LM.getKind() == LengthModifier::AsLongDouble) {
932 switch(CS.getKind()) {
933 case ConversionSpecifier::dArg:
934 case ConversionSpecifier::iArg:
935 case ConversionSpecifier::oArg:
936 case ConversionSpecifier::uArg:
937 case ConversionSpecifier::xArg:
938 case ConversionSpecifier::XArg:
939 return false;
940 default:
941 return true;
942 }
943 }
944 return true;
945}
Hans Wennborg08574d32012-07-27 19:17:46 +0000946
David Blaikie05785d12013-02-20 22:23:23 +0000947Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
Jordan Rose2f9cc042012-09-08 04:00:12 +0000948 if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
949 if (LM.getKind() == LengthModifier::AsLongDouble ||
950 LM.getKind() == LengthModifier::AsQuad) {
Jordan Rose92303592012-09-08 04:00:03 +0000951 LengthModifier FixedLM(LM);
952 FixedLM.setKind(LengthModifier::AsLongLong);
953 return FixedLM;
954 }
Jordan Rose92303592012-09-08 04:00:03 +0000955 }
956
David Blaikie7a30dc52013-02-21 01:47:18 +0000957 return None;
Jordan Rose92303592012-09-08 04:00:03 +0000958}
959
Hans Wennborg08574d32012-07-27 19:17:46 +0000960bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
961 LengthModifier &LM) {
962 assert(isa<TypedefType>(QT) && "Expected a TypedefType");
963 const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
964
965 for (;;) {
966 const IdentifierInfo *Identifier = Typedef->getIdentifier();
967 if (Identifier->getName() == "size_t") {
968 LM.setKind(LengthModifier::AsSizeT);
969 return true;
970 } else if (Identifier->getName() == "ssize_t") {
971 // Not C99, but common in Unix.
972 LM.setKind(LengthModifier::AsSizeT);
973 return true;
974 } else if (Identifier->getName() == "intmax_t") {
975 LM.setKind(LengthModifier::AsIntMax);
976 return true;
977 } else if (Identifier->getName() == "uintmax_t") {
978 LM.setKind(LengthModifier::AsIntMax);
979 return true;
980 } else if (Identifier->getName() == "ptrdiff_t") {
981 LM.setKind(LengthModifier::AsPtrDiff);
982 return true;
983 }
984
985 QualType T = Typedef->getUnderlyingType();
986 if (!isa<TypedefType>(T))
987 break;
988
989 Typedef = cast<TypedefType>(T)->getDecl();
990 }
991 return false;
992}