blob: f22c4f8f64405951e1d65d24fbf48c6c7d6e1dac [file] [log] [blame]
Ted Kremenek02087932010-07-16 02:11:22 +00001//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
Ted Kremeneka2e77b42010-01-27 23:43:25 +00002//
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
Tim Northover314fbfa2018-11-02 13:14:11 +000015#include "clang/AST/FormatString.h"
16#include "clang/AST/OSLog.h"
Ted Kremenek02087932010-07-16 02:11:22 +000017#include "FormatStringParsing.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000018#include "clang/Basic/TargetInfo.h"
Ted Kremeneka2e77b42010-01-27 23:43:25 +000019
Hans Wennborgc3b3da02012-08-07 08:11:26 +000020using clang::analyze_format_string::ArgType;
Ted Kremenek02087932010-07-16 02:11:22 +000021using clang::analyze_format_string::FormatStringHandler;
22using clang::analyze_format_string::LengthModifier;
23using clang::analyze_format_string::OptionalAmount;
Ted Kremenekf03e6d852010-07-20 20:04:27 +000024using clang::analyze_format_string::ConversionSpecifier;
Ted Kremenek02087932010-07-16 02:11:22 +000025using clang::analyze_printf::PrintfSpecifier;
Ted Kremenekd1668192010-02-27 01:41:03 +000026
Ted Kremenekc22f78d2010-01-29 03:16:21 +000027using namespace clang;
Ted Kremeneka2e77b42010-01-27 23:43:25 +000028
Ted Kremenek02087932010-07-16 02:11:22 +000029typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
30 PrintfSpecifierResult;
Ted Kremenekc8b188d2010-02-16 01:46:59 +000031
32//===----------------------------------------------------------------------===//
33// Methods for parsing format strings.
34//===----------------------------------------------------------------------===//
Ted Kremeneka2e77b42010-01-27 23:43:25 +000035
Ted Kremenek02087932010-07-16 02:11:22 +000036using analyze_format_string::ParseNonPositionAmount;
Ted Kremenekc8b188d2010-02-16 01:46:59 +000037
Ted Kremenek02087932010-07-16 02:11:22 +000038static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
Ted Kremenekd1668192010-02-27 01:41:03 +000039 const char *Start, const char *&Beg, const char *E,
40 unsigned *argIndex) {
41 if (argIndex) {
42 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
Chad Rosier6fdf38b2011-08-17 23:08:45 +000043 } else {
Ted Kremenekd1668192010-02-27 01:41:03 +000044 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
Ted Kremenek02087932010-07-16 02:11:22 +000045 analyze_format_string::PrecisionPos);
Ted Kremenekd1668192010-02-27 01:41:03 +000046 if (Amt.isInvalid())
47 return true;
48 FS.setPrecision(Amt);
49 }
50 return false;
51}
52
Ted Kremenek2b417712015-07-02 05:39:16 +000053static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
54 const char *FlagBeg, const char *E, bool Warn) {
55 StringRef Flag(FlagBeg, E - FlagBeg);
56 // Currently there is only one flag.
57 if (Flag == "tt") {
58 FS.setHasObjCTechnicalTerm(FlagBeg);
59 return false;
60 }
61 // Handle either the case of no flag or an invalid flag.
62 if (Warn) {
63 if (Flag == "")
64 H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
65 else
66 H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
67 }
68 return true;
69}
70
Ted Kremenek02087932010-07-16 02:11:22 +000071static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
Ted Kremenek1de17072010-02-04 20:46:58 +000072 const char *&Beg,
Ted Kremenek4a49d982010-02-26 19:18:41 +000073 const char *E,
Hans Wennborg23926bd2011-12-15 10:25:47 +000074 unsigned &argIndex,
Jordan Rose510260c2012-09-13 02:11:03 +000075 const LangOptions &LO,
Fariborz Jahanian6485fe42014-09-09 23:10:54 +000076 const TargetInfo &Target,
Dimitry Andric6b5ed342015-02-19 22:32:33 +000077 bool Warn,
78 bool isFreeBSDKPrintf) {
Ted Kremenekc8b188d2010-02-16 01:46:59 +000079
Ted Kremenekf03e6d852010-07-20 20:04:27 +000080 using namespace clang::analyze_format_string;
Ted Kremenek176f7d62010-01-29 02:13:53 +000081 using namespace clang::analyze_printf;
Ted Kremenekc8b188d2010-02-16 01:46:59 +000082
Ted Kremeneka2e77b42010-01-27 23:43:25 +000083 const char *I = Beg;
Craig Topper25542942014-05-20 04:30:07 +000084 const char *Start = nullptr;
Ted Kremeneka2e77b42010-01-27 23:43:25 +000085 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86
87 // Look for a '%' character that indicates the start of a format specifier.
Ted Kremenekb5c98ef2010-01-28 23:56:52 +000088 for ( ; I != E ; ++I) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +000089 char c = *I;
Ted Kremeneka2e77b42010-01-27 23:43:25 +000090 if (c == '\0') {
91 // Detect spurious null characters, which are likely errors.
92 H.HandleNullChar(I);
93 return true;
94 }
95 if (c == '%') {
Ted Kremenekb5c98ef2010-01-28 23:56:52 +000096 Start = I++; // Record the start of the format specifier.
Ted Kremeneka2e77b42010-01-27 23:43:25 +000097 break;
98 }
99 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000100
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000101 // No format specifier found?
102 if (!Start)
103 return false;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000104
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000105 if (I == E) {
106 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000107 if (Warn)
108 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000109 return true;
110 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000111
Ted Kremenek02087932010-07-16 02:11:22 +0000112 PrintfSpecifier FS;
Ted Kremenekd1668192010-02-27 01:41:03 +0000113 if (ParseArgPosition(H, FS, Start, I, E))
114 return true;
115
116 if (I == E) {
117 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000118 if (Warn)
119 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremenekd1668192010-02-27 01:41:03 +0000120 return true;
121 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000122
Mehdi Amini06d367c2016-10-24 20:39:34 +0000123 if (*I == '{') {
Akira Hatanaka189359d2018-07-10 00:50:25 +0000124 ++I;
125 unsigned char PrivacyFlags = 0;
126 StringRef MatchedStr;
Mehdi Amini06d367c2016-10-24 20:39:34 +0000127
Akira Hatanaka189359d2018-07-10 00:50:25 +0000128 do {
129 StringRef Str(I, E - I);
Akira Hatanakad572cf42018-11-06 07:05:14 +0000130 std::string Match = "^[[:space:]]*"
131 "(private|public|sensitive|mask\\.[^[:space:],}]*)"
Akira Hatanakafb1e4462018-11-06 06:26:17 +0000132 "[[:space:]]*(,|})";
Akira Hatanaka189359d2018-07-10 00:50:25 +0000133 llvm::Regex R(Match);
134 SmallVector<StringRef, 2> Matches;
135
136 if (R.match(Str, &Matches)) {
137 MatchedStr = Matches[1];
138 I += Matches[0].size();
139
Akira Hatanakae18c2d22018-07-11 22:19:14 +0000140 // Set the privacy flag if the privacy annotation in the
141 // comma-delimited segment is at least as strict as the privacy
142 // annotations in previous comma-delimited segments.
Akira Hatanakad572cf42018-11-06 07:05:14 +0000143 if (MatchedStr.startswith("mask")) {
144 StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
145 unsigned Size = MaskType.size();
146 if (Warn && (Size == 0 || Size > 8))
147 H.handleInvalidMaskType(MaskType);
148 FS.setMaskType(MaskType);
149 } else if (MatchedStr.equals("sensitive"))
Akira Hatanakafb1e4462018-11-06 06:26:17 +0000150 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
151 else if (PrivacyFlags !=
152 clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
153 MatchedStr.equals("private"))
Akira Hatanaka189359d2018-07-10 00:50:25 +0000154 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
Akira Hatanakae18c2d22018-07-11 22:19:14 +0000155 else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
Akira Hatanaka189359d2018-07-10 00:50:25 +0000156 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
157 } else {
158 size_t CommaOrBracePos =
159 Str.find_if([](char c) { return c == ',' || c == '}'; });
Akira Hatanaka189359d2018-07-10 00:50:25 +0000160
161 if (CommaOrBracePos == StringRef::npos) {
162 // Neither a comma nor the closing brace was found.
163 if (Warn)
164 H.HandleIncompleteSpecifier(Start, E - Start);
165 return true;
166 }
Akira Hatanakae18c2d22018-07-11 22:19:14 +0000167
168 I += CommaOrBracePos + 1;
Akira Hatanaka189359d2018-07-10 00:50:25 +0000169 }
170 // Continue until the closing brace is found.
171 } while (*(I - 1) == ',');
172
173 // Set the privacy flag.
174 switch (PrivacyFlags) {
175 case 0:
176 break;
177 case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
178 FS.setIsPrivate(MatchedStr.data());
179 break;
180 case clang::analyze_os_log::OSLogBufferItem::IsPublic:
181 FS.setIsPublic(MatchedStr.data());
182 break;
Akira Hatanakafb1e4462018-11-06 06:26:17 +0000183 case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
184 FS.setIsSensitive(MatchedStr.data());
185 break;
Akira Hatanaka189359d2018-07-10 00:50:25 +0000186 default:
187 llvm_unreachable("Unexpected privacy flag value");
Mehdi Amini06d367c2016-10-24 20:39:34 +0000188 }
189 }
190
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000191 // Look for flags (if any).
192 bool hasMore = true;
193 for ( ; I != E; ++I) {
194 switch (*I) {
195 default: hasMore = false; break;
NAKAMURA Takumif9cbcc42011-01-27 07:10:08 +0000196 case '\'':
Ted Kremeneka322cae2011-01-08 05:28:38 +0000197 // FIXME: POSIX specific. Always accept?
198 FS.setHasThousandsGrouping(I);
199 break;
Tom Careb49ec692010-06-17 19:00:27 +0000200 case '-': FS.setIsLeftJustified(I); break;
201 case '+': FS.setHasPlusPrefix(I); break;
202 case ' ': FS.setHasSpacePrefix(I); break;
203 case '#': FS.setHasAlternativeForm(I); break;
204 case '0': FS.setHasLeadingZeros(I); break;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000205 }
206 if (!hasMore)
207 break;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000208 }
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000209
210 if (I == E) {
211 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000212 if (Warn)
213 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000214 return true;
215 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000216
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000217 // Look for the field width (if any).
Ted Kremenekd1668192010-02-27 01:41:03 +0000218 if (ParseFieldWidth(H, FS, Start, I, E,
Craig Topper25542942014-05-20 04:30:07 +0000219 FS.usesPositionalArg() ? nullptr : &argIndex))
Ted Kremenekd1668192010-02-27 01:41:03 +0000220 return true;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000221
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000222 if (I == E) {
223 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000224 if (Warn)
225 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000226 return true;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000227 }
228
229 // Look for the precision (if any).
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000230 if (*I == '.') {
Ted Kremenekc22f78d2010-01-29 03:16:21 +0000231 ++I;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000232 if (I == E) {
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000233 if (Warn)
234 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000235 return true;
236 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000237
Ted Kremenekd1668192010-02-27 01:41:03 +0000238 if (ParsePrecision(H, FS, Start, I, E,
Craig Topper25542942014-05-20 04:30:07 +0000239 FS.usesPositionalArg() ? nullptr : &argIndex))
Ted Kremenekd1668192010-02-27 01:41:03 +0000240 return true;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000241
242 if (I == E) {
243 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000244 if (Warn)
245 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000246 return true;
247 }
248 }
249
250 // Look for the length modifier.
Hans Wennborg23926bd2011-12-15 10:25:47 +0000251 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000252 // No more characters left?
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000253 if (Warn)
254 H.HandleIncompleteSpecifier(Start, E - Start);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000255 return true;
256 }
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000257
Ted Kremenek2b417712015-07-02 05:39:16 +0000258 // Look for the Objective-C modifier flags, if any.
259 // We parse these here, even if they don't apply to
260 // the conversion specifier, and then emit an error
261 // later if the conversion specifier isn't '@'. This
262 // enables better recovery, and we don't know if
263 // these flags are applicable until later.
264 const char *ObjCModifierFlagsStart = nullptr,
265 *ObjCModifierFlagsEnd = nullptr;
266 if (*I == '[') {
267 ObjCModifierFlagsStart = I;
268 ++I;
269 auto flagStart = I;
270 for (;; ++I) {
271 ObjCModifierFlagsEnd = I;
272 if (I == E) {
273 if (Warn)
274 H.HandleIncompleteSpecifier(Start, E - Start);
275 return true;
276 }
277 // Did we find the closing ']'?
278 if (*I == ']') {
279 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
280 return true;
281 ++I;
282 break;
283 }
284 // There are no separators defined yet for multiple
285 // Objective-C modifier flags. When those are
286 // defined, this is the place to check.
287 }
288 }
289
Ted Kremenek23a71a12010-01-29 20:29:53 +0000290 if (*I == '\0') {
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000291 // Detect spurious null characters, which are likely errors.
292 H.HandleNullChar(I);
293 return true;
Ted Kremenek23a71a12010-01-29 20:29:53 +0000294 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000295
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000296 // Finally, look for the conversion specifier.
Ted Kremenekfee0e962010-01-28 02:46:17 +0000297 const char *conversionPosition = I++;
Ted Kremenek94af5752010-01-29 02:40:24 +0000298 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000299 switch (*conversionPosition) {
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000300 default:
Ted Kremenek94af5752010-01-29 02:40:24 +0000301 break;
Ted Kremenekc06ead62010-01-28 00:55:28 +0000302 // C99: 7.19.6.1 (section 8).
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000303 case '%': k = ConversionSpecifier::PercentArg; break;
304 case 'A': k = ConversionSpecifier::AArg; break;
305 case 'E': k = ConversionSpecifier::EArg; break;
306 case 'F': k = ConversionSpecifier::FArg; break;
307 case 'G': k = ConversionSpecifier::GArg; break;
308 case 'X': k = ConversionSpecifier::XArg; break;
309 case 'a': k = ConversionSpecifier::aArg; break;
Ted Kremenekab0fe8a2010-07-20 20:03:49 +0000310 case 'c': k = ConversionSpecifier::cArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000311 case 'd': k = ConversionSpecifier::dArg; break;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000312 case 'e': k = ConversionSpecifier::eArg; break;
313 case 'f': k = ConversionSpecifier::fArg; break;
314 case 'g': k = ConversionSpecifier::gArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000315 case 'i': k = ConversionSpecifier::iArg; break;
Ted Kremenek516ef222010-07-20 20:04:10 +0000316 case 'n': k = ConversionSpecifier::nArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000317 case 'o': k = ConversionSpecifier::oArg; break;
David Majnemer3cba4952013-08-21 21:54:46 +0000318 case 'p': k = ConversionSpecifier::pArg; break;
319 case 's': k = ConversionSpecifier::sArg; break;
Ted Kremenekfee0e962010-01-28 02:46:17 +0000320 case 'u': k = ConversionSpecifier::uArg; break;
321 case 'x': k = ConversionSpecifier::xArg; break;
Ted Kremeneka322cae2011-01-08 05:28:38 +0000322 // POSIX specific.
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000323 case 'C': k = ConversionSpecifier::CArg; break;
Ted Kremenek348d1492010-07-20 20:04:15 +0000324 case 'S': k = ConversionSpecifier::SArg; break;
Mehdi Amini06d367c2016-10-24 20:39:34 +0000325 // Apple extension for os_log
326 case 'P':
327 k = ConversionSpecifier::PArg;
328 break;
Ted Kremenekc06ead62010-01-28 00:55:28 +0000329 // Objective-C.
Ted Kremenek23a71a12010-01-29 20:29:53 +0000330 case '@': k = ConversionSpecifier::ObjCObjArg; break;
Ted Kremenek2a0cd592010-02-09 00:04:09 +0000331 // Glibc specific.
Ted Kremenek23a71a12010-01-29 20:29:53 +0000332 case 'm': k = ConversionSpecifier::PrintErrno; break;
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000333 // FreeBSD kernel specific.
334 case 'b':
335 if (isFreeBSDKPrintf)
336 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
337 break;
338 case 'r':
339 if (isFreeBSDKPrintf)
340 k = ConversionSpecifier::FreeBSDrArg; // int
341 break;
342 case 'y':
343 if (isFreeBSDKPrintf)
344 k = ConversionSpecifier::FreeBSDyArg; // int
345 break;
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000346 // Apple-specific.
Jordan Rose510260c2012-09-13 02:11:03 +0000347 case 'D':
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000348 if (isFreeBSDKPrintf)
349 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
350 else if (Target.getTriple().isOSDarwin())
Jordan Rose510260c2012-09-13 02:11:03 +0000351 k = ConversionSpecifier::DArg;
352 break;
353 case 'O':
354 if (Target.getTriple().isOSDarwin())
355 k = ConversionSpecifier::OArg;
356 break;
357 case 'U':
358 if (Target.getTriple().isOSDarwin())
359 k = ConversionSpecifier::UArg;
360 break;
Hans Wennborgc597b4c2014-09-07 03:03:51 +0000361 // MS specific.
362 case 'Z':
363 if (Target.getTriple().isOSMSVCRT())
364 k = ConversionSpecifier::ZArg;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000365 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000366
Ted Kremenek2b417712015-07-02 05:39:16 +0000367 // Check to see if we used the Objective-C modifier flags with
368 // a conversion specifier other than '@'.
369 if (k != ConversionSpecifier::ObjCObjArg &&
370 k != ConversionSpecifier::InvalidSpecifier &&
371 ObjCModifierFlagsStart) {
372 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
373 ObjCModifierFlagsEnd + 1,
374 conversionPosition);
375 return true;
376 }
Mehdi Amini06d367c2016-10-24 20:39:34 +0000377
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000378 PrintfConversionSpecifier CS(conversionPosition, k);
Ted Kremenek4a49d982010-02-26 19:18:41 +0000379 FS.setConversionSpecifier(CS);
Ted Kremenekd1668192010-02-27 01:41:03 +0000380 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
Ted Kremenek4a49d982010-02-26 19:18:41 +0000381 FS.setArgIndex(argIndex++);
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000382 // FreeBSD kernel specific.
383 if (k == ConversionSpecifier::FreeBSDbArg ||
384 k == ConversionSpecifier::FreeBSDDArg)
385 argIndex++;
Ted Kremenek94af5752010-01-29 02:40:24 +0000386
387 if (k == ConversionSpecifier::InvalidSpecifier) {
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000388 unsigned Len = I - Start;
389 if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
390 CS.setEndScanList(Start + Len);
391 FS.setConversionSpecifier(CS);
392 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000393 // Assume the conversion takes one argument.
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000394 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
Ted Kremenek94af5752010-01-29 02:40:24 +0000395 }
Ted Kremenek02087932010-07-16 02:11:22 +0000396 return PrintfSpecifierResult(Start, FS);
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000397}
398
Ted Kremenek02087932010-07-16 02:11:22 +0000399bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
400 const char *I,
Hans Wennborg23926bd2011-12-15 10:25:47 +0000401 const char *E,
Jordan Rose510260c2012-09-13 02:11:03 +0000402 const LangOptions &LO,
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000403 const TargetInfo &Target,
404 bool isFreeBSDKPrintf) {
Ted Kremenek4a49d982010-02-26 19:18:41 +0000405
406 unsigned argIndex = 0;
407
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000408 // Keep looking for a format specifier until we have exhausted the string.
409 while (I != E) {
Hans Wennborg23926bd2011-12-15 10:25:47 +0000410 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000411 LO, Target, true,
412 isFreeBSDKPrintf);
Ted Kremenek94af5752010-01-29 02:40:24 +0000413 // Did a fail-stop error of any kind occur when parsing the specifier?
414 // If so, don't do any more processing.
415 if (FSR.shouldStop())
Dmitri Gribenko76bb5cabfa2012-09-10 21:20:09 +0000416 return true;
Ted Kremenek94af5752010-01-29 02:40:24 +0000417 // Did we exhaust the string or encounter an error that
418 // we can recover from?
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000419 if (!FSR.hasValue())
Ted Kremenek94af5752010-01-29 02:40:24 +0000420 continue;
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000421 // We have a format specifier. Pass it to the callback.
Ted Kremenek02087932010-07-16 02:11:22 +0000422 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
Ted Kremenekfee0e962010-01-28 02:46:17 +0000423 I - FSR.getStart()))
Ted Kremenek23a71a12010-01-29 20:29:53 +0000424 return true;
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000425 }
426 assert(I == E && "Format string not exhausted");
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000427 return false;
428}
Ted Kremeneka2e77b42010-01-27 23:43:25 +0000429
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000430bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
431 const char *E,
432 const LangOptions &LO,
433 const TargetInfo &Target) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000434
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000435 unsigned argIndex = 0;
Fangrui Song6907ce22018-07-30 19:24:48 +0000436
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000437 // Keep looking for a %s format specifier until we have exhausted the string.
438 FormatStringHandler H;
439 while (I != E) {
440 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000441 LO, Target, false,
442 false);
Fariborz Jahanian6485fe42014-09-09 23:10:54 +0000443 // Did a fail-stop error of any kind occur when parsing the specifier?
444 // If so, don't do any more processing.
445 if (FSR.shouldStop())
446 return false;
447 // Did we exhaust the string or encounter an error that
448 // we can recover from?
449 if (!FSR.hasValue())
450 continue;
451 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
452 // Return true if this a %s format specifier.
453 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
454 return true;
455 }
456 return false;
457}
458
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000459//===----------------------------------------------------------------------===//
Ted Kremenek02087932010-07-16 02:11:22 +0000460// Methods on PrintfSpecifier.
Tom Careb7042702010-06-09 04:11:11 +0000461//===----------------------------------------------------------------------===//
462
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000463ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
464 bool IsObjCLiteral) const {
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000465 const PrintfConversionSpecifier &CS = getConversionSpecifier();
NAKAMURA Takumif9cbcc42011-01-27 07:10:08 +0000466
Ted Kremenek79db7b72010-01-29 22:59:32 +0000467 if (!CS.consumesDataArgument())
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000468 return ArgType::Invalid();
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000469
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000470 if (CS.getKind() == ConversionSpecifier::cArg)
471 switch (LM.getKind()) {
Hans Wennborg1b231582014-09-04 21:39:52 +0000472 case LengthModifier::None:
473 return Ctx.IntTy;
Hans Wennborga5b1aa92011-12-09 12:22:12 +0000474 case LengthModifier::AsLong:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000475 case LengthModifier::AsWide:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000476 return ArgType(ArgType::WIntTy, "wint_t");
Hans Wennborg1b231582014-09-04 21:39:52 +0000477 case LengthModifier::AsShort:
478 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
479 return Ctx.IntTy;
Galina Kistanovade7e2212017-06-03 06:23:51 +0000480 LLVM_FALLTHROUGH;
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000481 default:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000482 return ArgType::Invalid();
Ted Kremenek5f0c0662010-08-24 22:24:51 +0000483 }
NAKAMURA Takumif9cbcc42011-01-27 07:10:08 +0000484
Ted Kremenek79db7b72010-01-29 22:59:32 +0000485 if (CS.isIntArg())
Tom Careb7042702010-06-09 04:11:11 +0000486 switch (LM.getKind()) {
487 case LengthModifier::AsLongDouble:
Ted Kremenek6fa57272012-01-24 21:29:54 +0000488 // GNU extension.
489 return Ctx.LongLongTy;
David Majnemer3cba4952013-08-21 21:54:46 +0000490 case LengthModifier::None:
491 return Ctx.IntTy;
492 case LengthModifier::AsInt32:
493 return ArgType(Ctx.IntTy, "__int32");
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000494 case LengthModifier::AsChar: return ArgType::AnyCharTy;
Tom Careb7042702010-06-09 04:11:11 +0000495 case LengthModifier::AsShort: return Ctx.ShortTy;
496 case LengthModifier::AsLong: return Ctx.LongTy;
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000497 case LengthModifier::AsLongLong:
498 case LengthModifier::AsQuad:
499 return Ctx.LongLongTy;
David Majnemer3cba4952013-08-21 21:54:46 +0000500 case LengthModifier::AsInt64:
501 return ArgType(Ctx.LongLongTy, "__int64");
Hans Wennborg772e9272011-12-07 10:33:11 +0000502 case LengthModifier::AsIntMax:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000503 return ArgType(Ctx.getIntMaxType(), "intmax_t");
Hans Wennborg27541db2011-10-27 08:29:09 +0000504 case LengthModifier::AsSizeT:
JF Bastienec7d7f32018-06-22 21:54:40 +0000505 return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
David Majnemer3cba4952013-08-21 21:54:46 +0000506 case LengthModifier::AsInt3264:
David Majnemera39da8e2013-08-22 07:53:21 +0000507 return Ctx.getTargetInfo().getTriple().isArch64Bit()
508 ? ArgType(Ctx.LongLongTy, "__int64")
509 : ArgType(Ctx.IntTy, "__int32");
Hans Wennborg772e9272011-12-07 10:33:11 +0000510 case LengthModifier::AsPtrDiff:
Alex Lorenzb2043ac2018-07-05 22:51:11 +0000511 return ArgType::makePtrdiffT(
512 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
Hans Wennborg23926bd2011-12-15 10:25:47 +0000513 case LengthModifier::AsAllocate:
Hans Wennborg6073e312012-01-12 17:11:12 +0000514 case LengthModifier::AsMAllocate:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000515 case LengthModifier::AsWide:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000516 return ArgType::Invalid();
Ted Kremenek79db7b72010-01-29 22:59:32 +0000517 }
518
519 if (CS.isUIntArg())
Tom Careb7042702010-06-09 04:11:11 +0000520 switch (LM.getKind()) {
521 case LengthModifier::AsLongDouble:
Ted Kremenek6fa57272012-01-24 21:29:54 +0000522 // GNU extension.
523 return Ctx.UnsignedLongLongTy;
David Majnemer3cba4952013-08-21 21:54:46 +0000524 case LengthModifier::None:
525 return Ctx.UnsignedIntTy;
526 case LengthModifier::AsInt32:
527 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
Tom Careb7042702010-06-09 04:11:11 +0000528 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
529 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
530 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000531 case LengthModifier::AsLongLong:
532 case LengthModifier::AsQuad:
533 return Ctx.UnsignedLongLongTy;
David Majnemer3cba4952013-08-21 21:54:46 +0000534 case LengthModifier::AsInt64:
535 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
Hans Wennborg772e9272011-12-07 10:33:11 +0000536 case LengthModifier::AsIntMax:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000537 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
Tom Careb7042702010-06-09 04:11:11 +0000538 case LengthModifier::AsSizeT:
JF Bastienec7d7f32018-06-22 21:54:40 +0000539 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
David Majnemer3cba4952013-08-21 21:54:46 +0000540 case LengthModifier::AsInt3264:
541 return Ctx.getTargetInfo().getTriple().isArch64Bit()
David Majnemera39da8e2013-08-22 07:53:21 +0000542 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
543 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
Tom Careb7042702010-06-09 04:11:11 +0000544 case LengthModifier::AsPtrDiff:
Alex Lorenzb2043ac2018-07-05 22:51:11 +0000545 return ArgType::makePtrdiffT(
546 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
Hans Wennborg23926bd2011-12-15 10:25:47 +0000547 case LengthModifier::AsAllocate:
Hans Wennborg6073e312012-01-12 17:11:12 +0000548 case LengthModifier::AsMAllocate:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000549 case LengthModifier::AsWide:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000550 return ArgType::Invalid();
Ted Kremenek79db7b72010-01-29 22:59:32 +0000551 }
Ted Kremenekc8b188d2010-02-16 01:46:59 +0000552
Ted Kremenek016b6052010-02-01 23:23:50 +0000553 if (CS.isDoubleArg()) {
Tom Careb7042702010-06-09 04:11:11 +0000554 if (LM.getKind() == LengthModifier::AsLongDouble)
Ted Kremenek016b6052010-02-01 23:23:50 +0000555 return Ctx.LongDoubleTy;
Ted Kremenek9ff02052010-01-30 01:02:18 +0000556 return Ctx.DoubleTy;
Ted Kremenek016b6052010-02-01 23:23:50 +0000557 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000558
Hans Wennborgabc1e222012-08-07 09:13:19 +0000559 if (CS.getKind() == ConversionSpecifier::nArg) {
560 switch (LM.getKind()) {
561 case LengthModifier::None:
562 return ArgType::PtrTo(Ctx.IntTy);
563 case LengthModifier::AsChar:
564 return ArgType::PtrTo(Ctx.SignedCharTy);
565 case LengthModifier::AsShort:
566 return ArgType::PtrTo(Ctx.ShortTy);
567 case LengthModifier::AsLong:
568 return ArgType::PtrTo(Ctx.LongTy);
569 case LengthModifier::AsLongLong:
570 case LengthModifier::AsQuad:
571 return ArgType::PtrTo(Ctx.LongLongTy);
572 case LengthModifier::AsIntMax:
573 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
574 case LengthModifier::AsSizeT:
Alexander Shaposhnikov441c1d92017-07-14 22:57:00 +0000575 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
Hans Wennborgabc1e222012-08-07 09:13:19 +0000576 case LengthModifier::AsPtrDiff:
577 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
578 case LengthModifier::AsLongDouble:
579 return ArgType(); // FIXME: Is this a known extension?
580 case LengthModifier::AsAllocate:
581 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000582 case LengthModifier::AsInt32:
583 case LengthModifier::AsInt3264:
584 case LengthModifier::AsInt64:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000585 case LengthModifier::AsWide:
Hans Wennborgabc1e222012-08-07 09:13:19 +0000586 return ArgType::Invalid();
587 }
588 }
589
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000590 switch (CS.getKind()) {
Hans Wennborg0c353262011-12-09 15:57:33 +0000591 case ConversionSpecifier::sArg:
Nico Weber496cdc22012-01-31 01:43:25 +0000592 if (LM.getKind() == LengthModifier::AsWideChar) {
593 if (IsObjCLiteral)
Jordan Rose0e5badd2012-12-05 18:44:49 +0000594 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
595 "const unichar *");
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000596 return ArgType(ArgType::WCStrTy, "wchar_t *");
Nico Weber496cdc22012-01-31 01:43:25 +0000597 }
Hans Wennborg68f42b92014-09-04 21:39:46 +0000598 if (LM.getKind() == LengthModifier::AsWide)
599 return ArgType(ArgType::WCStrTy, "wchar_t *");
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000600 return ArgType::CStrTy;
Ted Kremenek348d1492010-07-20 20:04:15 +0000601 case ConversionSpecifier::SArg:
Nico Weber496cdc22012-01-31 01:43:25 +0000602 if (IsObjCLiteral)
Jordan Rose0e5badd2012-12-05 18:44:49 +0000603 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
604 "const unichar *");
Hans Wennborg1b231582014-09-04 21:39:52 +0000605 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
606 LM.getKind() == LengthModifier::AsShort)
607 return ArgType::CStrTy;
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000608 return ArgType(ArgType::WCStrTy, "wchar_t *");
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000609 case ConversionSpecifier::CArg:
Nico Weber496cdc22012-01-31 01:43:25 +0000610 if (IsObjCLiteral)
Jordan Rose0e5badd2012-12-05 18:44:49 +0000611 return ArgType(Ctx.UnsignedShortTy, "unichar");
Hans Wennborg1b231582014-09-04 21:39:52 +0000612 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
613 LM.getKind() == LengthModifier::AsShort)
614 return Ctx.IntTy;
Hans Wennborg0d81e012013-05-10 10:08:40 +0000615 return ArgType(Ctx.WideCharTy, "wchar_t");
Ted Kremenek1ce32be2010-07-20 20:04:04 +0000616 case ConversionSpecifier::pArg:
Mehdi Amini06d367c2016-10-24 20:39:34 +0000617 case ConversionSpecifier::PArg:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000618 return ArgType::CPointerTy;
Ted Kremenek9b1f3d42012-01-25 00:04:09 +0000619 case ConversionSpecifier::ObjCObjArg:
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000620 return ArgType::ObjCPointerTy;
Ted Kremenek74a4ce72010-02-24 00:05:54 +0000621 default:
622 break;
623 }
Ted Kremenek4a49d982010-02-26 19:18:41 +0000624
Ted Kremenek79db7b72010-01-29 22:59:32 +0000625 // FIXME: Handle other cases.
Hans Wennborgc3b3da02012-08-07 08:11:26 +0000626 return ArgType();
Ted Kremenek79db7b72010-01-29 22:59:32 +0000627}
628
Hans Wennborgd99d6882012-02-15 09:59:46 +0000629bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
630 ASTContext &Ctx, bool IsObjCLiteral) {
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000631 // %n is different from other conversion specifiers; don't try to fix it.
632 if (CS.getKind() == ConversionSpecifier::nArg)
633 return false;
634
Jordan Rose68f6d3b2012-05-30 21:53:13 +0000635 // Handle Objective-C objects first. Note that while the '%@' specifier will
636 // not warn for structure pointer or void pointer arguments (because that's
637 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
638 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
639 if (QT->isObjCRetainableType()) {
640 if (!IsObjCLiteral)
641 return false;
642
643 CS.setKind(ConversionSpecifier::ObjCObjArg);
644
645 // Disable irrelevant flags
646 HasThousandsGrouping = false;
647 HasPlusPrefix = false;
648 HasSpacePrefix = false;
649 HasAlternativeForm = false;
650 HasLeadingZeroes = false;
651 Precision.setHowSpecified(OptionalAmount::NotSpecified);
652 LM.setKind(LengthModifier::None);
653
654 return true;
655 }
656
657 // Handle strings next (char *, wchar_t *)
Tom Careb7042702010-06-09 04:11:11 +0000658 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
Ted Kremenek563e3ed2010-07-20 20:03:58 +0000659 CS.setKind(ConversionSpecifier::sArg);
Tom Careb7042702010-06-09 04:11:11 +0000660
Tom Care00554632010-06-11 04:22:02 +0000661 // Disable irrelevant flags
662 HasAlternativeForm = 0;
663 HasLeadingZeroes = 0;
664
Tom Careb7042702010-06-09 04:11:11 +0000665 // Set the long length modifier for wide characters
666 if (QT->getPointeeType()->isWideCharType())
667 LM.setKind(LengthModifier::AsWideChar);
Hans Wennborg2027de32011-12-09 10:51:29 +0000668 else
669 LM.setKind(LengthModifier::None);
Tom Careb7042702010-06-09 04:11:11 +0000670
671 return true;
672 }
673
Jordan Rose614e72b2012-06-04 22:49:02 +0000674 // If it's an enum, get its underlying type.
675 if (const EnumType *ETy = QT->getAs<EnumType>())
676 QT = ETy->getDecl()->getIntegerType();
677
Tom Careb7042702010-06-09 04:11:11 +0000678 // We can only work with builtin types.
Tom Careb7042702010-06-09 04:11:11 +0000679 const BuiltinType *BT = QT->getAs<BuiltinType>();
John McCall59207972011-10-18 22:28:37 +0000680 if (!BT)
681 return false;
Tom Care00554632010-06-11 04:22:02 +0000682
Tom Careb7042702010-06-09 04:11:11 +0000683 // Set length modifier
684 switch (BT->getKind()) {
Eli Friedman7ec652a2011-04-27 22:06:20 +0000685 case BuiltinType::Bool:
686 case BuiltinType::WChar_U:
687 case BuiltinType::WChar_S:
Richard Smith3a8244d2018-05-01 05:02:45 +0000688 case BuiltinType::Char8: // FIXME: Treat like 'char'?
Eli Friedman7ec652a2011-04-27 22:06:20 +0000689 case BuiltinType::Char16:
690 case BuiltinType::Char32:
691 case BuiltinType::UInt128:
692 case BuiltinType::Int128:
Anton Korobeynikovf0c267e2011-10-14 23:23:15 +0000693 case BuiltinType::Half:
Sjoerd Meijercc623ad2017-09-08 15:15:00 +0000694 case BuiltinType::Float16:
Nemanja Ivanovicbb1ea2d2016-05-09 08:52:33 +0000695 case BuiltinType::Float128:
Leonard Chanf921d852018-06-04 16:07:52 +0000696 case BuiltinType::ShortAccum:
697 case BuiltinType::Accum:
698 case BuiltinType::LongAccum:
699 case BuiltinType::UShortAccum:
700 case BuiltinType::UAccum:
701 case BuiltinType::ULongAccum:
Leonard Chanab80f3c2018-06-14 14:53:51 +0000702 case BuiltinType::ShortFract:
703 case BuiltinType::Fract:
704 case BuiltinType::LongFract:
705 case BuiltinType::UShortFract:
706 case BuiltinType::UFract:
707 case BuiltinType::ULongFract:
708 case BuiltinType::SatShortAccum:
709 case BuiltinType::SatAccum:
710 case BuiltinType::SatLongAccum:
711 case BuiltinType::SatUShortAccum:
712 case BuiltinType::SatUAccum:
713 case BuiltinType::SatULongAccum:
714 case BuiltinType::SatShortFract:
715 case BuiltinType::SatFract:
716 case BuiltinType::SatLongFract:
717 case BuiltinType::SatUShortFract:
718 case BuiltinType::SatUFract:
719 case BuiltinType::SatULongFract:
John McCall59207972011-10-18 22:28:37 +0000720 // Various types which are non-trivial to correct.
Eli Friedman7ec652a2011-04-27 22:06:20 +0000721 return false;
722
Alexey Bader954ba212016-04-08 13:40:33 +0000723#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
724 case BuiltinType::Id:
Alexey Baderb62f1442016-04-13 08:33:41 +0000725#include "clang/Basic/OpenCLImageTypes.def"
Andrew Savonichev3fee3512018-11-08 11:25:41 +0000726#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
727 case BuiltinType::Id:
728#include "clang/Basic/OpenCLExtensionTypes.def"
John McCall59207972011-10-18 22:28:37 +0000729#define SIGNED_TYPE(Id, SingletonId)
730#define UNSIGNED_TYPE(Id, SingletonId)
731#define FLOATING_TYPE(Id, SingletonId)
732#define BUILTIN_TYPE(Id, SingletonId) \
733 case BuiltinType::Id:
734#include "clang/AST/BuiltinTypes.def"
Eli Friedman7ec652a2011-04-27 22:06:20 +0000735 // Misc other stuff which doesn't make sense here.
736 return false;
737
738 case BuiltinType::UInt:
739 case BuiltinType::Int:
740 case BuiltinType::Float:
741 case BuiltinType::Double:
Tom Care00554632010-06-11 04:22:02 +0000742 LM.setKind(LengthModifier::None);
Tom Careb7042702010-06-09 04:11:11 +0000743 break;
Tom Care00554632010-06-11 04:22:02 +0000744
Ted Kremenek12a37de2010-10-21 04:00:58 +0000745 case BuiltinType::Char_U:
746 case BuiltinType::UChar:
747 case BuiltinType::Char_S:
748 case BuiltinType::SChar:
749 LM.setKind(LengthModifier::AsChar);
750 break;
751
752 case BuiltinType::Short:
753 case BuiltinType::UShort:
754 LM.setKind(LengthModifier::AsShort);
755 break;
756
Tom Careb7042702010-06-09 04:11:11 +0000757 case BuiltinType::Long:
758 case BuiltinType::ULong:
759 LM.setKind(LengthModifier::AsLong);
760 break;
761
762 case BuiltinType::LongLong:
763 case BuiltinType::ULongLong:
764 LM.setKind(LengthModifier::AsLongLong);
765 break;
766
767 case BuiltinType::LongDouble:
768 LM.setKind(LengthModifier::AsLongDouble);
769 break;
770 }
771
Hans Wennborgf99d04f2011-10-18 08:10:06 +0000772 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
Richard Smith2bf7fdb2013-01-02 11:42:31 +0000773 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
Hans Wennborg08574d32012-07-27 19:17:46 +0000774 namedTypeToLengthModifier(QT, LM);
Hans Wennborgf99d04f2011-10-18 08:10:06 +0000775
Jordan Roseaa7a3b32013-01-17 18:47:16 +0000776 // If fixing the length modifier was enough, we might be done.
Jordan Rose92303592012-09-08 04:00:03 +0000777 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
Jordan Roseaa7a3b32013-01-17 18:47:16 +0000778 // If we're going to offer a fix anyway, make sure the sign matches.
779 switch (CS.getKind()) {
780 case ConversionSpecifier::uArg:
781 case ConversionSpecifier::UArg:
782 if (QT->isSignedIntegerType())
783 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
784 break;
785 case ConversionSpecifier::dArg:
786 case ConversionSpecifier::DArg:
787 case ConversionSpecifier::iArg:
Jordan Rose1eb34292013-01-17 22:34:10 +0000788 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
Jordan Roseaa7a3b32013-01-17 18:47:16 +0000789 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
790 break;
791 default:
792 // Other specifiers do not have signed/unsigned variants.
793 break;
794 }
795
Jordan Rose92303592012-09-08 04:00:03 +0000796 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
797 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
798 return true;
799 }
Hans Wennborgd99d6882012-02-15 09:59:46 +0000800
Tom Careb7042702010-06-09 04:11:11 +0000801 // Set conversion specifier and disable any flags which do not apply to it.
Ted Kremenek12a37de2010-10-21 04:00:58 +0000802 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
Jordan Rose6aaa87e2012-12-05 18:44:37 +0000803 if (!isa<TypedefType>(QT) && QT->isCharType()) {
Ted Kremenekab0fe8a2010-07-20 20:03:49 +0000804 CS.setKind(ConversionSpecifier::cArg);
Ted Kremenek12a37de2010-10-21 04:00:58 +0000805 LM.setKind(LengthModifier::None);
Tom Careb7042702010-06-09 04:11:11 +0000806 Precision.setHowSpecified(OptionalAmount::NotSpecified);
807 HasAlternativeForm = 0;
808 HasLeadingZeroes = 0;
Tom Careb49ec692010-06-17 19:00:27 +0000809 HasPlusPrefix = 0;
Tom Careb7042702010-06-09 04:11:11 +0000810 }
811 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
Douglas Gregor49b4d732010-06-22 23:07:26 +0000812 else if (QT->isRealFloatingType()) {
Tom Careb7042702010-06-09 04:11:11 +0000813 CS.setKind(ConversionSpecifier::fArg);
814 }
Tom Careb7042702010-06-09 04:11:11 +0000815 else if (QT->isSignedIntegerType()) {
816 CS.setKind(ConversionSpecifier::dArg);
817 HasAlternativeForm = 0;
818 }
Douglas Gregorb4e3533ce2010-06-09 05:25:34 +0000819 else if (QT->isUnsignedIntegerType()) {
Hans Wennborgd99d6882012-02-15 09:59:46 +0000820 CS.setKind(ConversionSpecifier::uArg);
Tom Careb7042702010-06-09 04:11:11 +0000821 HasAlternativeForm = 0;
Tom Careb49ec692010-06-17 19:00:27 +0000822 HasPlusPrefix = 0;
Chad Rosier6fdf38b2011-08-17 23:08:45 +0000823 } else {
David Blaikie83d382b2011-09-23 05:06:16 +0000824 llvm_unreachable("Unexpected type");
Tom Careb7042702010-06-09 04:11:11 +0000825 }
826
827 return true;
828}
829
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000830void PrintfSpecifier::toString(raw_ostream &os) const {
Tom Careb7042702010-06-09 04:11:11 +0000831 // Whilst some features have no defined order, we are using the order
NAKAMURA Takumi7c288862011-01-27 07:09:49 +0000832 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
Tom Careb7042702010-06-09 04:11:11 +0000833 os << "%";
834
835 // Positional args
836 if (usesPositionalArg()) {
837 os << getPositionalArgIndex() << "$";
838 }
839
840 // Conversion flags
841 if (IsLeftJustified) os << "-";
842 if (HasPlusPrefix) os << "+";
843 if (HasSpacePrefix) os << " ";
844 if (HasAlternativeForm) os << "#";
845 if (HasLeadingZeroes) os << "0";
846
847 // Minimum field width
848 FieldWidth.toString(os);
849 // Precision
850 Precision.toString(os);
851 // Length modifier
852 os << LM.toString();
853 // Conversion specifier
854 os << CS.toString();
855}
Tom Careb49ec692010-06-17 19:00:27 +0000856
Ted Kremenek02087932010-07-16 02:11:22 +0000857bool PrintfSpecifier::hasValidPlusPrefix() const {
Tom Careb49ec692010-06-17 19:00:27 +0000858 if (!HasPlusPrefix)
859 return true;
860
861 // The plus prefix only makes sense for signed conversions
862 switch (CS.getKind()) {
863 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000864 case ConversionSpecifier::DArg:
Tom Careb49ec692010-06-17 19:00:27 +0000865 case ConversionSpecifier::iArg:
866 case ConversionSpecifier::fArg:
867 case ConversionSpecifier::FArg:
868 case ConversionSpecifier::eArg:
869 case ConversionSpecifier::EArg:
870 case ConversionSpecifier::gArg:
871 case ConversionSpecifier::GArg:
872 case ConversionSpecifier::aArg:
873 case ConversionSpecifier::AArg:
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000874 case ConversionSpecifier::FreeBSDrArg:
875 case ConversionSpecifier::FreeBSDyArg:
Tom Careb49ec692010-06-17 19:00:27 +0000876 return true;
877
878 default:
879 return false;
880 }
881}
882
Ted Kremenek02087932010-07-16 02:11:22 +0000883bool PrintfSpecifier::hasValidAlternativeForm() const {
Tom Careb49ec692010-06-17 19:00:27 +0000884 if (!HasAlternativeForm)
885 return true;
886
Anders Carlssona369f8d2010-11-21 18:34:21 +0000887 // Alternate form flag only valid with the oxXaAeEfFgG conversions
Tom Careb49ec692010-06-17 19:00:27 +0000888 switch (CS.getKind()) {
889 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000890 case ConversionSpecifier::OArg:
Tom Careb49ec692010-06-17 19:00:27 +0000891 case ConversionSpecifier::xArg:
Anders Carlssona369f8d2010-11-21 18:34:21 +0000892 case ConversionSpecifier::XArg:
Tom Careb49ec692010-06-17 19:00:27 +0000893 case ConversionSpecifier::aArg:
894 case ConversionSpecifier::AArg:
895 case ConversionSpecifier::eArg:
896 case ConversionSpecifier::EArg:
897 case ConversionSpecifier::fArg:
898 case ConversionSpecifier::FArg:
899 case ConversionSpecifier::gArg:
900 case ConversionSpecifier::GArg:
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000901 case ConversionSpecifier::FreeBSDrArg:
902 case ConversionSpecifier::FreeBSDyArg:
Tom Careb49ec692010-06-17 19:00:27 +0000903 return true;
904
905 default:
906 return false;
907 }
908}
909
Ted Kremenek02087932010-07-16 02:11:22 +0000910bool PrintfSpecifier::hasValidLeadingZeros() const {
Tom Careb49ec692010-06-17 19:00:27 +0000911 if (!HasLeadingZeroes)
912 return true;
913
914 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
915 switch (CS.getKind()) {
916 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000917 case ConversionSpecifier::DArg:
Tom Careb49ec692010-06-17 19:00:27 +0000918 case ConversionSpecifier::iArg:
919 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000920 case ConversionSpecifier::OArg:
Tom Careb49ec692010-06-17 19:00:27 +0000921 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000922 case ConversionSpecifier::UArg:
Tom Careb49ec692010-06-17 19:00:27 +0000923 case ConversionSpecifier::xArg:
924 case ConversionSpecifier::XArg:
925 case ConversionSpecifier::aArg:
926 case ConversionSpecifier::AArg:
927 case ConversionSpecifier::eArg:
928 case ConversionSpecifier::EArg:
929 case ConversionSpecifier::fArg:
930 case ConversionSpecifier::FArg:
931 case ConversionSpecifier::gArg:
932 case ConversionSpecifier::GArg:
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000933 case ConversionSpecifier::FreeBSDrArg:
934 case ConversionSpecifier::FreeBSDyArg:
Tom Careb49ec692010-06-17 19:00:27 +0000935 return true;
936
937 default:
938 return false;
939 }
940}
941
Ted Kremenek02087932010-07-16 02:11:22 +0000942bool PrintfSpecifier::hasValidSpacePrefix() const {
Tom Careb49ec692010-06-17 19:00:27 +0000943 if (!HasSpacePrefix)
944 return true;
945
946 // The space prefix only makes sense for signed conversions
947 switch (CS.getKind()) {
948 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000949 case ConversionSpecifier::DArg:
Tom Careb49ec692010-06-17 19:00:27 +0000950 case ConversionSpecifier::iArg:
951 case ConversionSpecifier::fArg:
952 case ConversionSpecifier::FArg:
953 case ConversionSpecifier::eArg:
954 case ConversionSpecifier::EArg:
955 case ConversionSpecifier::gArg:
956 case ConversionSpecifier::GArg:
957 case ConversionSpecifier::aArg:
958 case ConversionSpecifier::AArg:
Dimitry Andric6b5ed342015-02-19 22:32:33 +0000959 case ConversionSpecifier::FreeBSDrArg:
960 case ConversionSpecifier::FreeBSDyArg:
Tom Careb49ec692010-06-17 19:00:27 +0000961 return true;
962
963 default:
964 return false;
965 }
966}
967
Ted Kremenek02087932010-07-16 02:11:22 +0000968bool PrintfSpecifier::hasValidLeftJustified() const {
Tom Careb49ec692010-06-17 19:00:27 +0000969 if (!IsLeftJustified)
970 return true;
971
972 // The left justified flag is valid for all conversions except n
973 switch (CS.getKind()) {
Ted Kremenek516ef222010-07-20 20:04:10 +0000974 case ConversionSpecifier::nArg:
Tom Careb49ec692010-06-17 19:00:27 +0000975 return false;
976
977 default:
978 return true;
979 }
980}
981
Ted Kremenekbf4832c2011-01-08 05:28:46 +0000982bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
983 if (!HasThousandsGrouping)
984 return true;
NAKAMURA Takumif9cbcc42011-01-27 07:10:08 +0000985
Ted Kremenekbf4832c2011-01-08 05:28:46 +0000986 switch (CS.getKind()) {
987 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000988 case ConversionSpecifier::DArg:
Ted Kremenekbf4832c2011-01-08 05:28:46 +0000989 case ConversionSpecifier::iArg:
990 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000991 case ConversionSpecifier::UArg:
Ted Kremenekbf4832c2011-01-08 05:28:46 +0000992 case ConversionSpecifier::fArg:
993 case ConversionSpecifier::FArg:
994 case ConversionSpecifier::gArg:
995 case ConversionSpecifier::GArg:
996 return true;
997 default:
998 return false;
999 }
1000}
1001
Ted Kremenek02087932010-07-16 02:11:22 +00001002bool PrintfSpecifier::hasValidPrecision() const {
Tom Careb49ec692010-06-17 19:00:27 +00001003 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1004 return true;
1005
Mehdi Amini06d367c2016-10-24 20:39:34 +00001006 // Precision is only valid with the diouxXaAeEfFgGsP conversions
Tom Careb49ec692010-06-17 19:00:27 +00001007 switch (CS.getKind()) {
1008 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +00001009 case ConversionSpecifier::DArg:
Tom Careb49ec692010-06-17 19:00:27 +00001010 case ConversionSpecifier::iArg:
1011 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +00001012 case ConversionSpecifier::OArg:
Tom Careb49ec692010-06-17 19:00:27 +00001013 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +00001014 case ConversionSpecifier::UArg:
Tom Careb49ec692010-06-17 19:00:27 +00001015 case ConversionSpecifier::xArg:
1016 case ConversionSpecifier::XArg:
1017 case ConversionSpecifier::aArg:
1018 case ConversionSpecifier::AArg:
1019 case ConversionSpecifier::eArg:
1020 case ConversionSpecifier::EArg:
1021 case ConversionSpecifier::fArg:
1022 case ConversionSpecifier::FArg:
1023 case ConversionSpecifier::gArg:
1024 case ConversionSpecifier::GArg:
Ted Kremenek563e3ed2010-07-20 20:03:58 +00001025 case ConversionSpecifier::sArg:
Dimitry Andric6b5ed342015-02-19 22:32:33 +00001026 case ConversionSpecifier::FreeBSDrArg:
1027 case ConversionSpecifier::FreeBSDyArg:
Mehdi Amini06d367c2016-10-24 20:39:34 +00001028 case ConversionSpecifier::PArg:
Tom Careb49ec692010-06-17 19:00:27 +00001029 return true;
1030
1031 default:
1032 return false;
1033 }
1034}
Ted Kremenek02087932010-07-16 02:11:22 +00001035bool PrintfSpecifier::hasValidFieldWidth() const {
Tom Careb49ec692010-06-17 19:00:27 +00001036 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1037 return true;
1038
1039 // The field width is valid for all conversions except n
1040 switch (CS.getKind()) {
Ted Kremenek516ef222010-07-20 20:04:10 +00001041 case ConversionSpecifier::nArg:
Tom Careb49ec692010-06-17 19:00:27 +00001042 return false;
1043
1044 default:
1045 return true;
1046 }
1047}